summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry
diff options
context:
space:
mode:
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry')
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Add-support-for-MetricDefinition-scheme.patch496
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0002-Sync-Telmetry-service-with-EventService.patch294
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Switched-bmcweb-to-use-new-telemetry-service-API.patch301
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0004-Add-support-for-MetricDefinition-property-in-MetricReport.patch267
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Add-GET-method-for-TriggerCollection.patch313
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0006-Revert-Remove-LogService-from-TelemetryService.patch26
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0007-event-service-fix-added-Context-field-to-response.patch29
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0008-Generalize-ReadingType-in-MetricDefinition.patch93
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0009-Add-support-for-deleting-terminated-subscriptions.patch46
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/README30
10 files changed, 1895 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Add-support-for-MetricDefinition-scheme.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Add-support-for-MetricDefinition-scheme.patch
new file mode 100644
index 000000000..c19691cdc
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Add-support-for-MetricDefinition-scheme.patch
@@ -0,0 +1,496 @@
+From 80608f0d72da62426bb00e03a42fbf5daed931c9 Mon Sep 17 00:00:00 2001
+From: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
+Date: Tue, 13 Apr 2021 13:00:18 +0000
+Subject: [PATCH] Add support for MetricDefinition scheme
+
+Added MetricDefinition node to Redfish code. Now user is able to list
+all available metrics in OpenBMC that are supported by Telemetry
+service. Metrics are grouped by reading type.
+
+MetricDefinitions contains all physical sensors supported by redfish,
+algorithm iterates through all chassis and collects results for each
+node available in that chassis (Power, Thermal, Sensors).
+
+When https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/40169 will
+be merge it will be possible to optimize this algorithm to only get
+sensors from Sensors node. Currently Sensors node doesn't contain all
+available sensors.
+
+Tested:
+ - MetricDefinitions response is filled with existing sensors, it works
+ with and without Telemetry service
+ - Validated a presence of MetricDefinition members and its attributes
+ - Successfully passed RedfishServiceValidator.py using witherspoon
+ image on QEMU
+ - Tested using following GET,POST requests
+
+GET /redfish/v1/TelemetryService/MetricDefinitions
+{
+ "@odata.id": "/redfish/v1/TelemetryService/MetricDefinitions",
+ "@odata.type": "#MetricDefinitionCollection.MetricDefinitionCollection",
+ "Members": [
+ {
+ "@odata.id": "/redfish/v1/TelemetryService/MetricDefinitions/Rotational"
+ },
+ {
+ "@odata.id": "/redfish/v1/TelemetryService/MetricDefinitions/Percent"
+ },
+ {
+ "@odata.id": "/redfish/v1/TelemetryService/MetricDefinitions/Temperature"
+ },
+ {
+ "@odata.id": "/redfish/v1/TelemetryService/MetricDefinitions/Power"
+ },
+ {
+ "@odata.id": "/redfish/v1/TelemetryService/MetricDefinitions/AirFlow"
+ }
+ ],
+ "Members@odata.count": 5,
+ "Name": "Metric Definition Collection"
+}
+
+GET /redfish/v1/TelemetryService/MetricDefinitions/Rotational
+{
+ "@odata.id": "/redfish/v1/TelemetryService/MetricDefinitions/Rotational",
+ "@odata.type": "#MetricDefinition.v1_0_3.MetricDefinition",
+ "Id": "Rotational",
+ "Implementation": "PhysicalSensor",
+ "IsLinear": true,
+ "MetricDataType": "Decimal",
+ "MetricProperties": [
+ "/redfish/v1/Chassis/Chassis0/Thermal#/Fans/0/Reading",
+ "/redfish/v1/Chassis/Chassis0/Thermal#/Fans/1/Reading",
+ "/redfish/v1/Chassis/Chassis0/Thermal#/Fans/2/Reading",
+ "/redfish/v1/Chassis/Chassis0/Thermal#/Fans/3/Reading",
+ "/redfish/v1/Chassis/Chassis0/Thermal#/Fans/4/Reading",
+ "/redfish/v1/Chassis/Chassis0/Thermal#/Fans/5/Reading",
+ "/redfish/v1/Chassis/Chassis0/Thermal#/Fans/6/Reading",
+ "/redfish/v1/Chassis/Chassis0/Thermal#/Fans/7/Reading",
+ "/redfish/v1/Chassis/Chassis0/Thermal#/Fans/8/Reading",
+ "/redfish/v1/Chassis/Chassis0/Thermal#/Fans/9/Reading"
+ ],
+ "MetricType": "Numeric",
+ "Name": "Rotational",
+ "Units": "RPM"
+}
+
+POST redfish/v1/TelemetryService/MetricReportDefinitions, body:
+{
+ "Id": "TestReport",
+ "Metrics": [
+ {
+ "MetricId": "TestMetric",
+ "MetricProperties": [
+ "/redfish/v1/Chassis/Chassis0/Thermal#/Fans/3/Reading",
+ ]
+ }
+ ],
+ "MetricReportDefinitionType": "OnRequest",
+ "ReportActions": [
+ "RedfishEvent",
+ "LogToMetricReportsCollection"
+ ]
+}
+{
+ "@Message.ExtendedInfo": [
+ {
+ "@odata.type": "#Message.v1_1_1.Message",
+ "Message": "The resource has been created successfully",
+ "MessageArgs": [],
+ "MessageId": "Base.1.8.1.Created",
+ "MessageSeverity": "OK",
+ "Resolution": "None"
+ }
+ ]
+}
+
+Signed-off-by: Wludzik, Jozef <jozef.wludzik@intel.com>
+Signed-off-by: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
+Change-Id: I3086e1302e1ba2e5442d1367939fd5507a0cbc00
+---
+ redfish-core/include/redfish.hpp | 3 +
+ .../include/utils/get_chassis_names.hpp | 58 ++++
+ .../include/utils/telemetry_utils.hpp | 2 +
+ redfish-core/lib/metric_definition.hpp | 258 ++++++++++++++++++
+ redfish-core/lib/telemetry_service.hpp | 2 +
+ 5 files changed, 323 insertions(+)
+ create mode 100644 redfish-core/include/utils/get_chassis_names.hpp
+ create mode 100644 redfish-core/lib/metric_definition.hpp
+
+diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp
+index 1c7b695..9983b88 100644
+--- a/redfish-core/include/redfish.hpp
++++ b/redfish-core/include/redfish.hpp
+@@ -26,6 +26,7 @@
+ #include "../lib/managers.hpp"
+ #include "../lib/memory.hpp"
+ #include "../lib/message_registries.hpp"
++#include "../lib/metric_definition.hpp"
+ #include "../lib/metric_report.hpp"
+ #include "../lib/metric_report_definition.hpp"
+ #include "../lib/network_protocol.hpp"
+@@ -199,6 +200,8 @@ class RedfishService
+ requestRoutesMetricReportDefinition(app);
+ requestRoutesMetricReportCollection(app);
+ requestRoutesMetricReport(app);
++ requestRoutesMetricDefinitionCollection(app);
++ requestRoutesMetricDefinition(app);
+ }
+ };
+
+diff --git a/redfish-core/include/utils/get_chassis_names.hpp b/redfish-core/include/utils/get_chassis_names.hpp
+new file mode 100644
+index 0000000..0276b6f
+--- /dev/null
++++ b/redfish-core/include/utils/get_chassis_names.hpp
+@@ -0,0 +1,58 @@
++#pragma once
++
++#include <include/dbus_singleton.hpp>
++
++#include <array>
++#include <string>
++#include <vector>
++
++namespace redfish
++{
++
++namespace utils
++{
++
++template <typename F>
++inline void getChassisNames(F&& cb)
++{
++ const std::array<const char*, 2> interfaces = {
++ "xyz.openbmc_project.Inventory.Item.Board",
++ "xyz.openbmc_project.Inventory.Item.Chassis"};
++
++ crow::connections::systemBus->async_method_call(
++ [callback = std::move(cb)](const boost::system::error_code ec,
++ const std::vector<std::string>& chassis) {
++ std::vector<std::string> chassisNames;
++
++ if (ec)
++ {
++ callback(ec, chassisNames);
++ return;
++ }
++
++ chassisNames.reserve(chassis.size());
++ for (const std::string& path : chassis)
++ {
++ sdbusplus::message::object_path dbusPath = path;
++ std::string name = dbusPath.filename();
++ if (name.empty())
++ {
++ callback(boost::system::errc::make_error_code(
++ boost::system::errc::invalid_argument),
++ chassisNames);
++ return;
++ }
++ chassisNames.emplace_back(std::move(name));
++ }
++
++ callback(ec, chassisNames);
++ },
++ "xyz.openbmc_project.ObjectMapper",
++ "/xyz/openbmc_project/object_mapper",
++ "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
++ "/xyz/openbmc_project/inventory", 0, interfaces);
++}
++
++} // namespace utils
++
++} // namespace redfish
+diff --git a/redfish-core/include/utils/telemetry_utils.hpp b/redfish-core/include/utils/telemetry_utils.hpp
+index 5872350..1b4f75d 100644
+--- a/redfish-core/include/utils/telemetry_utils.hpp
++++ b/redfish-core/include/utils/telemetry_utils.hpp
+@@ -10,6 +10,8 @@ namespace telemetry
+
+ constexpr const char* service = "xyz.openbmc_project.Telemetry";
+ constexpr const char* reportInterface = "xyz.openbmc_project.Telemetry.Report";
++constexpr const char* metricDefinitionUri =
++ "/redfish/v1/TelemetryService/MetricDefinitions/";
+ constexpr const char* metricReportDefinitionUri =
+ "/redfish/v1/TelemetryService/MetricReportDefinitions/";
+ constexpr const char* metricReportUri =
+diff --git a/redfish-core/lib/metric_definition.hpp b/redfish-core/lib/metric_definition.hpp
+new file mode 100644
+index 0000000..019168b
+--- /dev/null
++++ b/redfish-core/lib/metric_definition.hpp
+@@ -0,0 +1,258 @@
++#pragma once
++
++#include "async_resp.hpp"
++#include "sensors.hpp"
++#include "utils/get_chassis_names.hpp"
++#include "utils/telemetry_utils.hpp"
++
++#include <registries/privilege_registry.hpp>
++
++namespace redfish
++{
++
++namespace telemetry
++{
++
++bool containsOdata(const nlohmann::json& json, const std::string& odataId)
++{
++ const auto it = std::find_if(
++ json.begin(), json.end(), [&odataId](const nlohmann::json& item) {
++ auto kt = item.find("@odata.id");
++ if (kt == item.end())
++ {
++ return false;
++ }
++ const std::string* value = kt->get_ptr<const std::string*>();
++ if (!value)
++ {
++ return false;
++ }
++ return *value == odataId;
++ });
++
++ return it != json.end();
++}
++
++void addMembers(crow::Response& res,
++ const boost::container::flat_map<std::string, std::string>& el)
++{
++ for (const auto& [_, dbusSensor] : el)
++ {
++ sdbusplus::message::object_path path(dbusSensor);
++ sdbusplus::message::object_path parentPath = path.parent_path();
++ const std::string type = parentPath.filename();
++
++ if (type.empty())
++ {
++ BMCWEB_LOG_ERROR << "Received invalid DBus Sensor Path = "
++ << dbusSensor;
++ continue;
++ }
++
++ nlohmann::json& members = res.jsonValue["Members"];
++
++ const std::string odataId =
++ std::string(telemetry::metricDefinitionUri) +
++ sensors::toReadingType(type);
++
++ if (!containsOdata(members, odataId))
++ {
++ members.push_back({{"@odata.id", odataId}});
++ }
++
++ res.jsonValue["Members@odata.count"] = members.size();
++ }
++}
++
++template <class Callback>
++inline void mapRedfishUriToDbusPath(Callback&& callback)
++{
++ utils::getChassisNames([callback = std::move(callback)](
++ boost::system::error_code ec,
++ const std::vector<std::string>& chassisNames) {
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR << "getChassisNames error: " << ec.value();
++ callback(ec, {});
++ return;
++ }
++
++ auto handleRetrieveUriToDbusMap =
++ [callback = std::move(callback)](
++ const boost::beast::http::status status,
++ const boost::container::flat_map<std::string, std::string>&
++ uriToDbus) {
++ if (status != boost::beast::http::status::ok)
++ {
++ BMCWEB_LOG_ERROR << "Failed to retrieve URI to dbus "
++ "sensors map with err "
++ << static_cast<unsigned>(status);
++ callback(boost::system::errc::make_error_code(
++ boost::system::errc::io_error),
++ {});
++ return;
++ }
++
++ callback(boost::system::errc::make_error_code(
++ boost::system::errc::success),
++ uriToDbus);
++ };
++
++ for (const std::string& chassisName : chassisNames)
++ {
++ for (const auto& [sensorNode, dbusPaths] : sensors::dbus::paths)
++ {
++ retrieveUriToDbusMap(chassisName, sensorNode.data(),
++ handleRetrieveUriToDbusMap);
++ }
++ }
++ });
++}
++
++} // namespace telemetry
++
++inline void requestRoutesMetricDefinitionCollection(App& app)
++{
++ BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricDefinitions/")
++ .privileges(privileges::getTelemetryService)
++ .methods(boost::beast::http::verb::get)(
++ [](const crow::Request&,
++ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
++ telemetry::mapRedfishUriToDbusPath(
++ [asyncResp](boost::system::error_code ec,
++ const boost::container::flat_map<
++ std::string, std::string>& uriToDbus) {
++ if (ec)
++ {
++ messages::internalError(asyncResp->res);
++ BMCWEB_LOG_ERROR
++ << "mapRedfishUriToDbusPath error: "
++ << ec.value();
++ return;
++ }
++
++ telemetry::addMembers(asyncResp->res, uriToDbus);
++ });
++
++ asyncResp->res.jsonValue["@odata.type"] =
++ "#MetricDefinitionCollection."
++ "MetricDefinitionCollection";
++ asyncResp->res.jsonValue["@odata.id"] =
++ "/redfish/v1/TelemetryService/MetricDefinitions";
++ asyncResp->res.jsonValue["Name"] =
++ "Metric Definition Collection";
++ asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
++ asyncResp->res.jsonValue["Members@odata.count"] = 0;
++ });
++}
++
++namespace telemetry
++{
++
++bool isSensorIdSupported(std::string_view readingType)
++{
++ for (const std::pair<std::string_view, std::vector<const char*>>&
++ typeToPaths : sensors::dbus::paths)
++ {
++ for (const char* supportedPath : typeToPaths.second)
++ {
++ if (readingType ==
++ sensors::toReadingType(
++ sdbusplus::message::object_path(supportedPath).filename()))
++ {
++ return true;
++ }
++ }
++ }
++ return false;
++}
++
++void addMetricProperty(
++ bmcweb::AsyncResp& asyncResp, const std::string& readingType,
++ const boost::container::flat_map<std::string, std::string>& el)
++{
++ nlohmann::json& metricProperties =
++ asyncResp.res.jsonValue["MetricProperties"];
++
++ for (const auto& [redfishSensor, dbusSensor] : el)
++ {
++ std::string sensorId;
++ if (dbus::utility::getNthStringFromPath(dbusSensor, 3, sensorId))
++ {
++ if (sensors::toReadingType(sensorId) == readingType)
++ {
++ metricProperties.push_back(redfishSensor);
++ }
++ }
++ }
++}
++
++inline const char* readingTypeToReadingUnits(const std::string& readingType)
++{
++ for (const auto& [node, paths] : sensors::dbus::paths)
++ {
++ for (const char* path : paths)
++ {
++ const sdbusplus::message::object_path sensorPath =
++ sdbusplus::message::object_path(path);
++ if (sensors::toReadingType(sensorPath.filename()) == readingType)
++ {
++ return sensors::toReadingUnits(sensorPath.filename());
++ }
++ }
++ }
++ return "";
++}
++
++} // namespace telemetry
++
++inline void requestRoutesMetricDefinition(App& app)
++{
++ BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricDefinitions/<str>/")
++ .privileges(privileges::getTelemetryService)
++ .methods(boost::beast::http::verb::get)(
++ [](const crow::Request&,
++ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
++ const std::string& readingType) {
++ if (!telemetry::isSensorIdSupported(readingType))
++ {
++ messages::resourceNotFound(asyncResp->res,
++ "MetricDefinition", readingType);
++ return;
++ }
++
++ telemetry::mapRedfishUriToDbusPath(
++ [asyncResp,
++ readingType](boost::system::error_code ec,
++ const boost::container::flat_map<
++ std::string, std::string>& uriToDbus) {
++ if (ec)
++ {
++ messages::internalError(asyncResp->res);
++ BMCWEB_LOG_ERROR
++ << "mapRedfishUriToDbusPath error: "
++ << ec.value();
++ return;
++ }
++
++ asyncResp->res.jsonValue["Id"] = readingType;
++ asyncResp->res.jsonValue["Name"] = readingType;
++ asyncResp->res.jsonValue["@odata.id"] =
++ telemetry::metricDefinitionUri + readingType;
++ asyncResp->res.jsonValue["@odata.type"] =
++ "#MetricDefinition.v1_0_3.MetricDefinition";
++ asyncResp->res.jsonValue["MetricDataType"] = "Decimal";
++ asyncResp->res.jsonValue["MetricType"] = "Numeric";
++ asyncResp->res.jsonValue["IsLinear"] = true;
++ asyncResp->res.jsonValue["Implementation"] =
++ "PhysicalSensor";
++ asyncResp->res.jsonValue["Units"] =
++ telemetry::readingTypeToReadingUnits(readingType);
++
++ telemetry::addMetricProperty(*asyncResp, readingType,
++ uriToDbus);
++ });
++ });
++}
++
++} // namespace redfish
+diff --git a/redfish-core/lib/telemetry_service.hpp b/redfish-core/lib/telemetry_service.hpp
+index ad86d5c..c4962e9 100644
+--- a/redfish-core/lib/telemetry_service.hpp
++++ b/redfish-core/lib/telemetry_service.hpp
+@@ -29,6 +29,8 @@ inline void requestRoutesTelemetryService(App& app)
+ "/redfish/v1/TelemetryService/MetricReportDefinitions";
+ asyncResp->res.jsonValue["MetricReports"]["@odata.id"] =
+ "/redfish/v1/TelemetryService/MetricReports";
++ asyncResp->res.jsonValue["MetricDefinitions"]["@odata.id"] =
++ "/redfish/v1/TelemetryService/MetricDefinitions";
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](
+--
+2.25.1
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0002-Sync-Telmetry-service-with-EventService.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0002-Sync-Telmetry-service-with-EventService.patch
new file mode 100644
index 000000000..d32c85356
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0002-Sync-Telmetry-service-with-EventService.patch
@@ -0,0 +1,294 @@
+From 77e8a0b5037a555b1520823b667595ac8780c675 Mon Sep 17 00:00:00 2001
+From: "Wludzik, Jozef" <jozef.wludzik@intel.com>
+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 <jozef.wludzik@intel.com>
+---
+ .../include/event_service_manager.hpp | 156 ++++++------------
+ redfish-core/lib/metric_report.hpp | 28 ++--
+ 2 files changed, 69 insertions(+), 115 deletions(-)
+
+diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
+index d89b789..4faaddd 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"
+@@ -511,47 +512,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<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));
+ }
+@@ -1317,75 +1303,6 @@ class EventServiceManager
+ }
+
+ #endif
+-
+- void getMetricReading(const std::string& service,
+- const std::string& objPath, const std::string& intf)
+- {
+- std::size_t found = objPath.find_last_of('/');
+- if (found == std::string::npos)
+- {
+- BMCWEB_LOG_DEBUG << "Invalid objPath received";
+- return;
+- }
+-
+- std::string idStr = objPath.substr(found + 1);
+- if (idStr.empty())
+- {
+- BMCWEB_LOG_DEBUG << "Invalid ID in objPath";
+- 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);
+- }
+-
+ void unregisterMetricReportSignal()
+ {
+ if (matchTelemetryMonitor)
+@@ -1405,9 +1322,11 @@ 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',"
++ "path_namespace=/xyz/openbmc_project/Telemetry/"
++ "Reports/TelemetryService,"
++ "arg0=xyz.openbmc_project.Telemetry.Report";
+
+ matchTelemetryMonitor = std::make_shared<sdbusplus::bus::match::match>(
+ *crow::connections::systemBus, matchStr,
+@@ -1418,10 +1337,43 @@ 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);
++ sdbusplus::message::object_path path(msg.get_path());
++ std::string id = path.filename();
++ if (id.empty())
++ {
++ BMCWEB_LOG_ERROR << "Failed to get Id from path";
++ return;
++ }
++
++ std::string intf;
++ std::vector<std::pair<
++ std::string, std::variant<telemetry::TimestampReadings>>>
++ props;
++ std::vector<std::string> invalidProps;
++ msg.read(intf, props, invalidProps);
++
++ auto found =
++ std::find_if(props.begin(), props.end(), [](const auto& x) {
++ return x.first == "Readings";
++ });
++ if (found == props.end())
++ {
++ BMCWEB_LOG_ERROR
++ << "Failed to get Readings from Report properties";
++ return;
++ }
++
++ 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);
++ }
++ }
+ });
+ }
+
+diff --git a/redfish-core/lib/metric_report.hpp b/redfish-core/lib/metric_report.hpp
+index 63c8c19..7fe281d 100644
+--- a/redfish-core/lib/metric_report.hpp
++++ b/redfish-core/lib/metric_report.hpp
+@@ -33,16 +33,14 @@ inline nlohmann::json toMetricValues(const Readings& readings)
+ 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 + 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 =
+@@ -50,14 +48,14 @@ inline void fillReport(const std::shared_ptr<bmcweb::AsyncResp>& 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<time_t>(timestamp));
+- asyncResp->res.jsonValue["MetricValues"] = toMetricValues(readings);
++ json["MetricValues"] = toMetricValues(readings);
++ return true;
+ }
+ } // namespace telemetry
+
+@@ -118,7 +116,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
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Switched-bmcweb-to-use-new-telemetry-service-API.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Switched-bmcweb-to-use-new-telemetry-service-API.patch
new file mode 100644
index 000000000..20bcbabfa
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Switched-bmcweb-to-use-new-telemetry-service-API.patch
@@ -0,0 +1,301 @@
+From fca6f5b951a363916a83a25f6578f95a6cf32a3e Mon Sep 17 00:00:00 2001
+From: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
+Date: Thu, 17 Jun 2021 13:37:57 +0000
+Subject: [PATCH] Switched bmcweb to use new telemetry service API
+
+Added support for multiple MetricProperties. Added support for new
+parameters: CollectionTimeScope, CollectionDuration.
+
+Tested:
+ - It is possible to create MetricReportDefinitions with multiple
+ MetricProperties.
+ - Stub values for new parameters are correctly passed to telemetry
+ service.
+ - All existing telemetry service functionalities remain unchanged.
+
+Change-Id: I2cd17069e3ea015c8f5571c29278f1d50536272a
+Signed-off-by: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
+---
+ redfish-core/lib/metric_report_definition.hpp | 212 ++++++++++--------
+ 1 file changed, 114 insertions(+), 98 deletions(-)
+
+diff --git a/redfish-core/lib/metric_report_definition.hpp b/redfish-core/lib/metric_report_definition.hpp
+index a0c4f1d..7c26787 100644
+--- a/redfish-core/lib/metric_report_definition.hpp
++++ b/redfish-core/lib/metric_report_definition.hpp
+@@ -7,6 +7,8 @@
+ #include <app.hpp>
+ #include <boost/container/flat_map.hpp>
+ #include <registries/privilege_registry.hpp>
++#include <sdbusplus/asio/property.hpp>
++#include <sdbusplus/unpack_properties.hpp>
+
+ #include <tuple>
+ #include <variant>
+@@ -17,87 +19,90 @@ namespace redfish
+ namespace telemetry
+ {
+
+-using ReadingParameters =
+- std::vector<std::tuple<sdbusplus::message::object_path, std::string,
+- std::string, std::string>>;
++using ReadingParameters = std::vector<
++ std::tuple<std::vector<sdbusplus::message::object_path>, std::string,
++ std::string, std::string, std::string, uint64_t>>;
+
+ inline void fillReportDefinition(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id,
+ const std::vector<
+- std::pair<std::string, std::variant<std::string, bool, uint64_t,
+- ReadingParameters>>>& ret)
++ std::pair<std::string, std::variant<std::monostate, std::string, bool,
++ uint64_t, ReadingParameters>>>&
++ properties)
+ {
+- asyncResp->res.jsonValue["@odata.type"] =
+- "#MetricReportDefinition.v1_3_0.MetricReportDefinition";
+- asyncResp->res.jsonValue["@odata.id"] =
+- telemetry::metricReportDefinitionUri + id;
+- asyncResp->res.jsonValue["Id"] = id;
+- asyncResp->res.jsonValue["Name"] = id;
+- asyncResp->res.jsonValue["MetricReport"]["@odata.id"] =
+- telemetry::metricReportUri + id;
+- asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
+- asyncResp->res.jsonValue["ReportUpdates"] = "Overwrite";
+-
+- const bool* emitsReadingsUpdate = nullptr;
+- const bool* logToMetricReportsCollection = nullptr;
+- const ReadingParameters* readingParams = nullptr;
+- const std::string* reportingType = nullptr;
+- const uint64_t* interval = nullptr;
+- for (const auto& [key, var] : ret)
++ try
+ {
+- if (key == "EmitsReadingsUpdate")
++ bool emitsReadingsUpdate = false;
++ bool logToMetricReportsCollection = false;
++ ReadingParameters readingParams;
++ std::string reportingType;
++ uint64_t interval = 0u;
++
++ sdbusplus::unpackProperties(
++ properties, "EmitsReadingsUpdate", emitsReadingsUpdate,
++ "LogToMetricReportsCollection", logToMetricReportsCollection,
++ "ReadingParametersFutureVersion", readingParams, "ReportingType",
++ reportingType, "Interval", interval);
++
++ std::vector<std::string> redfishReportActions;
++ redfishReportActions.reserve(2);
++ if (emitsReadingsUpdate)
+ {
+- emitsReadingsUpdate = std::get_if<bool>(&var);
++ redfishReportActions.emplace_back("RedfishEvent");
+ }
+- else if (key == "LogToMetricReportsCollection")
++ if (logToMetricReportsCollection)
+ {
+- logToMetricReportsCollection = std::get_if<bool>(&var);
++ redfishReportActions.emplace_back("LogToMetricReportsCollection");
+ }
+- else if (key == "ReadingParameters")
+- {
+- readingParams = std::get_if<ReadingParameters>(&var);
+- }
+- else if (key == "ReportingType")
+- {
+- reportingType = std::get_if<std::string>(&var);
+- }
+- else if (key == "Interval")
++
++ nlohmann::json metrics = nlohmann::json::array();
++ for (auto& [sensorPath, operationType, id, metadata,
++ collectionTimeScope, collectionDuration] : readingParams)
+ {
+- interval = std::get_if<uint64_t>(&var);
++ std::vector<std::string> metricProperties;
++
++ nlohmann::json parsedMetadata = nlohmann::json::parse(metadata);
++ if (!json_util::readJson(parsedMetadata, asyncResp->res,
++ "MetricProperties", metricProperties))
++ {
++ BMCWEB_LOG_ERROR << "Failed to read metadata";
++ messages::internalError(asyncResp->res);
++ return;
++ }
++
++ metrics.push_back({
++ {"MetricId", id},
++ {"MetricProperties", std::move(metricProperties)},
++ });
+ }
+- }
+- if (!emitsReadingsUpdate || !logToMetricReportsCollection ||
+- !readingParams || !reportingType || !interval)
+- {
+- BMCWEB_LOG_ERROR << "Property type mismatch or property is missing";
+- messages::internalError(asyncResp->res);
+- return;
+- }
+
+- std::vector<std::string> redfishReportActions;
+- redfishReportActions.reserve(2);
+- if (*emitsReadingsUpdate)
+- {
+- redfishReportActions.emplace_back("RedfishEvent");
++ asyncResp->res.jsonValue["@odata.type"] =
++ "#MetricReportDefinition.v1_3_0.MetricReportDefinition";
++ asyncResp->res.jsonValue["@odata.id"] =
++ telemetry::metricReportDefinitionUri + id;
++ asyncResp->res.jsonValue["Id"] = id;
++ asyncResp->res.jsonValue["Name"] = id;
++ asyncResp->res.jsonValue["MetricReport"]["@odata.id"] =
++ telemetry::metricReportUri + id;
++ asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
++ asyncResp->res.jsonValue["ReportUpdates"] = "Overwrite";
++ asyncResp->res.jsonValue["Metrics"] = metrics;
++ asyncResp->res.jsonValue["MetricReportDefinitionType"] = reportingType;
++ asyncResp->res.jsonValue["ReportActions"] = redfishReportActions;
++ asyncResp->res.jsonValue["Schedule"]["RecurrenceInterval"] =
++ time_utils::toDurationString(std::chrono::milliseconds(interval));
+ }
+- if (*logToMetricReportsCollection)
++ catch (const sdbusplus::exception::UnpackPropertyError& error)
+ {
+- redfishReportActions.emplace_back("LogToMetricReportsCollection");
++ BMCWEB_LOG_ERROR << error.what() << ", property: "
++ << error.propertyName + ", reason: " << error.reason;
++ messages::internalError(asyncResp->res);
+ }
+-
+- nlohmann::json metrics = nlohmann::json::array();
+- for (auto& [sensorPath, operationType, id, metadata] : *readingParams)
++ catch (const nlohmann::json::parse_error& e)
+ {
+- metrics.push_back({
+- {"MetricId", id},
+- {"MetricProperties", {metadata}},
+- });
++ BMCWEB_LOG_ERROR << "Failed to parse metadata: " << e.what();
++ messages::internalError(asyncResp->res);
+ }
+- asyncResp->res.jsonValue["Metrics"] = metrics;
+- asyncResp->res.jsonValue["MetricReportDefinitionType"] = *reportingType;
+- asyncResp->res.jsonValue["ReportActions"] = redfishReportActions;
+- asyncResp->res.jsonValue["Schedule"]["RecurrenceInterval"] =
+- time_utils::toDurationString(std::chrono::milliseconds(*interval));
+ }
+
+ struct AddReportArgs
+@@ -275,6 +280,11 @@ class AddReport
+
+ for (const auto& [id, uris] : args.metrics)
+ {
++ std::vector<sdbusplus::message::object_path> dbusPaths;
++ dbusPaths.reserve(uris.size());
++ nlohmann::json metadata;
++ metadata["MetricProperties"] = nlohmann::json::array();
++
+ for (size_t i = 0; i < uris.size(); i++)
+ {
+ const std::string& uri = uris[i];
+@@ -291,8 +301,12 @@ class AddReport
+ }
+
+ const std::string& dbusPath = el->second;
+- readingParams.emplace_back(dbusPath, "SINGLE", id, uri);
++ dbusPaths.emplace_back(dbusPath);
++ metadata["MetricProperties"].emplace_back(uri);
+ }
++
++ readingParams.emplace_back(dbusPaths, "SINGLE", id, metadata.dump(),
++ "Point", 0u);
+ }
+ const std::shared_ptr<bmcweb::AsyncResp> aResp = asyncResp;
+ crow::connections::systemBus->async_method_call(
+@@ -330,10 +344,10 @@ class AddReport
+ messages::created(aResp->res);
+ },
+ telemetry::service, "/xyz/openbmc_project/Telemetry/Reports",
+- "xyz.openbmc_project.Telemetry.ReportManager", "AddReport",
+- "TelemetryService/" + args.name, args.reportingType,
+- args.emitsReadingsUpdate, args.logToMetricReportsCollection,
+- args.interval, readingParams);
++ "xyz.openbmc_project.Telemetry.ReportManager",
++ "AddReportFutureVersion", "TelemetryService/" + args.name,
++ args.reportingType, args.emitsReadingsUpdate,
++ args.logToMetricReportsCollection, args.interval, readingParams);
+ }
+
+ void insert(const boost::container::flat_map<std::string, std::string>& el)
+@@ -415,37 +429,39 @@ inline void requestRoutesMetricReportDefinition(App& app)
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/")
+ .privileges(redfish::privileges::getMetricReportDefinition)
+- .methods(boost::beast::http::verb::get)(
+- [](const crow::Request&,
+- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+- const std::string& id) {
+- crow::connections::systemBus->async_method_call(
+- [asyncResp, id](
+- const boost::system::error_code ec,
+- const std::vector<std::pair<
+- std::string,
+- std::variant<std::string, bool, uint64_t,
+- telemetry::ReadingParameters>>>& ret) {
+- if (ec.value() == EBADR ||
+- ec == boost::system::errc::host_unreachable)
+- {
+- messages::resourceNotFound(
+- asyncResp->res, "MetricReportDefinition", id);
+- return;
+- }
+- if (ec)
+- {
+- BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
+- messages::internalError(asyncResp->res);
+- return;
+- }
++ .methods(
++ boost::beast::http::verb::get)([](const crow::Request&,
++ const std::shared_ptr<
++ bmcweb::AsyncResp>& asyncResp,
++ const std::string& id) {
++ sdbusplus::asio::getAllProperties(
++ *crow::connections::systemBus, telemetry::service,
++ telemetry::getDbusReportPath(id), telemetry::reportInterface,
++ [asyncResp,
++ id](boost::system::error_code ec,
++ const std::vector<std::pair<
++ std::string,
++ std::variant<std::monostate, std::string, bool,
++ uint64_t, telemetry::ReadingParameters>>>&
++ properties) {
++ if (ec.value() == EBADR ||
++ ec == boost::system::errc::host_unreachable)
++ {
++ messages::resourceNotFound(
++ asyncResp->res, "MetricReportDefinition", id);
++ return;
++ }
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
++ messages::internalError(asyncResp->res);
++ return;
++ }
++
++ telemetry::fillReportDefinition(asyncResp, id, properties);
++ });
++ });
+
+- telemetry::fillReportDefinition(asyncResp, id, ret);
+- },
+- telemetry::service, telemetry::getDbusReportPath(id),
+- "org.freedesktop.DBus.Properties", "GetAll",
+- telemetry::reportInterface);
+- });
+ BMCWEB_ROUTE(app,
+ "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/")
+ .privileges(redfish::privileges::deleteMetricReportDefinitionCollection)
+--
+2.25.1
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0004-Add-support-for-MetricDefinition-property-in-MetricReport.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0004-Add-support-for-MetricDefinition-property-in-MetricReport.patch
new file mode 100644
index 000000000..3d60ae293
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0004-Add-support-for-MetricDefinition-property-in-MetricReport.patch
@@ -0,0 +1,267 @@
+From 79b3d35b864a2b545b4c9b2ac9390ea5dec169f5 Mon Sep 17 00:00:00 2001
+From: Szymon Dompke <szymon.dompke@intel.com>
+Date: Mon, 28 Jun 2021 11:10:23 +0200
+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 <szymon.dompke@intel.com>
+---
+ 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 f6a66f1..6b5d9af 100644
+--- a/meson.build
++++ b/meson.build
+@@ -355,6 +355,8 @@ srcfiles_unittest = ['include/ut/dbus_utility_test.cpp',
+ 'redfish-core/ut/time_utils_test.cpp',
+ 'http/ut/utility_test.cpp']
+
++srcfiles_unittest_dependencies = ['redfish-core/src/error_messages.cpp']
++
+ # Gather the Configuration data
+
+ conf_data = configuration_data()
+@@ -412,7 +414,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<nlohmann::json>
++ getMetadataJson(const std::string& metadataStr)
++{
++ std::optional<nlohmann::json> 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<std::string>
++ readStringFromMetadata(const nlohmann::json& metadataJson, const char* key)
++{
++ std::optional<std::string> res;
++ if (auto it = metadataJson.find(key); it != metadataJson.end())
++ {
++ if (const std::string* value = it->get_ptr<const std::string*>())
++ {
++ 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<bmcweb::AsyncResp>& 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 <app.hpp>
+@@ -15,34 +16,56 @@ using Readings =
+ std::vector<std::tuple<std::string, std::string, double, uint64_t>>;
+ using TimestampReadings = std::tuple<uint64_t, Readings>;
+
+-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<nlohmann::json> readingMetadataJson =
++ getMetadataJson(metadataStr);
++ if (!readingMetadataJson)
++ {
++ return false;
++ }
++
++ std::optional<std::string> sensorDbusPath =
++ readStringFromMetadata(*readingMetadataJson, "SensorDbusPath");
++ if (!sensorDbusPath)
++ {
++ return false;
++ }
++
++ std::optional<std::string> 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<time_t>(timestamp))},
+ });
+ }
+
+- return metricValues;
++ return true;
+ }
+
+ inline bool fillReport(nlohmann::json& json, const std::string& id,
+ const std::variant<TimestampReadings>& 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<TimestampReadings>(&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<time_t>(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 cb7ea15..44c2129 100644
+--- a/redfish-core/lib/sensors.hpp
++++ b/redfish-core/lib/sensors.hpp
+@@ -21,6 +21,8 @@
+ #include <boost/container/flat_map.hpp>
+ #include <boost/range/algorithm/replace_copy_if.hpp>
+ #include <dbus_singleton.hpp>
++#include <dbus_utility.hpp>
++#include <error_messages.hpp>
+ #include <registries/privilege_registry.hpp>
+ #include <utils/json_utils.hpp>
+
+--
+2.25.1
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Add-GET-method-for-TriggerCollection.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Add-GET-method-for-TriggerCollection.patch
new file mode 100644
index 000000000..0646aba5c
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Add-GET-method-for-TriggerCollection.patch
@@ -0,0 +1,313 @@
+From a1e89d356ba5ed594a1494efe8257946e1062396 Mon Sep 17 00:00:00 2001
+From: Lukasz Kazmierczak <lukasz.kazmierczak@intel.com>
+Date: Tue, 31 Aug 2021 14:35:31 +0200
+Subject: [PATCH] Add GET method for TriggerCollection
+
+Added GET method for retrieving list of Triggers from Telemetry service
+
+Tested:
+- Added single Trigger and requested result from bmcweb via
+ /redfish/v1/TelemetryService/Triggers
+- Added multiple Triggers numeric and discrete, and requested results
+ from bmcweb via /redfish/v1/TelemetryService/Triggers
+- Verified uri /redfish/v1/TelemetryService/Triggers by using
+ Redfish-Service-Validator (all passed)
+
+Signed-off-by: Lukasz Kazmierczak <lukasz.kazmierczak@intel.com>
+Change-Id: Ide00eb44901ea1b97b80fc5c5ddfd97e393d4a04
+---
+ redfish-core/include/redfish.hpp | 2 +
+ .../include/utils/telemetry_utils.hpp | 40 ++++++++---
+ redfish-core/lib/metric_report.hpp | 6 +-
+ redfish-core/lib/metric_report_definition.hpp | 6 +-
+ redfish-core/lib/trigger.hpp | 31 ++++++++
+ scripts/update_schemas.py | 1 +
+ static/redfish/v1/$metadata/index.xml | 3 +
+ .../v1/schema/TriggersCollection_v1.xml | 70 +++++++++++++++++++
+ 8 files changed, 144 insertions(+), 15 deletions(-)
+ create mode 100644 redfish-core/lib/trigger.hpp
+ create mode 100644 static/redfish/v1/schema/TriggersCollection_v1.xml
+
+diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp
+index 9fb0ffe..99b3fe6 100644
+--- a/redfish-core/include/redfish.hpp
++++ b/redfish-core/include/redfish.hpp
+@@ -42,6 +42,7 @@
+ #include "../lib/task.hpp"
+ #include "../lib/telemetry_service.hpp"
+ #include "../lib/thermal.hpp"
++#include "../lib/trigger.hpp"
+ #include "../lib/update_service.hpp"
+ #include "../lib/virtual_media.hpp"
+
+@@ -197,6 +198,7 @@ class RedfishService
+
+ hypervisor::requestRoutesHypervisorSystems(app);
+
++ requestRoutesTriggerCollection(app);
+ requestRoutesTelemetryService(app);
+ requestRoutesMetricReportDefinitionCollection(app);
+ requestRoutesMetricReportDefinition(app);
+diff --git a/redfish-core/include/utils/telemetry_utils.hpp b/redfish-core/include/utils/telemetry_utils.hpp
+index c0c5ba3..df1aa68 100644
+--- a/redfish-core/include/utils/telemetry_utils.hpp
++++ b/redfish-core/include/utils/telemetry_utils.hpp
+@@ -9,6 +9,8 @@ namespace telemetry
+ {
+
+ constexpr const char* service = "xyz.openbmc_project.Telemetry";
++constexpr const char* reportSubtree =
++ "/xyz/openbmc_project/Telemetry/Reports/TelemetryService";
+ constexpr const char* reportInterface = "xyz.openbmc_project.Telemetry.Report";
+ constexpr const char* metricDefinitionUri =
+ "/redfish/v1/TelemetryService/MetricDefinitions/";
+@@ -16,6 +18,11 @@ constexpr const char* metricReportDefinitionUri =
+ "/redfish/v1/TelemetryService/MetricReportDefinitions/";
+ constexpr const char* metricReportUri =
+ "/redfish/v1/TelemetryService/MetricReports/";
++constexpr const char* triggerSubtree =
++ "/xyz/openbmc_project/Telemetry/Triggers/TelemetryService";
++constexpr const char* triggerInterface =
++ "xyz.openbmc_project.Telemetry.Trigger";
++constexpr const char* triggerUri = "/redfish/v1/TelemetryService/Triggers/";
+
+ inline std::optional<nlohmann::json>
+ getMetadataJson(const std::string& metadataStr)
+@@ -57,15 +64,27 @@ inline std::optional<std::string>
+ return res;
+ }
+
+-inline void
+- getReportCollection(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+- const std::string& uri)
++struct CollectionParams
+ {
+- const std::array<const char*, 1> interfaces = {reportInterface};
++ const char* subtree;
++ int depth;
++ std::array<const char*, 1> interfaces;
+
++ CollectionParams() = delete;
++ CollectionParams(const char* st, int dp,
++ const std::array<const char*, 1>& ifaces) :
++ subtree{st},
++ depth{dp}, interfaces{ifaces}
++ {}
++};
++
++inline void getCollection(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
++ const std::string& uri,
++ const CollectionParams& params)
++{
+ crow::connections::systemBus->async_method_call(
+ [asyncResp, uri](const boost::system::error_code ec,
+- const std::vector<std::string>& reports) {
++ const std::vector<std::string>& items) {
+ if (ec == boost::system::errc::io_error)
+ {
+ asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
+@@ -82,13 +101,13 @@ inline void
+ nlohmann::json& members = asyncResp->res.jsonValue["Members"];
+ members = nlohmann::json::array();
+
+- for (const std::string& report : reports)
++ for (const std::string& item : items)
+ {
+- sdbusplus::message::object_path path(report);
++ sdbusplus::message::object_path path(item);
+ std::string name = path.filename();
+ if (name.empty())
+ {
+- BMCWEB_LOG_ERROR << "Received invalid path: " << report;
++ BMCWEB_LOG_ERROR << "Received invalid path: " << item;
+ messages::internalError(asyncResp->res);
+ return;
+ }
+@@ -99,9 +118,8 @@ inline void
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+- "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
+- "/xyz/openbmc_project/Telemetry/Reports/TelemetryService", 1,
+- interfaces);
++ "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", params.subtree,
++ params.depth, params.interfaces);
+ }
+
+ inline std::string getDbusReportPath(const std::string& id)
+diff --git a/redfish-core/lib/metric_report.hpp b/redfish-core/lib/metric_report.hpp
+index 13bf792..ea4cd62 100644
+--- a/redfish-core/lib/metric_report.hpp
++++ b/redfish-core/lib/metric_report.hpp
+@@ -108,8 +108,10 @@ inline void requestRoutesMetricReportCollection(App& app)
+ "/redfish/v1/TelemetryService/MetricReports";
+ asyncResp->res.jsonValue["Name"] = "Metric Report Collection";
+
+- telemetry::getReportCollection(asyncResp,
+- telemetry::metricReportUri);
++ telemetry::getCollection(
++ asyncResp, telemetry::metricReportUri,
++ telemetry::CollectionParams(telemetry::reportSubtree, 1,
++ {telemetry::reportInterface}));
+ });
+ }
+
+diff --git a/redfish-core/lib/metric_report_definition.hpp b/redfish-core/lib/metric_report_definition.hpp
+index 7c26787..c97a1df 100644
+--- a/redfish-core/lib/metric_report_definition.hpp
++++ b/redfish-core/lib/metric_report_definition.hpp
+@@ -377,8 +377,10 @@ inline void requestRoutesMetricReportDefinitionCollection(App& app)
+ asyncResp->res.jsonValue["Name"] =
+ "Metric Definition Collection";
+
+- telemetry::getReportCollection(
+- asyncResp, telemetry::metricReportDefinitionUri);
++ telemetry::getCollection(
++ asyncResp, telemetry::metricReportDefinitionUri,
++ telemetry::CollectionParams(telemetry::reportSubtree, 1,
++ {telemetry::reportInterface}));
+ });
+
+ BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/")
+diff --git a/redfish-core/lib/trigger.hpp b/redfish-core/lib/trigger.hpp
+new file mode 100644
+index 0000000..681b3b4
+--- /dev/null
++++ b/redfish-core/lib/trigger.hpp
+@@ -0,0 +1,31 @@
++#pragma once
++
++#include "utils/telemetry_utils.hpp"
++
++#include <app.hpp>
++#include <registries/privilege_registry.hpp>
++
++namespace redfish
++{
++
++inline void requestRoutesTriggerCollection(App& app)
++{
++ BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/Triggers/")
++ .privileges(redfish::privileges::getTriggersCollection)
++ .methods(boost::beast::http::verb::get)(
++ [](const crow::Request&,
++ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
++ asyncResp->res.jsonValue["@odata.type"] =
++ "#TriggersCollection.TriggersCollection";
++ asyncResp->res.jsonValue["@odata.id"] =
++ "/redfish/v1/TelemetryService/Triggers";
++ asyncResp->res.jsonValue["Name"] = "Triggers Collection";
++
++ telemetry::getCollection(
++ asyncResp, telemetry::triggerUri,
++ telemetry::CollectionParams(telemetry::triggerSubtree, 1,
++ {telemetry::triggerInterface}));
++ });
++}
++
++} // namespace redfish
+diff --git a/scripts/update_schemas.py b/scripts/update_schemas.py
+index dd39278..d66a59a 100755
+--- a/scripts/update_schemas.py
++++ b/scripts/update_schemas.py
+@@ -93,6 +93,7 @@ include_list = [
+ 'TaskService',
+ 'TelemetryService',
+ 'Thermal',
++ 'TriggersCollection',
+ 'UpdateService',
+ 'VLanNetworkInterfaceCollection',
+ 'VLanNetworkInterface',
+diff --git a/static/redfish/v1/$metadata/index.xml b/static/redfish/v1/$metadata/index.xml
+index 876ebfb..75e3dd4 100644
+--- a/static/redfish/v1/$metadata/index.xml
++++ b/static/redfish/v1/$metadata/index.xml
+@@ -2215,6 +2215,9 @@
+ <edmx:Include Namespace="Thermal.v1_7_0"/>
+ <edmx:Include Namespace="Thermal.v1_7_1"/>
+ </edmx:Reference>
++ <edmx:Reference Uri="/redfish/v1/schema/TriggersCollection_v1.xml">
++ <edmx:Include Namespace="TriggersCollection"/>
++ </edmx:Reference>
+ <edmx:Reference Uri="/redfish/v1/schema/UpdateService_v1.xml">
+ <edmx:Include Namespace="UpdateService"/>
+ <edmx:Include Namespace="UpdateService.v1_0_0"/>
+diff --git a/static/redfish/v1/schema/TriggersCollection_v1.xml b/static/redfish/v1/schema/TriggersCollection_v1.xml
+new file mode 100644
+index 0000000..399bebd
+--- /dev/null
++++ b/static/redfish/v1/schema/TriggersCollection_v1.xml
+@@ -0,0 +1,70 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<!---->
++<!--################################################################################ -->
++<!--# Redfish Schema: TriggerSetCollection -->
++<!--# -->
++<!--# For a detailed change log, see the README file contained in the DSP8010 bundle, -->
++<!--# available at http://www.dmtf.org/standards/redfish -->
++<!--# Copyright 2014-2021 DMTF. -->
++<!--# For the full DMTF copyright policy, see http://www.dmtf.org/about/policies/copyright -->
++<!--################################################################################ -->
++<!---->
++<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
++
++ <edmx:Reference Uri="http://docs.oasis-open.org/odata/odata/v4.0/errata03/csd01/complete/vocabularies/Org.OData.Core.V1.xml">
++ <edmx:Include Namespace="Org.OData.Core.V1" Alias="OData"/>
++ </edmx:Reference>
++ <edmx:Reference Uri="http://docs.oasis-open.org/odata/odata/v4.0/errata03/csd01/complete/vocabularies/Org.OData.Capabilities.V1.xml">
++ <edmx:Include Namespace="Org.OData.Capabilities.V1" Alias="Capabilities"/>
++ </edmx:Reference>
++ <edmx:Reference Uri="http://redfish.dmtf.org/schemas/v1/Resource_v1.xml">
++ <edmx:Include Namespace="Resource.v1_0_0"/>
++ </edmx:Reference>
++ <edmx:Reference Uri="http://redfish.dmtf.org/schemas/v1/RedfishExtensions_v1.xml">
++ <edmx:Include Namespace="RedfishExtensions.v1_0_0" Alias="Redfish"/>
++ </edmx:Reference>
++ <edmx:Reference Uri="http://redfish.dmtf.org/schemas/v1/Triggers_v1.xml">
++ <edmx:Include Namespace="Triggers"/>
++ </edmx:Reference>
++
++ <edmx:DataServices>
++
++ <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="TriggersCollection">
++ <Annotation Term="Redfish.OwningEntity" String="DMTF"/>
++
++ <EntityType Name="TriggersCollection" BaseType="Resource.v1_0_0.ResourceCollection">
++ <Annotation Term="OData.Description" String="The collection of Triggers resource instances."/>
++ <Annotation Term="OData.LongDescription" String="This resource shall represent a resource collection of Triggers instances for a Redfish implementation."/>
++ <Annotation Term="Capabilities.InsertRestrictions">
++ <Record>
++ <PropertyValue Property="Insertable" Bool="true"/>
++ <Annotation Term="OData.Description" String="Create triggers through a POST to the trigger collection."/>
++ </Record>
++ </Annotation>
++ <Annotation Term="Capabilities.UpdateRestrictions">
++ <Record>
++ <PropertyValue Property="Updatable" Bool="false"/>
++ </Record>
++ </Annotation>
++ <Annotation Term="Capabilities.DeleteRestrictions">
++ <Record>
++ <PropertyValue Property="Deletable" Bool="false"/>
++ </Record>
++ </Annotation>
++ <Annotation Term="Redfish.Uris">
++ <Collection>
++ <String>/redfish/v1/TelemetryService/Triggers</String>
++ </Collection>
++ </Annotation>
++ <NavigationProperty Name="Members" Type="Collection(Triggers.Triggers)">
++ <Annotation Term="OData.Permissions" EnumMember="OData.Permission/Read"/>
++ <Annotation Term="OData.Description" String="The members of this collection."/>
++ <Annotation Term="OData.LongDescription" String="This property shall contain an array of links to the members of this collection."/>
++ <Annotation Term="OData.AutoExpandReferences"/>
++ <Annotation Term="Redfish.Required"/>
++ </NavigationProperty>
++ </EntityType>
++
++ </Schema>
++ </edmx:DataServices>
++</edmx:Edmx>
+--
+2.25.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0006-Revert-Remove-LogService-from-TelemetryService.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0006-Revert-Remove-LogService-from-TelemetryService.patch
new file mode 100644
index 000000000..987a43b4c
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0006-Revert-Remove-LogService-from-TelemetryService.patch
@@ -0,0 +1,26 @@
+From 472ac5f15a19917042852b243e8b668b3ab49e32 Mon Sep 17 00:00:00 2001
+From: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
+Date: Tue, 22 Jun 2021 13:59:48 +0000
+Subject: [PATCH] Revert "Remove LogService from TelemetryService"
+
+This reverts commit 2b3da45876aac57a36d3093379a992d699e7e396.
+---
+ redfish-core/lib/telemetry_service.hpp | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/redfish-core/lib/telemetry_service.hpp b/redfish-core/lib/telemetry_service.hpp
+index 37221c3..f3a1efb 100644
+--- a/redfish-core/lib/telemetry_service.hpp
++++ b/redfish-core/lib/telemetry_service.hpp
+@@ -30,6 +30,8 @@ inline void requestRoutesTelemetryService(App& app)
+ "/redfish/v1/TelemetryService/MetricReports";
+ asyncResp->res.jsonValue["MetricDefinitions"]["@odata.id"] =
+ "/redfish/v1/TelemetryService/MetricDefinitions";
++ asyncResp->res.jsonValue["LogService"]["@odata.id"] =
++ "/redfish/v1/Managers/bmc/LogServices/Journal";
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](
+--
+2.25.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0007-event-service-fix-added-Context-field-to-response.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0007-event-service-fix-added-Context-field-to-response.patch
new file mode 100644
index 000000000..ffab743f6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0007-event-service-fix-added-Context-field-to-response.patch
@@ -0,0 +1,29 @@
+From 0ca8c383db8c9afbce63380955a20ada0acc20b7 Mon Sep 17 00:00:00 2001
+From: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
+Date: Wed, 2 Jun 2021 12:44:43 +0000
+Subject: [PATCH] event service fix, added Context field to response
+
+Tested:
+ - Context field is present
+ - No regression detected
+
+Signed-off-by: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
+---
+ redfish-core/include/event_service_manager.hpp | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
+index 2b957ea..289886b 100644
+--- a/redfish-core/include/event_service_manager.hpp
++++ b/redfish-core/include/event_service_manager.hpp
+@@ -556,6 +556,7 @@ class Subscription
+ << id;
+ return;
+ }
++ msg["Context"] = customText;
+
+ this->sendEvent(
+ msg.dump(2, ' ', true, nlohmann::json::error_handler_t::replace));
+--
+2.25.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0008-Generalize-ReadingType-in-MetricDefinition.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0008-Generalize-ReadingType-in-MetricDefinition.patch
new file mode 100644
index 000000000..bd6e64346
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0008-Generalize-ReadingType-in-MetricDefinition.patch
@@ -0,0 +1,93 @@
+From d9baec3ccdff5ed4d1620f374a252c769de5b45b Mon Sep 17 00:00:00 2001
+From: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
+Date: Thu, 19 Aug 2021 10:55:38 +0000
+Subject: [PATCH] Generalize ReadingType in MetricDefinition
+
+Recent addition of PMT required adding new type of sensor 'count', which
+doesnt comply with any of Redfish-defined Sensor.ReadingType values.
+
+To support property of this kind MetricDefinition implementation was
+altered to support sensor types not covered by Redfish types by
+a 'fallback' to direct usage of sensor type. Populating 'Units' was also
+modified, so it won't be shown if value does not have any units mapped.
+
+Testing:
+- PMT counters are shown properly in MetricDefinitions/Count
+- Redfish Validator passes
+---
+ redfish-core/lib/metric_definition.hpp | 25 ++++++++++++++++++-------
+ 1 file changed, 18 insertions(+), 7 deletions(-)
+
+diff --git a/redfish-core/lib/metric_definition.hpp b/redfish-core/lib/metric_definition.hpp
+index 019168b..df29b65 100644
+--- a/redfish-core/lib/metric_definition.hpp
++++ b/redfish-core/lib/metric_definition.hpp
+@@ -33,6 +33,18 @@ bool containsOdata(const nlohmann::json& json, const std::string& odataId)
+ return it != json.end();
+ }
+
++std::string groupName(const std::string& sensorType)
++{
++ std::string group = sensors::toReadingType(sensorType);
++ if (group.empty())
++ {
++ // Fallback for types not covered by standard Redfish Sensor.ReadingType
++ group = sensorType;
++ group[0] = static_cast<char>(std::toupper(group[0]));
++ }
++ return group;
++}
++
+ void addMembers(crow::Response& res,
+ const boost::container::flat_map<std::string, std::string>& el)
+ {
+@@ -52,8 +64,7 @@ void addMembers(crow::Response& res,
+ nlohmann::json& members = res.jsonValue["Members"];
+
+ const std::string odataId =
+- std::string(telemetry::metricDefinitionUri) +
+- sensors::toReadingType(type);
++ std::string(telemetry::metricDefinitionUri) + groupName(type);
+
+ if (!containsOdata(members, odataId))
+ {
+@@ -149,15 +160,15 @@ inline void requestRoutesMetricDefinitionCollection(App& app)
+ namespace telemetry
+ {
+
+-bool isSensorIdSupported(std::string_view readingType)
++bool isSensorIdSupported(std::string_view group)
+ {
+ for (const std::pair<std::string_view, std::vector<const char*>>&
+ typeToPaths : sensors::dbus::paths)
+ {
+ for (const char* supportedPath : typeToPaths.second)
+ {
+- if (readingType ==
+- sensors::toReadingType(
++ if (group ==
++ groupName(
+ sdbusplus::message::object_path(supportedPath).filename()))
+ {
+ return true;
+@@ -168,7 +179,7 @@ bool isSensorIdSupported(std::string_view readingType)
+ }
+
+ void addMetricProperty(
+- bmcweb::AsyncResp& asyncResp, const std::string& readingType,
++ bmcweb::AsyncResp& asyncResp, const std::string& group,
+ const boost::container::flat_map<std::string, std::string>& el)
+ {
+ nlohmann::json& metricProperties =
+@@ -179,7 +190,7 @@ void addMetricProperty(
+ std::string sensorId;
+ if (dbus::utility::getNthStringFromPath(dbusSensor, 3, sensorId))
+ {
+- if (sensors::toReadingType(sensorId) == readingType)
++ if (groupName(sensorId) == group)
+ {
+ metricProperties.push_back(redfishSensor);
+ }
+--
+2.25.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0009-Add-support-for-deleting-terminated-subscriptions.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0009-Add-support-for-deleting-terminated-subscriptions.patch
new file mode 100644
index 000000000..548e3d9c6
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0009-Add-support-for-deleting-terminated-subscriptions.patch
@@ -0,0 +1,46 @@
+From ef83a4fb14648edc6c8370363ff88fb6f060a43b Mon Sep 17 00:00:00 2001
+From: P Dheeraj Srujan Kumar <p.dheeraj.srujan.kumar@intel.com>
+Date: Mon, 20 Sep 2021 21:55:57 +0530
+Subject: [PATCH] Add support for deleting terminated subscriptions
+
+Added functionality to delete/remove event subscription(s) which are
+configured to Terminate after retries.
+
+Currently, when an Event is subscribed with Retry Policy as
+"TerminateAfterRetries", the state of the connection is set to
+"Terminated" after retrying, but the Subscription is not removed.
+This commit adds the functionality to detect terminated connection and
+remove the respective subscription.
+
+This commit adds this check for metric reports.
+
+Tested:
+ - Created a Subscription with
+ DeliveryRetryPolicy: "TerminateAfterRetries"
+ - Received Events successfully on Event listener
+ - Once the Event listener was stopped, the Subscription was
+ removed/deleted after retries.
+
+Change-Id: I3cb0af5bc24411cddcdb3d1d9de25e8e9144106c
+Signed-off-by: P Dheeraj Srujan Kumar <p.dheeraj.srujan.kumar@intel.com>
+---
+ redfish-core/include/event_service_manager.hpp | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
+index c9e2812..c2fefb3 100644
+--- a/redfish-core/include/event_service_manager.hpp
++++ b/redfish-core/include/event_service_manager.hpp
+@@ -1535,6 +1535,9 @@ class EventServiceManager
+
+ std::variant<telemetry::TimestampReadings>& readings =
+ found->second;
++
++ this->deleteTerminatedSubcriptions();
++
+ for (const auto& it :
+ EventServiceManager::getInstance().subscriptionsMap)
+ {
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/README b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/README
new file mode 100644
index 000000000..fd88e9e18
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/README
@@ -0,0 +1,30 @@
+These patches are mirror of upstream TelemetryService implementation.
+Until change is integrated they will be manually merged here to enable feature in Intel builds.
+
+Current revisions:
+- Add support for MetricDefinition scheme
+ https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/33363/93
+
+- Sync Telmetry service with EventService
+ https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/38798/40
+
+- Switched bmcweb to use new telemetry service API
+ https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/44270/5
+
+- Add support for MetricDefinition property in MetricReport
+ https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/44512/9
+
+- Add GET method for TriggerCollection
+ file://telemetry/0005-Add-GET-method-for-TriggerCollection.patch
+
+- LogService field, actual implementation will be upstreamed with triggers feature
+ file://telemetry/0006-Revert-Remove-LogService-from-TelemetryService.patch
+
+- Event service fix for Context field
+ file://telemetry/0007-event-service-fix-added-Context-field-to-response.patch
+
+- Generalize ReadingType in MetricDefinition
+ file://telemetry/0008-Generalize-ReadingType-in-MetricDefinition.patch
+
+- Add support for deleting terminated subscriptions
+ file://telemetry/0009-Add-support-for-deleting-terminated-subscriptions.patch