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 13dcc4e193SKrzysztof Grobelny Metric::Metric(Sensors sensorsIn, OperationType operationTypeIn, 14b8cc78ddSKrzysztof Grobelny std::string idIn, CollectionTimeScope timeScopeIn, 158069771cSKrzysztof Grobelny CollectionDuration collectionDurationIn, 168069771cSKrzysztof Grobelny std::unique_ptr<interfaces::Clock> clockIn) : 17b8cc78ddSKrzysztof Grobelny id(std::move(idIn)), 18dcc4e193SKrzysztof Grobelny sensors(std::move(sensorsIn)), operationType(operationTypeIn), 198069771cSKrzysztof Grobelny collectionTimeScope(timeScopeIn), collectionDuration(collectionDurationIn), 20f7ea2997SKrzysztof Grobelny collectionAlgorithms( 21f7ea2997SKrzysztof Grobelny metrics::makeCollectionData(sensors.size(), operationType, 22f7ea2997SKrzysztof Grobelny collectionTimeScope, collectionDuration)), 238069771cSKrzysztof Grobelny clock(std::move(clockIn)) 24*9e8da546SKrzysztof Grobelny {} 256ccfcbf5SKrzysztof Grobelny 26f7ea2997SKrzysztof Grobelny void Metric::registerForUpdates(interfaces::MetricListener& listener) 27f7ea2997SKrzysztof Grobelny { 28f7ea2997SKrzysztof Grobelny listeners.emplace_back(listener); 29f7ea2997SKrzysztof Grobelny } 30f7ea2997SKrzysztof Grobelny 31f7ea2997SKrzysztof Grobelny void Metric::unregisterFromUpdates(interfaces::MetricListener& listener) 32f7ea2997SKrzysztof Grobelny { 33f7ea2997SKrzysztof Grobelny listeners.erase( 34f7ea2997SKrzysztof Grobelny std::remove_if(listeners.begin(), listeners.end(), 35f7ea2997SKrzysztof Grobelny [&listener](const interfaces::MetricListener& item) { 36f7ea2997SKrzysztof Grobelny return &item == &listener; 37f7ea2997SKrzysztof Grobelny }), 38f7ea2997SKrzysztof Grobelny listeners.end()); 39f7ea2997SKrzysztof Grobelny } 408069771cSKrzysztof Grobelny 416ccfcbf5SKrzysztof Grobelny void Metric::initialize() 426ccfcbf5SKrzysztof Grobelny { 43dcc4e193SKrzysztof Grobelny for (const auto& sensor : sensors) 44dcc4e193SKrzysztof Grobelny { 456ccfcbf5SKrzysztof Grobelny sensor->registerForUpdates(weak_from_this()); 466ccfcbf5SKrzysztof Grobelny } 47dcc4e193SKrzysztof Grobelny } 48e8fc5751SKrzysztof Grobelny 497e098e93SLukasz Kazmierczak void Metric::deinitialize() 507e098e93SLukasz Kazmierczak { 517e098e93SLukasz Kazmierczak for (const auto& sensor : sensors) 527e098e93SLukasz Kazmierczak { 537e098e93SLukasz Kazmierczak sensor->unregisterFromUpdates(weak_from_this()); 547e098e93SLukasz Kazmierczak } 557e098e93SLukasz Kazmierczak } 567e098e93SLukasz Kazmierczak 57*9e8da546SKrzysztof Grobelny const std::vector<MetricValue>& Metric::getUpdatedReadings() 58e8fc5751SKrzysztof Grobelny { 5951f0fd50SKrzysztof Grobelny const auto steadyTimestamp = clock->steadyTimestamp(); 60*9e8da546SKrzysztof Grobelny const auto systemTimestamp = 61*9e8da546SKrzysztof Grobelny std::chrono::duration_cast<Milliseconds>(clock->systemTimestamp()) 62*9e8da546SKrzysztof Grobelny .count(); 6351f0fd50SKrzysztof Grobelny 64*9e8da546SKrzysztof Grobelny for (size_t i = 0; i < collectionAlgorithms.size(); ++i) 658069771cSKrzysztof Grobelny { 6651f0fd50SKrzysztof Grobelny if (const auto value = collectionAlgorithms[i]->update(steadyTimestamp)) 6751f0fd50SKrzysztof Grobelny { 68*9e8da546SKrzysztof Grobelny if (i < readings.size()) 69*9e8da546SKrzysztof Grobelny { 70*9e8da546SKrzysztof Grobelny readings[i].timestamp = systemTimestamp; 71*9e8da546SKrzysztof Grobelny readings[i].value = *value; 72*9e8da546SKrzysztof Grobelny } 73*9e8da546SKrzysztof Grobelny else 74*9e8da546SKrzysztof Grobelny { 75*9e8da546SKrzysztof Grobelny if (i > readings.size()) 76*9e8da546SKrzysztof Grobelny { 77*9e8da546SKrzysztof Grobelny const auto idx = readings.size(); 78*9e8da546SKrzysztof Grobelny std::swap(collectionAlgorithms[i], 79*9e8da546SKrzysztof Grobelny collectionAlgorithms[idx]); 80*9e8da546SKrzysztof Grobelny std::swap(sensors[i], sensors[idx]); 81*9e8da546SKrzysztof Grobelny i = idx; 82*9e8da546SKrzysztof Grobelny } 83*9e8da546SKrzysztof Grobelny 84*9e8da546SKrzysztof Grobelny readings.emplace_back(id, sensors[i]->metadata(), *value, 85*9e8da546SKrzysztof Grobelny systemTimestamp); 86*9e8da546SKrzysztof Grobelny } 8751f0fd50SKrzysztof Grobelny } 888069771cSKrzysztof Grobelny } 898069771cSKrzysztof Grobelny 90*9e8da546SKrzysztof Grobelny return readings; 916ccfcbf5SKrzysztof Grobelny } 926ccfcbf5SKrzysztof Grobelny 9351f0fd50SKrzysztof Grobelny void Metric::sensorUpdated(interfaces::Sensor& notifier, Milliseconds timestamp, 946ccfcbf5SKrzysztof Grobelny double value) 956ccfcbf5SKrzysztof Grobelny { 96f7ea2997SKrzysztof Grobelny auto& data = findAssociatedData(notifier); 97f7ea2997SKrzysztof Grobelny double newValue = data.update(timestamp, value); 98f7ea2997SKrzysztof Grobelny 99f7ea2997SKrzysztof Grobelny if (data.updateLastValue(newValue)) 100f7ea2997SKrzysztof Grobelny { 101f7ea2997SKrzysztof Grobelny for (interfaces::MetricListener& listener : listeners) 102f7ea2997SKrzysztof Grobelny { 103f7ea2997SKrzysztof Grobelny listener.metricUpdated(); 104f7ea2997SKrzysztof Grobelny } 105f7ea2997SKrzysztof Grobelny } 1066ccfcbf5SKrzysztof Grobelny } 1076ccfcbf5SKrzysztof Grobelny 108f7ea2997SKrzysztof Grobelny metrics::CollectionData& 1098069771cSKrzysztof Grobelny Metric::findAssociatedData(const interfaces::Sensor& notifier) 1106ccfcbf5SKrzysztof Grobelny { 111dcc4e193SKrzysztof Grobelny auto it = std::find_if( 112dcc4e193SKrzysztof Grobelny sensors.begin(), sensors.end(), 113dcc4e193SKrzysztof Grobelny [¬ifier](const auto& sensor) { return sensor.get() == ¬ifier; }); 114dcc4e193SKrzysztof Grobelny auto index = std::distance(sensors.begin(), it); 1158069771cSKrzysztof Grobelny return *collectionAlgorithms.at(index); 1166ccfcbf5SKrzysztof Grobelny } 1176ccfcbf5SKrzysztof Grobelny 118d2238194SKrzysztof Grobelny LabeledMetricParameters Metric::dumpConfiguration() const 1196ccfcbf5SKrzysztof Grobelny { 120dcc4e193SKrzysztof Grobelny auto sensorPath = utils::transform(sensors, [this](const auto& sensor) { 12194f71c51SSzymon Dompke return LabeledSensorInfo(sensor->id().service, sensor->id().path, 122b8cc78ddSKrzysztof Grobelny sensor->metadata()); 123dcc4e193SKrzysztof Grobelny }); 124dcc4e193SKrzysztof Grobelny 125dcc4e193SKrzysztof Grobelny return LabeledMetricParameters(std::move(sensorPath), operationType, id, 126b8cc78ddSKrzysztof Grobelny collectionTimeScope, collectionDuration); 127dcc4e193SKrzysztof Grobelny } 128dcc4e193SKrzysztof Grobelny 1293eb56865SSzymon Dompke uint64_t Metric::sensorCount() const 1303eb56865SSzymon Dompke { 1313eb56865SSzymon Dompke return sensors.size(); 1323eb56865SSzymon Dompke } 133f7ea2997SKrzysztof Grobelny 134f7ea2997SKrzysztof Grobelny void Metric::updateReadings(Milliseconds timestamp) 135f7ea2997SKrzysztof Grobelny { 136f7ea2997SKrzysztof Grobelny for (auto& data : collectionAlgorithms) 137f7ea2997SKrzysztof Grobelny { 138f7ea2997SKrzysztof Grobelny if (std::optional<double> newValue = data->update(timestamp)) 139f7ea2997SKrzysztof Grobelny { 140f7ea2997SKrzysztof Grobelny if (data->updateLastValue(*newValue)) 141f7ea2997SKrzysztof Grobelny { 142f7ea2997SKrzysztof Grobelny for (interfaces::MetricListener& listener : listeners) 143f7ea2997SKrzysztof Grobelny { 144f7ea2997SKrzysztof Grobelny listener.metricUpdated(); 145f7ea2997SKrzysztof Grobelny } 146f7ea2997SKrzysztof Grobelny return; 147f7ea2997SKrzysztof Grobelny } 148f7ea2997SKrzysztof Grobelny } 149f7ea2997SKrzysztof Grobelny } 150f7ea2997SKrzysztof Grobelny } 151f7ea2997SKrzysztof Grobelny 152f7ea2997SKrzysztof Grobelny bool Metric::isTimerRequired() const 153f7ea2997SKrzysztof Grobelny { 154f7ea2997SKrzysztof Grobelny if (collectionTimeScope == CollectionTimeScope::point) 155f7ea2997SKrzysztof Grobelny { 156f7ea2997SKrzysztof Grobelny return false; 157f7ea2997SKrzysztof Grobelny } 158f7ea2997SKrzysztof Grobelny 159f7ea2997SKrzysztof Grobelny if (collectionTimeScope == CollectionTimeScope::startup && 160f7ea2997SKrzysztof Grobelny (operationType == OperationType::min || 161f7ea2997SKrzysztof Grobelny operationType == OperationType::max)) 162f7ea2997SKrzysztof Grobelny { 163f7ea2997SKrzysztof Grobelny return false; 164f7ea2997SKrzysztof Grobelny } 165f7ea2997SKrzysztof Grobelny 166f7ea2997SKrzysztof Grobelny return true; 167f7ea2997SKrzysztof Grobelny } 168