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 [¬ifier](const auto& sensor) { return sensor.get() == ¬ifier; });
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