blob: a9cf45e3079717fac4404f04d27766444e14e0ba [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 Grobelnydcc4e192021-03-08 09:09:34 +000024{
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010025 readings = utils::transform(sensors, [this](const auto& sensor) {
26 return MetricValue{id, sensor->metadata(), 0.0, 0u};
27 });
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000028}
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010029
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +010030void Metric::registerForUpdates(interfaces::MetricListener& listener)
31{
32 listeners.emplace_back(listener);
33}
34
35void Metric::unregisterFromUpdates(interfaces::MetricListener& listener)
36{
37 listeners.erase(
38 std::remove_if(listeners.begin(), listeners.end(),
39 [&listener](const interfaces::MetricListener& item) {
40 return &item == &listener;
41 }),
42 listeners.end());
43}
Krzysztof Grobelny80697712021-03-04 09:49:27 +000044
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010045void Metric::initialize()
46{
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000047 for (const auto& sensor : sensors)
48 {
49 sensor->registerForUpdates(weak_from_this());
50 }
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010051}
52
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +020053void Metric::deinitialize()
54{
55 for (const auto& sensor : sensors)
56 {
57 sensor->unregisterFromUpdates(weak_from_this());
58 }
59}
60
Krzysztof Grobelny80697712021-03-04 09:49:27 +000061std::vector<MetricValue> Metric::getReadings() const
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010062{
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010063 const auto steadyTimestamp = clock->steadyTimestamp();
64 const auto systemTimestamp = clock->systemTimestamp();
65
Krzysztof Grobelny80697712021-03-04 09:49:27 +000066 auto resultReadings = readings;
67
68 for (size_t i = 0; i < resultReadings.size(); ++i)
69 {
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010070 if (const auto value = collectionAlgorithms[i]->update(steadyTimestamp))
71 {
72 resultReadings[i].timestamp =
73 std::chrono::duration_cast<Milliseconds>(systemTimestamp)
74 .count();
75 resultReadings[i].value = *value;
76 }
Krzysztof Grobelny80697712021-03-04 09:49:27 +000077 }
78
79 return resultReadings;
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010080}
81
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010082void Metric::sensorUpdated(interfaces::Sensor& notifier, Milliseconds timestamp,
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010083 double value)
84{
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +010085 auto& data = findAssociatedData(notifier);
86 double newValue = data.update(timestamp, value);
87
88 if (data.updateLastValue(newValue))
89 {
90 for (interfaces::MetricListener& listener : listeners)
91 {
92 listener.metricUpdated();
93 }
94 }
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010095}
96
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +010097metrics::CollectionData&
Krzysztof Grobelny80697712021-03-04 09:49:27 +000098 Metric::findAssociatedData(const interfaces::Sensor& notifier)
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010099{
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000100 auto it = std::find_if(
101 sensors.begin(), sensors.end(),
102 [&notifier](const auto& sensor) { return sensor.get() == &notifier; });
103 auto index = std::distance(sensors.begin(), it);
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000104 return *collectionAlgorithms.at(index);
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100105}
106
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000107LabeledMetricParameters Metric::dumpConfiguration() const
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100108{
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000109 auto sensorPath = utils::transform(sensors, [this](const auto& sensor) {
Szymon Dompke94f71c52021-12-10 07:16:33 +0100110 return LabeledSensorInfo(sensor->id().service, sensor->id().path,
111 sensor->metadata());
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000112 });
113
114 return LabeledMetricParameters(std::move(sensorPath), operationType, id,
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100115 collectionTimeScope, collectionDuration);
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000116}
117
Szymon Dompke3eb56862021-09-20 15:32:04 +0200118uint64_t Metric::sensorCount() const
119{
120 return sensors.size();
121}
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +0100122
123void Metric::updateReadings(Milliseconds timestamp)
124{
125 for (auto& data : collectionAlgorithms)
126 {
127 if (std::optional<double> newValue = data->update(timestamp))
128 {
129 if (data->updateLastValue(*newValue))
130 {
131 for (interfaces::MetricListener& listener : listeners)
132 {
133 listener.metricUpdated();
134 }
135 return;
136 }
137 }
138 }
139}
140
141bool Metric::isTimerRequired() const
142{
143 if (collectionTimeScope == CollectionTimeScope::point)
144 {
145 return false;
146 }
147
148 if (collectionTimeScope == CollectionTimeScope::startup &&
149 (operationType == OperationType::min ||
150 operationType == OperationType::max))
151 {
152 return false;
153 }
154
155 return true;
156}