From 14a429586fd8ccb82c72611fe3310860db2e643b Mon Sep 17 00:00:00 2001 From: "Wludzik, Jozef" Date: Tue, 15 Dec 2020 12:30:31 +0100 Subject: [PATCH 4/4] 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 --- redfish-core/include/event_service_manager.hpp | 157 +++++++++---------------- redfish-core/lib/metric_report.hpp | 28 +++-- 2 files changed, 71 insertions(+), 114 deletions(-) diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp index 3db9f0c..5c5a6c1 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 "node.hpp" #include "registries.hpp" #include "registries/base_message_registry.hpp" @@ -510,48 +511,29 @@ class Subscription } #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 json; + if (!telemetry::fillReport(json, 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)}}; + 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()); + this->sendEvent(json.dump()); } void updateRetryConfig(const uint32_t retryAttempts, @@ -1342,56 +1324,72 @@ class EventServiceManager } #endif - - void getMetricReading(const std::string& service, - const std::string& objPath, const std::string& intf) + void unregisterMetricReportSignal() { - std::size_t found = objPath.find_last_of('/'); - if (found == std::string::npos) + if (matchTelemetryMonitor) { - BMCWEB_LOG_DEBUG << "Invalid objPath received"; - return; + BMCWEB_LOG_DEBUG << "Metrics report signal - Unregister"; + matchTelemetryMonitor.reset(); + matchTelemetryMonitor = nullptr; } + } - std::string idStr = objPath.substr(found + 1); - if (idStr.empty()) + void registerMetricReportSignal() + { + if (!serviceEnabled || matchTelemetryMonitor) { - BMCWEB_LOG_DEBUG << "Invalid ID in objPath"; + BMCWEB_LOG_DEBUG << "Not registering metric report signal."; 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 << "Metrics report signal - Register"; + std::string matchStr = "type='signal',member='PropertiesChanged'," + "interface='org.freedesktop.DBus.Properties'," + "path_namespace=/xyz/openbmc_project/Telemetry/" + "Reports/TelemetryService," + "arg0=xyz.openbmc_project.Telemetry.Report"; + + matchTelemetryMonitor = std::make_shared( + *crow::connections::systemBus, matchStr, + [this](sdbusplus::message::message& msg) { + if (msg.is_method_error()) { - BMCWEB_LOG_DEBUG - << "D-Bus call failed to GetAll metric readings."; + BMCWEB_LOG_ERROR << "TelemetryMonitor Signal error"; return; } - const int32_t* timestampPtr = - std::get_if(&resp["Timestamp"]); - if (!timestampPtr) + std::string intf; + std::vector>> + props; + std::vector invalidProp; + + msg.read(intf, props, invalidProp); + if (intf != "xyz.openbmc_project.Telemetry.Report") { - BMCWEB_LOG_DEBUG << "Failed to Get timestamp."; return; } - ReadingsObjType* readingsPtr = - std::get_if(&resp["Readings"]); - if (!readingsPtr) + const std::variant* varPtr = + nullptr; + for (const auto& [key, var] : props) + { + if (key == "Readings") + { + varPtr = &var; + break; + } + } + if (!varPtr) { - BMCWEB_LOG_DEBUG << "Failed to Get Readings property."; return; } - if (!readingsPtr->size()) + sdbusplus::message::object_path path(msg.get_path()); + std::string id = path.filename(); + if (id.empty()) { - BMCWEB_LOG_DEBUG << "No metrics report to be transferred"; + BMCWEB_LOG_ERROR << "Failed to get Id from path"; return; } @@ -1401,52 +1399,9 @@ class EventServiceManager std::shared_ptr entry = it.second; if (entry->eventFormatType == metricReportFormatType) { - entry->filterAndSendReports( - idStr, crow::utility::getDateTime(*timestampPtr), - *readingsPtr); + entry->filterAndSendReports(id, *varPtr); } } - }, - service, objPath, "org.freedesktop.DBus.Properties", "GetAll", - intf); - } - - void unregisterMetricReportSignal() - { - if (matchTelemetryMonitor) - { - BMCWEB_LOG_DEBUG << "Metrics report signal - Unregister"; - matchTelemetryMonitor.reset(); - matchTelemetryMonitor = nullptr; - } - } - - void registerMetricReportSignal() - { - if (!serviceEnabled || matchTelemetryMonitor) - { - BMCWEB_LOG_DEBUG << "Not registering metric report signal."; - return; - } - - BMCWEB_LOG_DEBUG << "Metrics report signal - Register"; - std::string matchStr( - "type='signal',member='ReportUpdate', " - "interface='xyz.openbmc_project.MonitoringService.Report'"); - - matchTelemetryMonitor = std::make_shared( - *crow::connections::systemBus, matchStr, - [this](sdbusplus::message::message& msg) { - if (msg.is_method_error()) - { - BMCWEB_LOG_ERROR << "TelemetryMonitor Signal error"; - return; - } - - std::string service = msg.get_sender(); - std::string objPath = msg.get_path(); - std::string intf = msg.get_interface(); - getMetricReading(service, objPath, intf); }); } diff --git a/redfish-core/lib/metric_report.hpp b/redfish-core/lib/metric_report.hpp index 9caf4a3..e79a41c 100644 --- a/redfish-core/lib/metric_report.hpp +++ b/redfish-core/lib/metric_report.hpp @@ -31,16 +31,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 + 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 + id; + json["Id"] = id; + json["Name"] = id; + json["MetricReportDefinition"]["@odata.id"] = telemetry::metricReportDefinitionUri + id; const TimestampReadings* timestampReadings = @@ -48,14 +46,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 @@ -146,7 +144,11 @@ class MetricReport : public Node 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.16.6