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)),
18 operationType(operationTypeIn), collectionTimeScope(timeScopeIn),
19 collectionDuration(collectionDurationIn),
20 collectionAlgorithms(
21 metrics::makeCollectionData(sensors.size(), operationType,
22 collectionTimeScope, collectionDuration)),
23 clock(std::move(clockIn))
24 {}
25
registerForUpdates(interfaces::MetricListener & listener)26 void Metric::registerForUpdates(interfaces::MetricListener& listener)
27 {
28 listeners.emplace_back(listener);
29 }
30
unregisterFromUpdates(interfaces::MetricListener & listener)31 void Metric::unregisterFromUpdates(interfaces::MetricListener& listener)
32 {
33 listeners.erase(
34 std::remove_if(listeners.begin(), listeners.end(),
35 [&listener](const interfaces::MetricListener& item) {
36 return &item == &listener;
37 }),
38 listeners.end());
39 }
40
initialize()41 void Metric::initialize()
42 {
43 for (const auto& sensor : sensors)
44 {
45 sensor->registerForUpdates(weak_from_this());
46 }
47 }
48
deinitialize()49 void Metric::deinitialize()
50 {
51 for (const auto& sensor : sensors)
52 {
53 sensor->unregisterFromUpdates(weak_from_this());
54 }
55 }
56
getUpdatedReadings()57 const std::vector<MetricValue>& Metric::getUpdatedReadings()
58 {
59 const auto steadyTimestamp = clock->steadyTimestamp();
60 const auto systemTimestamp =
61 std::chrono::duration_cast<Milliseconds>(clock->systemTimestamp())
62 .count();
63
64 for (size_t i = 0; i < collectionAlgorithms.size(); ++i)
65 {
66 if (const auto value = collectionAlgorithms[i]->update(steadyTimestamp))
67 {
68 if (i < readings.size())
69 {
70 readings[i].timestamp = systemTimestamp;
71 readings[i].value = *value;
72 }
73 else
74 {
75 if (i > readings.size())
76 {
77 const auto idx = readings.size();
78 std::swap(collectionAlgorithms[i],
79 collectionAlgorithms[idx]);
80 std::swap(sensors[i], sensors[idx]);
81 i = idx;
82 }
83
84 readings.emplace_back(sensors[i]->metadata(), *value,
85 systemTimestamp);
86 }
87 }
88 }
89
90 return readings;
91 }
92
sensorUpdated(interfaces::Sensor & notifier,Milliseconds timestamp,double value)93 void Metric::sensorUpdated(interfaces::Sensor& notifier, Milliseconds timestamp,
94 double value)
95 {
96 auto& data = findAssociatedData(notifier);
97 double newValue = data.update(timestamp, value);
98
99 if (data.updateLastValue(newValue))
100 {
101 for (interfaces::MetricListener& listener : listeners)
102 {
103 listener.metricUpdated();
104 }
105 }
106 }
107
108 metrics::CollectionData&
findAssociatedData(const interfaces::Sensor & notifier)109 Metric::findAssociatedData(const interfaces::Sensor& notifier)
110 {
111 auto it = std::find_if(
112 sensors.begin(), sensors.end(),
113 [¬ifier](const auto& sensor) { return sensor.get() == ¬ifier; });
114 auto index = std::distance(sensors.begin(), it);
115 return *collectionAlgorithms.at(index);
116 }
117
dumpConfiguration() const118 LabeledMetricParameters Metric::dumpConfiguration() const
119 {
120 auto sensorPath = utils::transform(sensors, [this](const auto& sensor) {
121 return LabeledSensorInfo(sensor->id().service, sensor->id().path,
122 sensor->metadata());
123 });
124
125 return LabeledMetricParameters(std::move(sensorPath), operationType,
126 collectionTimeScope, collectionDuration);
127 }
128
metricCount() const129 uint64_t Metric::metricCount() const
130 {
131 return sensors.size();
132 }
133
updateReadings(Milliseconds timestamp)134 void Metric::updateReadings(Milliseconds timestamp)
135 {
136 for (auto& data : collectionAlgorithms)
137 {
138 if (std::optional<double> newValue = data->update(timestamp))
139 {
140 if (data->updateLastValue(*newValue))
141 {
142 for (interfaces::MetricListener& listener : listeners)
143 {
144 listener.metricUpdated();
145 }
146 return;
147 }
148 }
149 }
150 }
151
isTimerRequired() const152 bool Metric::isTimerRequired() const
153 {
154 if (collectionTimeScope == CollectionTimeScope::point)
155 {
156 return false;
157 }
158
159 if (collectionTimeScope == CollectionTimeScope::startup &&
160 (operationType == OperationType::min ||
161 operationType == OperationType::max))
162 {
163 return false;
164 }
165
166 return true;
167 }
168