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, 14*cff70c14SKrzysztof Grobelny CollectionTimeScope timeScopeIn, 158069771cSKrzysztof Grobelny CollectionDuration collectionDurationIn, 168069771cSKrzysztof Grobelny std::unique_ptr<interfaces::Clock> clockIn) : 17*cff70c14SKrzysztof Grobelny sensors(std::move(sensorsIn)), 18*cff70c14SKrzysztof Grobelny operationType(operationTypeIn), collectionTimeScope(timeScopeIn), 19*cff70c14SKrzysztof Grobelny collectionDuration(collectionDurationIn), 20f7ea2997SKrzysztof Grobelny collectionAlgorithms( 21f7ea2997SKrzysztof Grobelny metrics::makeCollectionData(sensors.size(), operationType, 22f7ea2997SKrzysztof Grobelny collectionTimeScope, collectionDuration)), 238069771cSKrzysztof Grobelny clock(std::move(clockIn)) 249e8da546SKrzysztof 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 { 333a1c297aSPatrick Williams listeners.erase(std::remove_if( 343a1c297aSPatrick Williams 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 579e8da546SKrzysztof Grobelny const std::vector<MetricValue>& Metric::getUpdatedReadings() 58e8fc5751SKrzysztof Grobelny { 5951f0fd50SKrzysztof Grobelny const auto steadyTimestamp = clock->steadyTimestamp(); 609e8da546SKrzysztof Grobelny const auto systemTimestamp = 619e8da546SKrzysztof Grobelny std::chrono::duration_cast<Milliseconds>(clock->systemTimestamp()) 629e8da546SKrzysztof Grobelny .count(); 6351f0fd50SKrzysztof Grobelny 649e8da546SKrzysztof Grobelny for (size_t i = 0; i < collectionAlgorithms.size(); ++i) 658069771cSKrzysztof Grobelny { 6651f0fd50SKrzysztof Grobelny if (const auto value = collectionAlgorithms[i]->update(steadyTimestamp)) 6751f0fd50SKrzysztof Grobelny { 689e8da546SKrzysztof Grobelny if (i < readings.size()) 699e8da546SKrzysztof Grobelny { 709e8da546SKrzysztof Grobelny readings[i].timestamp = systemTimestamp; 719e8da546SKrzysztof Grobelny readings[i].value = *value; 729e8da546SKrzysztof Grobelny } 739e8da546SKrzysztof Grobelny else 749e8da546SKrzysztof Grobelny { 759e8da546SKrzysztof Grobelny if (i > readings.size()) 769e8da546SKrzysztof Grobelny { 779e8da546SKrzysztof Grobelny const auto idx = readings.size(); 789e8da546SKrzysztof Grobelny std::swap(collectionAlgorithms[i], 799e8da546SKrzysztof Grobelny collectionAlgorithms[idx]); 809e8da546SKrzysztof Grobelny std::swap(sensors[i], sensors[idx]); 819e8da546SKrzysztof Grobelny i = idx; 829e8da546SKrzysztof Grobelny } 839e8da546SKrzysztof Grobelny 84*cff70c14SKrzysztof Grobelny readings.emplace_back(sensors[i]->metadata(), *value, 859e8da546SKrzysztof Grobelny systemTimestamp); 869e8da546SKrzysztof Grobelny } 8751f0fd50SKrzysztof Grobelny } 888069771cSKrzysztof Grobelny } 898069771cSKrzysztof Grobelny 909e8da546SKrzysztof 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 { 1113a1c297aSPatrick Williams auto it = std::find_if(sensors.begin(), sensors.end(), 1123a1c297aSPatrick Williams [¬ifier](const auto& sensor) { 1133a1c297aSPatrick Williams return sensor.get() == ¬ifier; 1143a1c297aSPatrick Williams }); 115dcc4e193SKrzysztof Grobelny auto index = std::distance(sensors.begin(), it); 1168069771cSKrzysztof Grobelny return *collectionAlgorithms.at(index); 1176ccfcbf5SKrzysztof Grobelny } 1186ccfcbf5SKrzysztof Grobelny 119d2238194SKrzysztof Grobelny LabeledMetricParameters Metric::dumpConfiguration() const 1206ccfcbf5SKrzysztof Grobelny { 121dcc4e193SKrzysztof Grobelny auto sensorPath = utils::transform(sensors, [this](const auto& sensor) { 12294f71c51SSzymon Dompke return LabeledSensorInfo(sensor->id().service, sensor->id().path, 123b8cc78ddSKrzysztof Grobelny sensor->metadata()); 124dcc4e193SKrzysztof Grobelny }); 125dcc4e193SKrzysztof Grobelny 126*cff70c14SKrzysztof Grobelny return LabeledMetricParameters(std::move(sensorPath), operationType, 127b8cc78ddSKrzysztof Grobelny collectionTimeScope, collectionDuration); 128dcc4e193SKrzysztof Grobelny } 129dcc4e193SKrzysztof Grobelny 13018e7101cSKrzysztof Grobelny uint64_t Metric::metricCount() const 1313eb56865SSzymon Dompke { 1323eb56865SSzymon Dompke return sensors.size(); 1333eb56865SSzymon Dompke } 134f7ea2997SKrzysztof Grobelny 135f7ea2997SKrzysztof Grobelny void Metric::updateReadings(Milliseconds timestamp) 136f7ea2997SKrzysztof Grobelny { 137f7ea2997SKrzysztof Grobelny for (auto& data : collectionAlgorithms) 138f7ea2997SKrzysztof Grobelny { 139f7ea2997SKrzysztof Grobelny if (std::optional<double> newValue = data->update(timestamp)) 140f7ea2997SKrzysztof Grobelny { 141f7ea2997SKrzysztof Grobelny if (data->updateLastValue(*newValue)) 142f7ea2997SKrzysztof Grobelny { 143f7ea2997SKrzysztof Grobelny for (interfaces::MetricListener& listener : listeners) 144f7ea2997SKrzysztof Grobelny { 145f7ea2997SKrzysztof Grobelny listener.metricUpdated(); 146f7ea2997SKrzysztof Grobelny } 147f7ea2997SKrzysztof Grobelny return; 148f7ea2997SKrzysztof Grobelny } 149f7ea2997SKrzysztof Grobelny } 150f7ea2997SKrzysztof Grobelny } 151f7ea2997SKrzysztof Grobelny } 152f7ea2997SKrzysztof Grobelny 153f7ea2997SKrzysztof Grobelny bool Metric::isTimerRequired() const 154f7ea2997SKrzysztof Grobelny { 155f7ea2997SKrzysztof Grobelny if (collectionTimeScope == CollectionTimeScope::point) 156f7ea2997SKrzysztof Grobelny { 157f7ea2997SKrzysztof Grobelny return false; 158f7ea2997SKrzysztof Grobelny } 159f7ea2997SKrzysztof Grobelny 160f7ea2997SKrzysztof Grobelny if (collectionTimeScope == CollectionTimeScope::startup && 161f7ea2997SKrzysztof Grobelny (operationType == OperationType::min || 162f7ea2997SKrzysztof Grobelny operationType == OperationType::max)) 163f7ea2997SKrzysztof Grobelny { 164f7ea2997SKrzysztof Grobelny return false; 165f7ea2997SKrzysztof Grobelny } 166f7ea2997SKrzysztof Grobelny 167f7ea2997SKrzysztof Grobelny return true; 168f7ea2997SKrzysztof Grobelny } 169