From dab3c96f9e39a89d7c359e22655650c7c16952ec Mon Sep 17 00:00:00 2001 From: Krzysztof Grobelny Date: Tue, 12 Oct 2021 08:06:13 +0000 Subject: [PATCH] Add support for MetricDefinition property in MetricReport Added MetricDefinition as part of MetricValues array returned by MetricReport. It contains single @odata.id with URI to proper MetricDefinition resource - depending on MetricProperty. Testing done: - GET request on redfish/v1/TelemetryService/MetricReports got response with MetricDefinition and proper id inside MetricValues array. Testing steps: 1. POST on redfish/v1/TelemetryService/MetricReportDefinitions with body: { "Id": "PeriodicReport_1", "MetricReportDefinitionType": "Periodic", "ReportActions": [ "LogToMetricReportsCollection", "RedfishEvent" ], "Metrics": [ { "MetricId": "sensor_1", "MetricProperties": [ "/redfish/v1/Chassis/AC_Baseboard/Thermal#/Fans/1/Reading" ] } ], "Schedule": { "RecurrenceInterval": "PT10S" } } 2. GET on redfish/v1/TelemetryService/MetricReports/PeriodicReport_1 should return: { "@odata.id": "/redfish/v1/TelemetryService/MetricReports/PeriodicReport_1", "@odata.type": "#MetricReport.v1_3_0.MetricReport", "Id": "PeriodicReport_1", "MetricReportDefinition": { "@odata.id": "/redfish/v1/TelemetryService/MetricReportDefinitions/PeriodicReport_1" }, "MetricValues": [ { "MetricDefinition": { "@odata.id": "/redfish/v1/TelemetryService/MetricDefinitions/Rotational" }, "MetricId": "sensor_1", "MetricProperty": "/redfish/v1/Chassis/AC_Baseboard/Thermal#/Fans/1/Reading", "MetricValue": "nan", "Timestamp": "1970-01-01T00:03:21+00:00" } ], "Name": "PeriodicReport_1", "Timestamp": "1970-01-01T00:03:21+00:00" } Change-Id: I7181c612f9b443015d551259bae25303aa436822 Signed-off-by: Szymon Dompke --- meson.build | 4 +- .../include/utils/telemetry_utils.hpp | 40 ++++++++++++ redfish-core/lib/metric_report.hpp | 64 +++++++++++++++---- redfish-core/lib/sensors.hpp | 2 + 4 files changed, 95 insertions(+), 15 deletions(-) diff --git a/meson.build b/meson.build index 6b6a8ab..218ea49 100644 --- a/meson.build +++ b/meson.build @@ -377,6 +377,8 @@ srcfiles_unittest = [ 'http/ut/utility_test.cpp' ] +srcfiles_unittest_dependencies = ['redfish-core/src/error_messages.cpp', 'src/boost_url.cpp'] + # Gather the Configuration data conf_data = configuration_data() @@ -434,7 +436,7 @@ executable('bmcweb',srcfiles_bmcweb, if(get_option('tests').enabled()) foreach src_test : srcfiles_unittest testname = src_test.split('/')[-1].split('.')[0] - test(testname,executable(testname,src_test, + test(testname,executable(testname,[src_test] + srcfiles_unittest_dependencies, include_directories : incdir, install_dir: bindir, dependencies: [ diff --git a/redfish-core/include/utils/telemetry_utils.hpp b/redfish-core/include/utils/telemetry_utils.hpp index 1b4f75d..c0c5ba3 100644 --- a/redfish-core/include/utils/telemetry_utils.hpp +++ b/redfish-core/include/utils/telemetry_utils.hpp @@ -17,6 +17,46 @@ constexpr const char* metricReportDefinitionUri = constexpr const char* metricReportUri = "/redfish/v1/TelemetryService/MetricReports/"; +inline std::optional + getMetadataJson(const std::string& metadataStr) +{ + std::optional res = + nlohmann::json::parse(metadataStr, nullptr, false); + if (res->is_discarded()) + { + BMCWEB_LOG_ERROR << "Malformed reading metatadata JSON provided by " + "telemetry service."; + return std::nullopt; + } + return res; +} + +inline std::optional + readStringFromMetadata(const nlohmann::json& metadataJson, const char* key) +{ + std::optional res; + if (auto it = metadataJson.find(key); it != metadataJson.end()) + { + if (const std::string* value = it->get_ptr()) + { + res = *value; + } + else + { + BMCWEB_LOG_ERROR << "Incorrect reading metatadata JSON provided by " + "telemetry service. Missing key '" + << key << "'."; + } + } + else + { + BMCWEB_LOG_ERROR << "Incorrect reading metatadata JSON provided by " + "telemetry service. Key '" + << key << "' has a wrong type."; + } + return res; +} + inline void getReportCollection(const std::shared_ptr& asyncResp, const std::string& uri) diff --git a/redfish-core/lib/metric_report.hpp b/redfish-core/lib/metric_report.hpp index 7fe281d..13bf792 100644 --- a/redfish-core/lib/metric_report.hpp +++ b/redfish-core/lib/metric_report.hpp @@ -1,5 +1,6 @@ #pragma once +#include "sensors.hpp" #include "utils/telemetry_utils.hpp" #include @@ -15,34 +16,56 @@ using Readings = std::vector>; using TimestampReadings = std::tuple; -inline nlohmann::json toMetricValues(const Readings& readings) +inline bool fillMetricValues(nlohmann::json& metricValues, + const Readings& readings) { - nlohmann::json metricValues = nlohmann::json::array_t(); - - for (auto& [id, metadata, sensorValue, timestamp] : readings) + for (auto& [id, metadataStr, sensorValue, timestamp] : readings) { + std::optional readingMetadataJson = + getMetadataJson(metadataStr); + if (!readingMetadataJson) + { + return false; + } + + std::optional sensorDbusPath = + readStringFromMetadata(*readingMetadataJson, "SensorDbusPath"); + if (!sensorDbusPath) + { + return false; + } + + std::optional sensorRedfishUri = + readStringFromMetadata(*readingMetadataJson, "SensorRedfishUri"); + if (!sensorRedfishUri) + { + return false; + } + + std::string metricDefinition = + std::string(metricDefinitionUri) + + sensors::toReadingType( + sdbusplus::message::object_path(*sensorDbusPath) + .parent_path() + .filename()); + metricValues.push_back({ + {"MetricDefinition", + nlohmann::json{{"@odata.id", metricDefinition}}}, {"MetricId", id}, - {"MetricProperty", metadata}, + {"MetricProperty", *sensorRedfishUri}, {"MetricValue", std::to_string(sensorValue)}, {"Timestamp", crow::utility::getDateTime(static_cast(timestamp))}, }); } - return metricValues; + return true; } inline bool fillReport(nlohmann::json& json, const std::string& id, const std::variant& var) { - json["@odata.type"] = "#MetricReport.v1_3_0.MetricReport"; - json["@odata.id"] = telemetry::metricReportUri + id; - json["Id"] = id; - json["Name"] = id; - json["MetricReportDefinition"]["@odata.id"] = - telemetry::metricReportDefinitionUri + id; - const TimestampReadings* timestampReadings = std::get_if(&var); if (!timestampReadings) @@ -52,9 +75,22 @@ inline bool fillReport(nlohmann::json& json, const std::string& id, } const auto& [timestamp, readings] = *timestampReadings; + nlohmann::json metricValues = nlohmann::json::array(); + if (!fillMetricValues(metricValues, readings)) + { + return false; + } + + json["@odata.type"] = "#MetricReport.v1_3_0.MetricReport"; + json["@odata.id"] = telemetry::metricReportUri + id; + json["Id"] = id; + json["Name"] = id; + json["MetricReportDefinition"]["@odata.id"] = + telemetry::metricReportDefinitionUri + id; json["Timestamp"] = crow::utility::getDateTime(static_cast(timestamp)); - json["MetricValues"] = toMetricValues(readings); + json["MetricValues"] = metricValues; + return true; } } // namespace telemetry diff --git a/redfish-core/lib/sensors.hpp b/redfish-core/lib/sensors.hpp index 7405e5a..9850b24 100644 --- a/redfish-core/lib/sensors.hpp +++ b/redfish-core/lib/sensors.hpp @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include #include -- 2.25.1