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 <jozef.wludzik@intel.com>
Signed-off-by: Lukasz Kazmierczak <lukasz.kazmierczak@intel.com>
diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
index 010c991..a20f36a 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 @@
     }
 #endif
 
-    void filterAndSendReports(const std::string& id2,
-                              const std::string& readingsTs,
-                              const ReadingsObjType& readings)
+    void filterAndSendReports(
+        const std::string& id,
+        const std::variant<telemetry::TimestampReadings>& 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 @@
     }
 
 #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<std::string, std::variant<telemetry::TimestampReadings>>>
+            props;
+        std::vector<std::string> 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<int32_t, ReadingsObjType>>&
-                    resp) {
-                if (ec)
-                {
-                    BMCWEB_LOG_DEBUG
-                        << "D-Bus call failed to GetAll metric readings.";
-                    return;
-                }
-
-                const int32_t* timestampPtr =
-                    std::get_if<int32_t>(&resp["Timestamp"]);
-                if (!timestampPtr)
-                {
-                    BMCWEB_LOG_DEBUG << "Failed to Get timestamp.";
-                    return;
-                }
-
-                ReadingsObjType* readingsPtr =
-                    std::get_if<ReadingsObjType>(&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<Subscription> 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<telemetry::TimestampReadings>& 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 @@
         }
 
         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<sdbusplus::bus::match::match>(
             *crow::connections::systemBus, matchStr,
@@ -1410,10 +1366,7 @@
                     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 @@
     return metricValues;
 }
 
-inline void fillReport(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
-                       const std::string& id,
+inline bool fillReport(nlohmann::json& json, const std::string& id,
                        const std::variant<TimestampReadings>& 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 @@
     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<time_t>(timestamp));
-    asyncResp->res.jsonValue["MetricValues"] = toMetricValues(readings);
+    json["MetricValues"] = toMetricValues(readings);
+    return true;
 }
 } // namespace telemetry
 
@@ -122,7 +119,11 @@
                                     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",