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 13 Metric::Metric(Sensors sensorsIn, OperationType operationTypeIn, 14 std::string idIn, CollectionTimeScope timeScopeIn, 15 CollectionDuration collectionDurationIn, 16 std::unique_ptr<interfaces::Clock> clockIn) : 17 id(std::move(idIn)), 18 sensors(std::move(sensorsIn)), operationType(operationTypeIn), 19 collectionTimeScope(timeScopeIn), collectionDuration(collectionDurationIn), 20 collectionAlgorithms( 21 metrics::makeCollectionData(sensors.size(), operationType, 22 collectionTimeScope, collectionDuration)), 23 clock(std::move(clockIn)) 24 { 25 readings = utils::transform(sensors, [this](const auto& sensor) { 26 return MetricValue{id, sensor->metadata(), 0.0, 0u}; 27 }); 28 } 29 30 void Metric::registerForUpdates(interfaces::MetricListener& listener) 31 { 32 listeners.emplace_back(listener); 33 } 34 35 void 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 } 44 45 void Metric::initialize() 46 { 47 for (const auto& sensor : sensors) 48 { 49 sensor->registerForUpdates(weak_from_this()); 50 } 51 } 52 53 void Metric::deinitialize() 54 { 55 for (const auto& sensor : sensors) 56 { 57 sensor->unregisterFromUpdates(weak_from_this()); 58 } 59 } 60 61 std::vector<MetricValue> Metric::getReadings() const 62 { 63 const auto steadyTimestamp = clock->steadyTimestamp(); 64 const auto systemTimestamp = clock->systemTimestamp(); 65 66 auto resultReadings = readings; 67 68 for (size_t i = 0; i < resultReadings.size(); ++i) 69 { 70 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 } 77 } 78 79 return resultReadings; 80 } 81 82 void Metric::sensorUpdated(interfaces::Sensor& notifier, Milliseconds timestamp, 83 double value) 84 { 85 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 } 95 } 96 97 metrics::CollectionData& 98 Metric::findAssociatedData(const interfaces::Sensor& notifier) 99 { 100 auto it = std::find_if( 101 sensors.begin(), sensors.end(), 102 [¬ifier](const auto& sensor) { return sensor.get() == ¬ifier; }); 103 auto index = std::distance(sensors.begin(), it); 104 return *collectionAlgorithms.at(index); 105 } 106 107 LabeledMetricParameters Metric::dumpConfiguration() const 108 { 109 auto sensorPath = utils::transform(sensors, [this](const auto& sensor) { 110 return LabeledSensorInfo(sensor->id().service, sensor->id().path, 111 sensor->metadata()); 112 }); 113 114 return LabeledMetricParameters(std::move(sensorPath), operationType, id, 115 collectionTimeScope, collectionDuration); 116 } 117 118 uint64_t Metric::sensorCount() const 119 { 120 return sensors.size(); 121 } 122 123 void 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 141 bool 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 } 157