From 383848b9088056371743a28eb1f9a3ed415dc46b Mon Sep 17 00:00:00 2001 From: "Wludzik, Jozef" Date: Tue, 15 Dec 2020 12:30:31 +0100 Subject: [PATCH] Sync Telmetry service with EventService Synced the latest changes in Telemetry service with Event Service code. Now assembling MetricReport is covered in single place in code. Updated method of fetching Readings from Telemetry by Event Service. Using ReportUpdate signal is no longer supported. Now Event Service monitors for PropertiesChanged signal from /xyz/openbmc_project/Telemetry/Reports path. Tested: - Verified that EventListener received MetricReport response from Event Service in insecure http push style eventing mode Change-Id: I2fc1841a6c9259a8bff30b34bddc0d4aabd41912 Signed-off-by: Wludzik, Jozef Signed-off-by: Lukasz Kazmierczak --- .../include/event_service_manager.hpp | 135 ++++++------------ redfish-core/lib/metric_report.hpp | 29 ++-- 2 files changed, 59 insertions(+), 105 deletions(-) diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp index 010c991..38ab879 100644 --- a/redfish-core/include/event_service_manager.hpp +++ b/redfish-core/include/event_service_manager.hpp @@ -14,6 +14,7 @@ // limitations under the License. */ #pragma once +#include "metric_report.hpp" #include "registries.hpp" #include "registries/base_message_registry.hpp" #include "registries/openbmc_message_registry.hpp" @@ -503,47 +504,32 @@ class Subscription : public persistent_data::UserSubscription } #endif - void filterAndSendReports(const std::string& id2, - const std::string& readingsTs, - const ReadingsObjType& readings) + void filterAndSendReports( + const std::string& id, + const std::variant& var) { - std::string metricReportDef = - "/redfish/v1/TelemetryService/MetricReportDefinitions/" + id2; + std::string mrdUri = telemetry::metricReportDefinitionUri + id; // Empty list means no filter. Send everything. if (metricReportDefinitions.size()) { if (std::find(metricReportDefinitions.begin(), metricReportDefinitions.end(), - metricReportDef) == metricReportDefinitions.end()) + mrdUri) == metricReportDefinitions.end()) { return; } } - nlohmann::json metricValuesArray = nlohmann::json::array(); - for (const auto& it : readings) + nlohmann::json msg; + if (!telemetry::fillReport(msg, id, var)) { - metricValuesArray.push_back({}); - nlohmann::json& entry = metricValuesArray.back(); - - auto& [id, property, value, timestamp] = it; - - entry = {{"MetricId", id}, - {"MetricProperty", property}, - {"MetricValue", std::to_string(value)}, - {"Timestamp", crow::utility::getDateTime(timestamp)}}; + BMCWEB_LOG_ERROR << "Failed to fill the MetricReport for DBus " + "Report with id " + << id; + return; } - nlohmann::json msg = { - {"@odata.id", "/redfish/v1/TelemetryService/MetricReports/" + id}, - {"@odata.type", "#MetricReport.v1_3_0.MetricReport"}, - {"Id", id2}, - {"Name", id2}, - {"Timestamp", readingsTs}, - {"MetricReportDefinition", {{"@odata.id", metricReportDef}}}, - {"MetricValues", metricValuesArray}}; - this->sendEvent( msg.dump(2, ' ', true, nlohmann::json::error_handler_t::replace)); } @@ -1309,73 +1295,43 @@ class EventServiceManager } #endif - - void getMetricReading(const std::string& service, - const std::string& objPath, const std::string& intf) + void getReadingsForReport(sdbusplus::message::message& msg) { - std::size_t found = objPath.find_last_of('/'); - if (found == std::string::npos) + sdbusplus::message::object_path path(msg.get_path()); + std::string id = path.filename(); + if (id.empty()) { - BMCWEB_LOG_DEBUG << "Invalid objPath received"; + BMCWEB_LOG_ERROR << "Failed to get Id from path"; return; } - std::string idStr = objPath.substr(found + 1); - if (idStr.empty()) + std::string interface; + std::vector< + std::pair>> + props; + std::vector invalidProps; + msg.read(interface, props, invalidProps); + + auto found = + std::find_if(props.begin(), props.end(), + [](const auto& x) { return x.first == "Readings"; }); + if (found == props.end()) { - BMCWEB_LOG_DEBUG << "Invalid ID in objPath"; + BMCWEB_LOG_INFO << "Failed to get Readings from Report properties"; return; } - crow::connections::systemBus->async_method_call( - [idStr{std::move(idStr)}]( - const boost::system::error_code ec, - boost::container::flat_map< - std::string, std::variant>& - resp) { - if (ec) - { - BMCWEB_LOG_DEBUG - << "D-Bus call failed to GetAll metric readings."; - return; - } - - const int32_t* timestampPtr = - std::get_if(&resp["Timestamp"]); - if (!timestampPtr) - { - BMCWEB_LOG_DEBUG << "Failed to Get timestamp."; - return; - } - - ReadingsObjType* readingsPtr = - std::get_if(&resp["Readings"]); - if (!readingsPtr) - { - BMCWEB_LOG_DEBUG << "Failed to Get Readings property."; - return; - } - - if (!readingsPtr->size()) - { - BMCWEB_LOG_DEBUG << "No metrics report to be transferred"; - return; - } - - for (const auto& it : - EventServiceManager::getInstance().subscriptionsMap) - { - std::shared_ptr entry = it.second; - if (entry->eventFormatType == metricReportFormatType) - { - entry->filterAndSendReports( - idStr, crow::utility::getDateTime(*timestampPtr), - *readingsPtr); - } - } - }, - service, objPath, "org.freedesktop.DBus.Properties", "GetAll", - intf); + const std::variant& readings = + found->second; + for (const auto& it : + EventServiceManager::getInstance().subscriptionsMap) + { + Subscription& entry = *it.second.get(); + if (entry.eventFormatType == metricReportFormatType) + { + entry.filterAndSendReports(id, readings); + } + } } void unregisterMetricReportSignal() @@ -1397,9 +1353,9 @@ class EventServiceManager } BMCWEB_LOG_DEBUG << "Metrics report signal - Register"; - std::string matchStr( - "type='signal',member='ReportUpdate', " - "interface='xyz.openbmc_project.MonitoringService.Report'"); + std::string matchStr = "type='signal',member='PropertiesChanged'," + "interface='org.freedesktop.DBus.Properties'," + "arg0=xyz.openbmc_project.Telemetry.Report"; matchTelemetryMonitor = std::make_shared( *crow::connections::systemBus, matchStr, @@ -1410,10 +1366,7 @@ class EventServiceManager return; } - std::string service = msg.get_sender(); - std::string objPath = msg.get_path(); - std::string intf = msg.get_interface(); - getMetricReading(service, objPath, intf); + getReadingsForReport(msg); }); } diff --git a/redfish-core/lib/metric_report.hpp b/redfish-core/lib/metric_report.hpp index 159968a..c959495 100644 --- a/redfish-core/lib/metric_report.hpp +++ b/redfish-core/lib/metric_report.hpp @@ -34,17 +34,14 @@ inline nlohmann::json toMetricValues(const Readings& readings) return metricValues; } -inline void fillReport(const std::shared_ptr& asyncResp, - const std::string& id, +inline bool fillReport(nlohmann::json& json, const std::string& id, const std::variant& var) { - asyncResp->res.jsonValue["@odata.type"] = - "#MetricReport.v1_3_0.MetricReport"; - asyncResp->res.jsonValue["@odata.id"] = - telemetry::metricReportUri + std::string("/") + id; - asyncResp->res.jsonValue["Id"] = id; - asyncResp->res.jsonValue["Name"] = id; - asyncResp->res.jsonValue["MetricReportDefinition"]["@odata.id"] = + json["@odata.type"] = "#MetricReport.v1_3_0.MetricReport"; + json["@odata.id"] = telemetry::metricReportUri + std::string("/") + id; + json["Id"] = id; + json["Name"] = id; + json["MetricReportDefinition"]["@odata.id"] = telemetry::metricReportDefinitionUri + std::string("/") + id; const TimestampReadings* timestampReadings = @@ -52,14 +49,14 @@ inline void fillReport(const std::shared_ptr& asyncResp, if (!timestampReadings) { BMCWEB_LOG_ERROR << "Property type mismatch or property is missing"; - messages::internalError(asyncResp->res); - return; + return false; } const auto& [timestamp, readings] = *timestampReadings; - asyncResp->res.jsonValue["Timestamp"] = + json["Timestamp"] = crow::utility::getDateTime(static_cast(timestamp)); - asyncResp->res.jsonValue["MetricValues"] = toMetricValues(readings); + json["MetricValues"] = toMetricValues(readings); + return true; } } // namespace telemetry @@ -122,7 +119,11 @@ inline void requestRoutesMetricReport(App& app) return; } - telemetry::fillReport(asyncResp, id, ret); + if (!telemetry::fillReport( + asyncResp->res.jsonValue, id, ret)) + { + messages::internalError(asyncResp->res); + } }, telemetry::service, reportPath, "org.freedesktop.DBus.Properties", "Get", -- 2.25.1