blob: c1c5fd20c3a026471d5d54a13488c1801a85479d [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) :
Patrick Williamsf535cad2024-08-16 15:21:20 -040017 sensors(std::move(sensorsIn)), operationType(operationTypeIn),
18 collectionTimeScope(timeScopeIn), collectionDuration(collectionDurationIn),
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +010019 collectionAlgorithms(
20 metrics::makeCollectionData(sensors.size(), operationType,
21 collectionTimeScope, collectionDuration)),
Krzysztof Grobelny80697712021-03-04 09:49:27 +000022 clock(std::move(clockIn))
Krzysztof Grobelny9e8da542022-02-17 10:40:16 +010023{}
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010024
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +010025void Metric::registerForUpdates(interfaces::MetricListener& listener)
26{
27 listeners.emplace_back(listener);
28}
29
30void Metric::unregisterFromUpdates(interfaces::MetricListener& listener)
31{
Patrick Williamsc7935fa2023-10-20 11:19:30 -050032 listeners.erase(
33 std::remove_if(listeners.begin(), listeners.end(),
34 [&listener](const interfaces::MetricListener& item) {
Patrick Williams3a1c2972023-05-10 07:51:04 -050035 return &item == &listener;
Patrick Williamsc7935fa2023-10-20 11:19:30 -050036 }),
37 listeners.end());
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +010038}
Krzysztof Grobelny80697712021-03-04 09:49:27 +000039
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010040void Metric::initialize()
41{
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000042 for (const auto& sensor : sensors)
43 {
44 sensor->registerForUpdates(weak_from_this());
45 }
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010046}
47
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +020048void Metric::deinitialize()
49{
50 for (const auto& sensor : sensors)
51 {
52 sensor->unregisterFromUpdates(weak_from_this());
53 }
54}
55
Krzysztof Grobelny9e8da542022-02-17 10:40:16 +010056const std::vector<MetricValue>& Metric::getUpdatedReadings()
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010057{
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010058 const auto steadyTimestamp = clock->steadyTimestamp();
Krzysztof Grobelny9e8da542022-02-17 10:40:16 +010059 const auto systemTimestamp =
60 std::chrono::duration_cast<Milliseconds>(clock->systemTimestamp())
61 .count();
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010062
Krzysztof Grobelny9e8da542022-02-17 10:40:16 +010063 for (size_t i = 0; i < collectionAlgorithms.size(); ++i)
Krzysztof Grobelny80697712021-03-04 09:49:27 +000064 {
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010065 if (const auto value = collectionAlgorithms[i]->update(steadyTimestamp))
66 {
Krzysztof Grobelny9e8da542022-02-17 10:40:16 +010067 if (i < readings.size())
68 {
69 readings[i].timestamp = systemTimestamp;
70 readings[i].value = *value;
71 }
72 else
73 {
74 if (i > readings.size())
75 {
76 const auto idx = readings.size();
77 std::swap(collectionAlgorithms[i],
78 collectionAlgorithms[idx]);
79 std::swap(sensors[i], sensors[idx]);
80 i = idx;
81 }
82
Krzysztof Grobelnycff70c12022-10-27 07:16:08 +000083 readings.emplace_back(sensors[i]->metadata(), *value,
Krzysztof Grobelny9e8da542022-02-17 10:40:16 +010084 systemTimestamp);
85 }
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010086 }
Krzysztof Grobelny80697712021-03-04 09:49:27 +000087 }
88
Krzysztof Grobelny9e8da542022-02-17 10:40:16 +010089 return readings;
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010090}
91
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010092void Metric::sensorUpdated(interfaces::Sensor& notifier, Milliseconds timestamp,
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010093 double value)
94{
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +010095 auto& data = findAssociatedData(notifier);
96 double newValue = data.update(timestamp, value);
97
98 if (data.updateLastValue(newValue))
99 {
100 for (interfaces::MetricListener& listener : listeners)
101 {
102 listener.metricUpdated();
103 }
104 }
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100105}
106
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +0100107metrics::CollectionData&
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000108 Metric::findAssociatedData(const interfaces::Sensor& notifier)
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100109{
Patrick Williamsc7935fa2023-10-20 11:19:30 -0500110 auto it = std::find_if(
111 sensors.begin(), sensors.end(),
112 [&notifier](const auto& sensor) { return sensor.get() == &notifier; });
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000113 auto index = std::distance(sensors.begin(), it);
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000114 return *collectionAlgorithms.at(index);
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100115}
116
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000117LabeledMetricParameters Metric::dumpConfiguration() const
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100118{
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000119 auto sensorPath = utils::transform(sensors, [this](const auto& sensor) {
Szymon Dompke94f71c52021-12-10 07:16:33 +0100120 return LabeledSensorInfo(sensor->id().service, sensor->id().path,
121 sensor->metadata());
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000122 });
123
Krzysztof Grobelnycff70c12022-10-27 07:16:08 +0000124 return LabeledMetricParameters(std::move(sensorPath), operationType,
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100125 collectionTimeScope, collectionDuration);
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000126}
127
Krzysztof Grobelny18e71012022-11-02 13:17:01 +0000128uint64_t Metric::metricCount() const
Szymon Dompke3eb56862021-09-20 15:32:04 +0200129{
130 return sensors.size();
131}
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +0100132
133void Metric::updateReadings(Milliseconds timestamp)
134{
135 for (auto& data : collectionAlgorithms)
136 {
137 if (std::optional<double> newValue = data->update(timestamp))
138 {
139 if (data->updateLastValue(*newValue))
140 {
141 for (interfaces::MetricListener& listener : listeners)
142 {
143 listener.metricUpdated();
144 }
145 return;
146 }
147 }
148 }
149}
150
151bool Metric::isTimerRequired() const
152{
153 if (collectionTimeScope == CollectionTimeScope::point)
154 {
155 return false;
156 }
157
158 if (collectionTimeScope == CollectionTimeScope::startup &&
159 (operationType == OperationType::min ||
160 operationType == OperationType::max))
161 {
162 return false;
163 }
164
165 return true;
166}