1 #include "metric.hpp"
2
3 #include "metrics/collection_data.hpp"
4 #include "types/report_types.hpp"
5 #include "types/sensor_types.hpp"
6 #include "utils/labeled_tuple.hpp"
7 #include "utils/transform.hpp"
8
9 #include <sdbusplus/exception.hpp>
10
11 #include <algorithm>
12
Metric(Sensors sensorsIn,OperationType operationTypeIn,CollectionTimeScope timeScopeIn,CollectionDuration collectionDurationIn,std::unique_ptr<interfaces::Clock> clockIn)13 Metric::Metric(Sensors sensorsIn, OperationType operationTypeIn,
14 CollectionTimeScope timeScopeIn,
15 CollectionDuration collectionDurationIn,
16 std::unique_ptr<interfaces::Clock> clockIn) :
17 sensors(std::move(sensorsIn)), operationType(operationTypeIn),
18 collectionTimeScope(timeScopeIn), collectionDuration(collectionDurationIn),
19 collectionAlgorithms(
20 metrics::makeCollectionData(sensors.size(), operationType,
21 collectionTimeScope, collectionDuration)),
22 clock(std::move(clockIn))
23 {}
24
registerForUpdates(interfaces::MetricListener & listener)25 void Metric::registerForUpdates(interfaces::MetricListener& listener)
26 {
27 listeners.emplace_back(listener);
28 }
29
unregisterFromUpdates(interfaces::MetricListener & listener)30 void Metric::unregisterFromUpdates(interfaces::MetricListener& listener)
31 {
32 listeners.erase(
33 std::remove_if(listeners.begin(), listeners.end(),
34 [&listener](const interfaces::MetricListener& item) {
35 return &item == &listener;
36 }),
37 listeners.end());
38 }
39
initialize()40 void Metric::initialize()
41 {
42 for (const auto& sensor : sensors)
43 {
44 sensor->registerForUpdates(weak_from_this());
45 }
46 }
47
deinitialize()48 void Metric::deinitialize()
49 {
50 for (const auto& sensor : sensors)
51 {
52 sensor->unregisterFromUpdates(weak_from_this());
53 }
54 }
55
getUpdatedReadings()56 const std::vector<MetricValue>& Metric::getUpdatedReadings()
57 {
58 const auto steadyTimestamp = clock->steadyTimestamp();
59 const auto systemTimestamp =
60 std::chrono::duration_cast<Milliseconds>(clock->systemTimestamp())
61 .count();
62
63 for (size_t i = 0; i < collectionAlgorithms.size(); ++i)
64 {
65 if (const auto value = collectionAlgorithms[i]->update(steadyTimestamp))
66 {
67 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
83 readings.emplace_back(sensors[i]->metadata(), *value,
84 systemTimestamp);
85 }
86 }
87 }
88
89 return readings;
90 }
91
sensorUpdated(interfaces::Sensor & notifier,Milliseconds timestamp,double value)92 void Metric::sensorUpdated(interfaces::Sensor& notifier, Milliseconds timestamp,
93 double value)
94 {
95 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 }
105 }
106
107 metrics::CollectionData&
findAssociatedData(const interfaces::Sensor & notifier)108 Metric::findAssociatedData(const interfaces::Sensor& notifier)
109 {
110 auto it = std::find_if(
111 sensors.begin(), sensors.end(),
112 [¬ifier](const auto& sensor) { return sensor.get() == ¬ifier; });
113 auto index = std::distance(sensors.begin(), it);
114 return *collectionAlgorithms.at(index);
115 }
116
dumpConfiguration() const117 LabeledMetricParameters Metric::dumpConfiguration() const
118 {
119 auto sensorPath = utils::transform(sensors, [this](const auto& sensor) {
120 return LabeledSensorInfo(sensor->id().service, sensor->id().path,
121 sensor->metadata());
122 });
123
124 return LabeledMetricParameters(std::move(sensorPath), operationType,
125 collectionTimeScope, collectionDuration);
126 }
127
metricCount() const128 uint64_t Metric::metricCount() const
129 {
130 return sensors.size();
131 }
132
updateReadings(Milliseconds timestamp)133 void 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
isTimerRequired() const151 bool 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 }
167