| #include "metric.hpp" |
| |
| #include "metrics/collection_data.hpp" |
| #include "types/report_types.hpp" |
| #include "types/sensor_types.hpp" |
| #include "utils/labeled_tuple.hpp" |
| #include "utils/transform.hpp" |
| |
| #include <sdbusplus/exception.hpp> |
| |
| #include <algorithm> |
| |
| Metric::Metric(Sensors sensorsIn, OperationType operationTypeIn, |
| std::string idIn, CollectionTimeScope timeScopeIn, |
| CollectionDuration collectionDurationIn, |
| std::unique_ptr<interfaces::Clock> clockIn) : |
| id(std::move(idIn)), |
| sensors(std::move(sensorsIn)), operationType(operationTypeIn), |
| collectionTimeScope(timeScopeIn), collectionDuration(collectionDurationIn), |
| collectionAlgorithms( |
| metrics::makeCollectionData(sensors.size(), operationType, |
| collectionTimeScope, collectionDuration)), |
| clock(std::move(clockIn)) |
| {} |
| |
| void Metric::registerForUpdates(interfaces::MetricListener& listener) |
| { |
| listeners.emplace_back(listener); |
| } |
| |
| void Metric::unregisterFromUpdates(interfaces::MetricListener& listener) |
| { |
| listeners.erase(std::remove_if( |
| listeners.begin(), listeners.end(), |
| [&listener](const interfaces::MetricListener& item) { |
| return &item == &listener; |
| }), |
| listeners.end()); |
| } |
| |
| void Metric::initialize() |
| { |
| for (const auto& sensor : sensors) |
| { |
| sensor->registerForUpdates(weak_from_this()); |
| } |
| } |
| |
| void Metric::deinitialize() |
| { |
| for (const auto& sensor : sensors) |
| { |
| sensor->unregisterFromUpdates(weak_from_this()); |
| } |
| } |
| |
| const std::vector<MetricValue>& Metric::getUpdatedReadings() |
| { |
| const auto steadyTimestamp = clock->steadyTimestamp(); |
| const auto systemTimestamp = |
| std::chrono::duration_cast<Milliseconds>(clock->systemTimestamp()) |
| .count(); |
| |
| for (size_t i = 0; i < collectionAlgorithms.size(); ++i) |
| { |
| if (const auto value = collectionAlgorithms[i]->update(steadyTimestamp)) |
| { |
| if (i < readings.size()) |
| { |
| readings[i].timestamp = systemTimestamp; |
| readings[i].value = *value; |
| } |
| else |
| { |
| if (i > readings.size()) |
| { |
| const auto idx = readings.size(); |
| std::swap(collectionAlgorithms[i], |
| collectionAlgorithms[idx]); |
| std::swap(sensors[i], sensors[idx]); |
| i = idx; |
| } |
| |
| readings.emplace_back(id, sensors[i]->metadata(), *value, |
| systemTimestamp); |
| } |
| } |
| } |
| |
| return readings; |
| } |
| |
| void Metric::sensorUpdated(interfaces::Sensor& notifier, Milliseconds timestamp, |
| double value) |
| { |
| auto& data = findAssociatedData(notifier); |
| double newValue = data.update(timestamp, value); |
| |
| if (data.updateLastValue(newValue)) |
| { |
| for (interfaces::MetricListener& listener : listeners) |
| { |
| listener.metricUpdated(); |
| } |
| } |
| } |
| |
| metrics::CollectionData& |
| Metric::findAssociatedData(const interfaces::Sensor& notifier) |
| { |
| auto it = std::find_if(sensors.begin(), sensors.end(), |
| [¬ifier](const auto& sensor) { |
| return sensor.get() == ¬ifier; |
| }); |
| auto index = std::distance(sensors.begin(), it); |
| return *collectionAlgorithms.at(index); |
| } |
| |
| LabeledMetricParameters Metric::dumpConfiguration() const |
| { |
| auto sensorPath = utils::transform(sensors, [this](const auto& sensor) { |
| return LabeledSensorInfo(sensor->id().service, sensor->id().path, |
| sensor->metadata()); |
| }); |
| |
| return LabeledMetricParameters(std::move(sensorPath), operationType, id, |
| collectionTimeScope, collectionDuration); |
| } |
| |
| uint64_t Metric::metricCount() const |
| { |
| return sensors.size(); |
| } |
| |
| void Metric::updateReadings(Milliseconds timestamp) |
| { |
| for (auto& data : collectionAlgorithms) |
| { |
| if (std::optional<double> newValue = data->update(timestamp)) |
| { |
| if (data->updateLastValue(*newValue)) |
| { |
| for (interfaces::MetricListener& listener : listeners) |
| { |
| listener.metricUpdated(); |
| } |
| return; |
| } |
| } |
| } |
| } |
| |
| bool Metric::isTimerRequired() const |
| { |
| if (collectionTimeScope == CollectionTimeScope::point) |
| { |
| return false; |
| } |
| |
| if (collectionTimeScope == CollectionTimeScope::startup && |
| (operationType == OperationType::min || |
| operationType == OperationType::max)) |
| { |
| return false; |
| } |
| |
| return true; |
| } |