blob: f7a0642adaa6f83217094720cef3290d433ecb21 [file] [log] [blame]
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +02001#include "metric.hpp"
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +01002
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +01003#include "metrics/collection_data.hpp"
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +00004#include "types/report_types.hpp"
Szymon Dompke94f71c52021-12-10 07:16:33 +01005#include "types/sensor_types.hpp"
Szymon Dompke3a617022021-07-19 18:23:02 +02006#include "utils/labeled_tuple.hpp"
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +01007#include "utils/transform.hpp"
8
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +01009#include <sdbusplus/exception.hpp>
10
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010011#include <algorithm>
12
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000013Metric::Metric(Sensors sensorsIn, OperationType operationTypeIn,
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010014 std::string idIn, CollectionTimeScope timeScopeIn,
Krzysztof Grobelny80697712021-03-04 09:49:27 +000015 CollectionDuration collectionDurationIn,
16 std::unique_ptr<interfaces::Clock> clockIn) :
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010017 id(std::move(idIn)),
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000018 sensors(std::move(sensorsIn)), operationType(operationTypeIn),
Krzysztof Grobelny80697712021-03-04 09:49:27 +000019 collectionTimeScope(timeScopeIn), collectionDuration(collectionDurationIn),
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +010020 collectionAlgorithms(
21 metrics::makeCollectionData(sensors.size(), operationType,
22 collectionTimeScope, collectionDuration)),
Krzysztof Grobelny80697712021-03-04 09:49:27 +000023 clock(std::move(clockIn))
Krzysztof Grobelny9e8da542022-02-17 10:40:16 +010024{}
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010025
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +010026void Metric::registerForUpdates(interfaces::MetricListener& listener)
27{
28 listeners.emplace_back(listener);
29}
30
31void Metric::unregisterFromUpdates(interfaces::MetricListener& listener)
32{
33 listeners.erase(
34 std::remove_if(listeners.begin(), listeners.end(),
35 [&listener](const interfaces::MetricListener& item) {
36 return &item == &listener;
37 }),
38 listeners.end());
39}
Krzysztof Grobelny80697712021-03-04 09:49:27 +000040
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010041void Metric::initialize()
42{
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000043 for (const auto& sensor : sensors)
44 {
45 sensor->registerForUpdates(weak_from_this());
46 }
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010047}
48
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +020049void Metric::deinitialize()
50{
51 for (const auto& sensor : sensors)
52 {
53 sensor->unregisterFromUpdates(weak_from_this());
54 }
55}
56
Krzysztof Grobelny9e8da542022-02-17 10:40:16 +010057const std::vector<MetricValue>& Metric::getUpdatedReadings()
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010058{
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010059 const auto steadyTimestamp = clock->steadyTimestamp();
Krzysztof Grobelny9e8da542022-02-17 10:40:16 +010060 const auto systemTimestamp =
61 std::chrono::duration_cast<Milliseconds>(clock->systemTimestamp())
62 .count();
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010063
Krzysztof Grobelny9e8da542022-02-17 10:40:16 +010064 for (size_t i = 0; i < collectionAlgorithms.size(); ++i)
Krzysztof Grobelny80697712021-03-04 09:49:27 +000065 {
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010066 if (const auto value = collectionAlgorithms[i]->update(steadyTimestamp))
67 {
Krzysztof Grobelny9e8da542022-02-17 10:40:16 +010068 if (i < readings.size())
69 {
70 readings[i].timestamp = systemTimestamp;
71 readings[i].value = *value;
72 }
73 else
74 {
75 if (i > readings.size())
76 {
77 const auto idx = readings.size();
78 std::swap(collectionAlgorithms[i],
79 collectionAlgorithms[idx]);
80 std::swap(sensors[i], sensors[idx]);
81 i = idx;
82 }
83
84 readings.emplace_back(id, sensors[i]->metadata(), *value,
85 systemTimestamp);
86 }
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010087 }
Krzysztof Grobelny80697712021-03-04 09:49:27 +000088 }
89
Krzysztof Grobelny9e8da542022-02-17 10:40:16 +010090 return readings;
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010091}
92
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010093void Metric::sensorUpdated(interfaces::Sensor& notifier, Milliseconds timestamp,
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010094 double value)
95{
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +010096 auto& data = findAssociatedData(notifier);
97 double newValue = data.update(timestamp, value);
98
99 if (data.updateLastValue(newValue))
100 {
101 for (interfaces::MetricListener& listener : listeners)
102 {
103 listener.metricUpdated();
104 }
105 }
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100106}
107
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +0100108metrics::CollectionData&
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000109 Metric::findAssociatedData(const interfaces::Sensor& notifier)
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100110{
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000111 auto it = std::find_if(
112 sensors.begin(), sensors.end(),
113 [&notifier](const auto& sensor) { return sensor.get() == &notifier; });
114 auto index = std::distance(sensors.begin(), it);
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000115 return *collectionAlgorithms.at(index);
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100116}
117
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000118LabeledMetricParameters Metric::dumpConfiguration() const
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100119{
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000120 auto sensorPath = utils::transform(sensors, [this](const auto& sensor) {
Szymon Dompke94f71c52021-12-10 07:16:33 +0100121 return LabeledSensorInfo(sensor->id().service, sensor->id().path,
122 sensor->metadata());
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000123 });
124
125 return LabeledMetricParameters(std::move(sensorPath), operationType, id,
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100126 collectionTimeScope, collectionDuration);
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000127}
128
Krzysztof Grobelny18e71012022-11-02 13:17:01 +0000129uint64_t Metric::metricCount() const
Szymon Dompke3eb56862021-09-20 15:32:04 +0200130{
131 return sensors.size();
132}
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +0100133
134void Metric::updateReadings(Milliseconds timestamp)
135{
136 for (auto& data : collectionAlgorithms)
137 {
138 if (std::optional<double> newValue = data->update(timestamp))
139 {
140 if (data->updateLastValue(*newValue))
141 {
142 for (interfaces::MetricListener& listener : listeners)
143 {
144 listener.metricUpdated();
145 }
146 return;
147 }
148 }
149 }
150}
151
152bool Metric::isTimerRequired() const
153{
154 if (collectionTimeScope == CollectionTimeScope::point)
155 {
156 return false;
157 }
158
159 if (collectionTimeScope == CollectionTimeScope::startup &&
160 (operationType == OperationType::min ||
161 operationType == OperationType::max))
162 {
163 return false;
164 }
165
166 return true;
167}