xref: /openbmc/telemetry/src/metric.cpp (revision f535cad6545d39fe58f50d0f23074359f43f8a03)
1c8e3a64aSKrzysztof Grobelny #include "metric.hpp"
26ccfcbf5SKrzysztof Grobelny 
3f7ea2997SKrzysztof Grobelny #include "metrics/collection_data.hpp"
4dcc4e193SKrzysztof Grobelny #include "types/report_types.hpp"
594f71c51SSzymon Dompke #include "types/sensor_types.hpp"
63a617023SSzymon Dompke #include "utils/labeled_tuple.hpp"
76ccfcbf5SKrzysztof Grobelny #include "utils/transform.hpp"
86ccfcbf5SKrzysztof Grobelny 
9b8cc78ddSKrzysztof Grobelny #include <sdbusplus/exception.hpp>
10b8cc78ddSKrzysztof Grobelny 
116ccfcbf5SKrzysztof Grobelny #include <algorithm>
126ccfcbf5SKrzysztof Grobelny 
Metric(Sensors sensorsIn,OperationType operationTypeIn,CollectionTimeScope timeScopeIn,CollectionDuration collectionDurationIn,std::unique_ptr<interfaces::Clock> clockIn)13dcc4e193SKrzysztof Grobelny Metric::Metric(Sensors sensorsIn, OperationType operationTypeIn,
14cff70c14SKrzysztof Grobelny                CollectionTimeScope timeScopeIn,
158069771cSKrzysztof Grobelny                CollectionDuration collectionDurationIn,
168069771cSKrzysztof Grobelny                std::unique_ptr<interfaces::Clock> clockIn) :
17*f535cad6SPatrick Williams     sensors(std::move(sensorsIn)), operationType(operationTypeIn),
18*f535cad6SPatrick Williams     collectionTimeScope(timeScopeIn), collectionDuration(collectionDurationIn),
19f7ea2997SKrzysztof Grobelny     collectionAlgorithms(
20f7ea2997SKrzysztof Grobelny         metrics::makeCollectionData(sensors.size(), operationType,
21f7ea2997SKrzysztof Grobelny                                     collectionTimeScope, collectionDuration)),
228069771cSKrzysztof Grobelny     clock(std::move(clockIn))
239e8da546SKrzysztof Grobelny {}
246ccfcbf5SKrzysztof Grobelny 
registerForUpdates(interfaces::MetricListener & listener)25f7ea2997SKrzysztof Grobelny void Metric::registerForUpdates(interfaces::MetricListener& listener)
26f7ea2997SKrzysztof Grobelny {
27f7ea2997SKrzysztof Grobelny     listeners.emplace_back(listener);
28f7ea2997SKrzysztof Grobelny }
29f7ea2997SKrzysztof Grobelny 
unregisterFromUpdates(interfaces::MetricListener & listener)30f7ea2997SKrzysztof Grobelny void Metric::unregisterFromUpdates(interfaces::MetricListener& listener)
31f7ea2997SKrzysztof Grobelny {
32c7935fa1SPatrick Williams     listeners.erase(
33c7935fa1SPatrick Williams         std::remove_if(listeners.begin(), listeners.end(),
34f7ea2997SKrzysztof Grobelny                        [&listener](const interfaces::MetricListener& item) {
35f7ea2997SKrzysztof Grobelny         return &item == &listener;
36f7ea2997SKrzysztof Grobelny     }),
37f7ea2997SKrzysztof Grobelny         listeners.end());
38f7ea2997SKrzysztof Grobelny }
398069771cSKrzysztof Grobelny 
initialize()406ccfcbf5SKrzysztof Grobelny void Metric::initialize()
416ccfcbf5SKrzysztof Grobelny {
42dcc4e193SKrzysztof Grobelny     for (const auto& sensor : sensors)
43dcc4e193SKrzysztof Grobelny     {
446ccfcbf5SKrzysztof Grobelny         sensor->registerForUpdates(weak_from_this());
456ccfcbf5SKrzysztof Grobelny     }
46dcc4e193SKrzysztof Grobelny }
47e8fc5751SKrzysztof Grobelny 
deinitialize()487e098e93SLukasz Kazmierczak void Metric::deinitialize()
497e098e93SLukasz Kazmierczak {
507e098e93SLukasz Kazmierczak     for (const auto& sensor : sensors)
517e098e93SLukasz Kazmierczak     {
527e098e93SLukasz Kazmierczak         sensor->unregisterFromUpdates(weak_from_this());
537e098e93SLukasz Kazmierczak     }
547e098e93SLukasz Kazmierczak }
557e098e93SLukasz Kazmierczak 
getUpdatedReadings()569e8da546SKrzysztof Grobelny const std::vector<MetricValue>& Metric::getUpdatedReadings()
57e8fc5751SKrzysztof Grobelny {
5851f0fd50SKrzysztof Grobelny     const auto steadyTimestamp = clock->steadyTimestamp();
599e8da546SKrzysztof Grobelny     const auto systemTimestamp =
609e8da546SKrzysztof Grobelny         std::chrono::duration_cast<Milliseconds>(clock->systemTimestamp())
619e8da546SKrzysztof Grobelny             .count();
6251f0fd50SKrzysztof Grobelny 
639e8da546SKrzysztof Grobelny     for (size_t i = 0; i < collectionAlgorithms.size(); ++i)
648069771cSKrzysztof Grobelny     {
6551f0fd50SKrzysztof Grobelny         if (const auto value = collectionAlgorithms[i]->update(steadyTimestamp))
6651f0fd50SKrzysztof Grobelny         {
679e8da546SKrzysztof Grobelny             if (i < readings.size())
689e8da546SKrzysztof Grobelny             {
699e8da546SKrzysztof Grobelny                 readings[i].timestamp = systemTimestamp;
709e8da546SKrzysztof Grobelny                 readings[i].value = *value;
719e8da546SKrzysztof Grobelny             }
729e8da546SKrzysztof Grobelny             else
739e8da546SKrzysztof Grobelny             {
749e8da546SKrzysztof Grobelny                 if (i > readings.size())
759e8da546SKrzysztof Grobelny                 {
769e8da546SKrzysztof Grobelny                     const auto idx = readings.size();
779e8da546SKrzysztof Grobelny                     std::swap(collectionAlgorithms[i],
789e8da546SKrzysztof Grobelny                               collectionAlgorithms[idx]);
799e8da546SKrzysztof Grobelny                     std::swap(sensors[i], sensors[idx]);
809e8da546SKrzysztof Grobelny                     i = idx;
819e8da546SKrzysztof Grobelny                 }
829e8da546SKrzysztof Grobelny 
83cff70c14SKrzysztof Grobelny                 readings.emplace_back(sensors[i]->metadata(), *value,
849e8da546SKrzysztof Grobelny                                       systemTimestamp);
859e8da546SKrzysztof Grobelny             }
8651f0fd50SKrzysztof Grobelny         }
878069771cSKrzysztof Grobelny     }
888069771cSKrzysztof Grobelny 
899e8da546SKrzysztof Grobelny     return readings;
906ccfcbf5SKrzysztof Grobelny }
916ccfcbf5SKrzysztof Grobelny 
sensorUpdated(interfaces::Sensor & notifier,Milliseconds timestamp,double value)9251f0fd50SKrzysztof Grobelny void Metric::sensorUpdated(interfaces::Sensor& notifier, Milliseconds timestamp,
936ccfcbf5SKrzysztof Grobelny                            double value)
946ccfcbf5SKrzysztof Grobelny {
95f7ea2997SKrzysztof Grobelny     auto& data = findAssociatedData(notifier);
96f7ea2997SKrzysztof Grobelny     double newValue = data.update(timestamp, value);
97f7ea2997SKrzysztof Grobelny 
98f7ea2997SKrzysztof Grobelny     if (data.updateLastValue(newValue))
99f7ea2997SKrzysztof Grobelny     {
100f7ea2997SKrzysztof Grobelny         for (interfaces::MetricListener& listener : listeners)
101f7ea2997SKrzysztof Grobelny         {
102f7ea2997SKrzysztof Grobelny             listener.metricUpdated();
103f7ea2997SKrzysztof Grobelny         }
104f7ea2997SKrzysztof Grobelny     }
1056ccfcbf5SKrzysztof Grobelny }
1066ccfcbf5SKrzysztof Grobelny 
107f7ea2997SKrzysztof Grobelny metrics::CollectionData&
findAssociatedData(const interfaces::Sensor & notifier)1088069771cSKrzysztof Grobelny     Metric::findAssociatedData(const interfaces::Sensor& notifier)
1096ccfcbf5SKrzysztof Grobelny {
110c7935fa1SPatrick Williams     auto it = std::find_if(
111c7935fa1SPatrick Williams         sensors.begin(), sensors.end(),
112c7935fa1SPatrick Williams         [&notifier](const auto& sensor) { return sensor.get() == &notifier; });
113dcc4e193SKrzysztof Grobelny     auto index = std::distance(sensors.begin(), it);
1148069771cSKrzysztof Grobelny     return *collectionAlgorithms.at(index);
1156ccfcbf5SKrzysztof Grobelny }
1166ccfcbf5SKrzysztof Grobelny 
dumpConfiguration() const117d2238194SKrzysztof Grobelny LabeledMetricParameters Metric::dumpConfiguration() const
1186ccfcbf5SKrzysztof Grobelny {
119dcc4e193SKrzysztof Grobelny     auto sensorPath = utils::transform(sensors, [this](const auto& sensor) {
12094f71c51SSzymon Dompke         return LabeledSensorInfo(sensor->id().service, sensor->id().path,
121b8cc78ddSKrzysztof Grobelny                                  sensor->metadata());
122dcc4e193SKrzysztof Grobelny     });
123dcc4e193SKrzysztof Grobelny 
124cff70c14SKrzysztof Grobelny     return LabeledMetricParameters(std::move(sensorPath), operationType,
125b8cc78ddSKrzysztof Grobelny                                    collectionTimeScope, collectionDuration);
126dcc4e193SKrzysztof Grobelny }
127dcc4e193SKrzysztof Grobelny 
metricCount() const12818e7101cSKrzysztof Grobelny uint64_t Metric::metricCount() const
1293eb56865SSzymon Dompke {
1303eb56865SSzymon Dompke     return sensors.size();
1313eb56865SSzymon Dompke }
132f7ea2997SKrzysztof Grobelny 
updateReadings(Milliseconds timestamp)133f7ea2997SKrzysztof Grobelny void Metric::updateReadings(Milliseconds timestamp)
134f7ea2997SKrzysztof Grobelny {
135f7ea2997SKrzysztof Grobelny     for (auto& data : collectionAlgorithms)
136f7ea2997SKrzysztof Grobelny     {
137f7ea2997SKrzysztof Grobelny         if (std::optional<double> newValue = data->update(timestamp))
138f7ea2997SKrzysztof Grobelny         {
139f7ea2997SKrzysztof Grobelny             if (data->updateLastValue(*newValue))
140f7ea2997SKrzysztof Grobelny             {
141f7ea2997SKrzysztof Grobelny                 for (interfaces::MetricListener& listener : listeners)
142f7ea2997SKrzysztof Grobelny                 {
143f7ea2997SKrzysztof Grobelny                     listener.metricUpdated();
144f7ea2997SKrzysztof Grobelny                 }
145f7ea2997SKrzysztof Grobelny                 return;
146f7ea2997SKrzysztof Grobelny             }
147f7ea2997SKrzysztof Grobelny         }
148f7ea2997SKrzysztof Grobelny     }
149f7ea2997SKrzysztof Grobelny }
150f7ea2997SKrzysztof Grobelny 
isTimerRequired() const151f7ea2997SKrzysztof Grobelny bool Metric::isTimerRequired() const
152f7ea2997SKrzysztof Grobelny {
153f7ea2997SKrzysztof Grobelny     if (collectionTimeScope == CollectionTimeScope::point)
154f7ea2997SKrzysztof Grobelny     {
155f7ea2997SKrzysztof Grobelny         return false;
156f7ea2997SKrzysztof Grobelny     }
157f7ea2997SKrzysztof Grobelny 
158f7ea2997SKrzysztof Grobelny     if (collectionTimeScope == CollectionTimeScope::startup &&
159f7ea2997SKrzysztof Grobelny         (operationType == OperationType::min ||
160f7ea2997SKrzysztof Grobelny          operationType == OperationType::max))
161f7ea2997SKrzysztof Grobelny     {
162f7ea2997SKrzysztof Grobelny         return false;
163f7ea2997SKrzysztof Grobelny     }
164f7ea2997SKrzysztof Grobelny 
165f7ea2997SKrzysztof Grobelny     return true;
166f7ea2997SKrzysztof Grobelny }
167