blob: 9350099e1a1b8d5006f0e88e9c572da8d457532e [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 Grobelnycff70c12022-10-27 07:16:08 +000014 CollectionTimeScope timeScopeIn,
Krzysztof Grobelny80697712021-03-04 09:49:27 +000015 CollectionDuration collectionDurationIn,
16 std::unique_ptr<interfaces::Clock> clockIn) :
Krzysztof Grobelnycff70c12022-10-27 07:16:08 +000017 sensors(std::move(sensorsIn)),
18 operationType(operationTypeIn), collectionTimeScope(timeScopeIn),
19 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{
Patrick Williams3a1c2972023-05-10 07:51:04 -050033 listeners.erase(std::remove_if(
34 listeners.begin(), listeners.end(),
35 [&listener](const interfaces::MetricListener& item) {
36 return &item == &listener;
37 }),
38 listeners.end());
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +010039}
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
Krzysztof Grobelnycff70c12022-10-27 07:16:08 +000084 readings.emplace_back(sensors[i]->metadata(), *value,
Krzysztof Grobelny9e8da542022-02-17 10:40:16 +010085 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{
Patrick Williams3a1c2972023-05-10 07:51:04 -0500111 auto it = std::find_if(sensors.begin(), sensors.end(),
112 [&notifier](const auto& sensor) {
113 return sensor.get() == &notifier;
114 });
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000115 auto index = std::distance(sensors.begin(), it);
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000116 return *collectionAlgorithms.at(index);
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100117}
118
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000119LabeledMetricParameters Metric::dumpConfiguration() const
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100120{
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000121 auto sensorPath = utils::transform(sensors, [this](const auto& sensor) {
Szymon Dompke94f71c52021-12-10 07:16:33 +0100122 return LabeledSensorInfo(sensor->id().service, sensor->id().path,
123 sensor->metadata());
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000124 });
125
Krzysztof Grobelnycff70c12022-10-27 07:16:08 +0000126 return LabeledMetricParameters(std::move(sensorPath), operationType,
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100127 collectionTimeScope, collectionDuration);
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000128}
129
Krzysztof Grobelny18e71012022-11-02 13:17:01 +0000130uint64_t Metric::metricCount() const
Szymon Dompke3eb56862021-09-20 15:32:04 +0200131{
132 return sensors.size();
133}
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +0100134
135void Metric::updateReadings(Milliseconds timestamp)
136{
137 for (auto& data : collectionAlgorithms)
138 {
139 if (std::optional<double> newValue = data->update(timestamp))
140 {
141 if (data->updateLastValue(*newValue))
142 {
143 for (interfaces::MetricListener& listener : listeners)
144 {
145 listener.metricUpdated();
146 }
147 return;
148 }
149 }
150 }
151}
152
153bool Metric::isTimerRequired() const
154{
155 if (collectionTimeScope == CollectionTimeScope::point)
156 {
157 return false;
158 }
159
160 if (collectionTimeScope == CollectionTimeScope::startup &&
161 (operationType == OperationType::min ||
162 operationType == OperationType::max))
163 {
164 return false;
165 }
166
167 return true;
168}