xref: /openbmc/bmcweb/features/redfish/lib/metric_report_definition.hpp (revision 7e860f1550c8686eec42f7a75bc5f2ef51e756ad)
1081ebf06SWludzik, Jozef #pragma once
2081ebf06SWludzik, Jozef 
34dbb8aeaSWludzik, Jozef #include "sensors.hpp"
4081ebf06SWludzik, Jozef #include "utils/telemetry_utils.hpp"
5081ebf06SWludzik, Jozef #include "utils/time_utils.hpp"
6081ebf06SWludzik, Jozef 
7*7e860f15SJohn Edward Broadbent #include <app.hpp>
84dbb8aeaSWludzik, Jozef #include <boost/container/flat_map.hpp>
94dbb8aeaSWludzik, Jozef 
10081ebf06SWludzik, Jozef #include <tuple>
11081ebf06SWludzik, Jozef #include <variant>
12081ebf06SWludzik, Jozef 
13081ebf06SWludzik, Jozef namespace redfish
14081ebf06SWludzik, Jozef {
15081ebf06SWludzik, Jozef 
16081ebf06SWludzik, Jozef namespace telemetry
17081ebf06SWludzik, Jozef {
18081ebf06SWludzik, Jozef 
19081ebf06SWludzik, Jozef using ReadingParameters =
20081ebf06SWludzik, Jozef     std::vector<std::tuple<sdbusplus::message::object_path, std::string,
21081ebf06SWludzik, Jozef                            std::string, std::string>>;
22081ebf06SWludzik, Jozef 
23081ebf06SWludzik, Jozef inline void fillReportDefinition(
248d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id,
25081ebf06SWludzik, Jozef     const std::vector<
26081ebf06SWludzik, Jozef         std::pair<std::string, std::variant<std::string, bool, uint64_t,
27081ebf06SWludzik, Jozef                                             ReadingParameters>>>& ret)
28081ebf06SWludzik, Jozef {
29081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["@odata.type"] =
30081ebf06SWludzik, Jozef         "#MetricReportDefinition.v1_3_0.MetricReportDefinition";
31081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["@odata.id"] =
32081ebf06SWludzik, Jozef         telemetry::metricReportDefinitionUri + id;
33081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["Id"] = id;
34081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["Name"] = id;
35081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["MetricReport"]["@odata.id"] =
36081ebf06SWludzik, Jozef         telemetry::metricReportUri + id;
37081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
38081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["ReportUpdates"] = "Overwrite";
39081ebf06SWludzik, Jozef 
40081ebf06SWludzik, Jozef     const bool* emitsReadingsUpdate = nullptr;
41081ebf06SWludzik, Jozef     const bool* logToMetricReportsCollection = nullptr;
42081ebf06SWludzik, Jozef     const ReadingParameters* readingParams = nullptr;
43081ebf06SWludzik, Jozef     const std::string* reportingType = nullptr;
44081ebf06SWludzik, Jozef     const uint64_t* interval = nullptr;
45081ebf06SWludzik, Jozef     for (const auto& [key, var] : ret)
46081ebf06SWludzik, Jozef     {
47081ebf06SWludzik, Jozef         if (key == "EmitsReadingsUpdate")
48081ebf06SWludzik, Jozef         {
49081ebf06SWludzik, Jozef             emitsReadingsUpdate = std::get_if<bool>(&var);
50081ebf06SWludzik, Jozef         }
51081ebf06SWludzik, Jozef         else if (key == "LogToMetricReportsCollection")
52081ebf06SWludzik, Jozef         {
53081ebf06SWludzik, Jozef             logToMetricReportsCollection = std::get_if<bool>(&var);
54081ebf06SWludzik, Jozef         }
55081ebf06SWludzik, Jozef         else if (key == "ReadingParameters")
56081ebf06SWludzik, Jozef         {
57081ebf06SWludzik, Jozef             readingParams = std::get_if<ReadingParameters>(&var);
58081ebf06SWludzik, Jozef         }
59081ebf06SWludzik, Jozef         else if (key == "ReportingType")
60081ebf06SWludzik, Jozef         {
61081ebf06SWludzik, Jozef             reportingType = std::get_if<std::string>(&var);
62081ebf06SWludzik, Jozef         }
63081ebf06SWludzik, Jozef         else if (key == "Interval")
64081ebf06SWludzik, Jozef         {
65081ebf06SWludzik, Jozef             interval = std::get_if<uint64_t>(&var);
66081ebf06SWludzik, Jozef         }
67081ebf06SWludzik, Jozef     }
68081ebf06SWludzik, Jozef     if (!emitsReadingsUpdate || !logToMetricReportsCollection ||
69081ebf06SWludzik, Jozef         !readingParams || !reportingType || !interval)
70081ebf06SWludzik, Jozef     {
71081ebf06SWludzik, Jozef         BMCWEB_LOG_ERROR << "Property type mismatch or property is missing";
72081ebf06SWludzik, Jozef         messages::internalError(asyncResp->res);
73081ebf06SWludzik, Jozef         return;
74081ebf06SWludzik, Jozef     }
75081ebf06SWludzik, Jozef 
76081ebf06SWludzik, Jozef     std::vector<std::string> redfishReportActions;
77081ebf06SWludzik, Jozef     redfishReportActions.reserve(2);
78081ebf06SWludzik, Jozef     if (*emitsReadingsUpdate)
79081ebf06SWludzik, Jozef     {
80081ebf06SWludzik, Jozef         redfishReportActions.emplace_back("RedfishEvent");
81081ebf06SWludzik, Jozef     }
82081ebf06SWludzik, Jozef     if (*logToMetricReportsCollection)
83081ebf06SWludzik, Jozef     {
84081ebf06SWludzik, Jozef         redfishReportActions.emplace_back("LogToMetricReportsCollection");
85081ebf06SWludzik, Jozef     }
86081ebf06SWludzik, Jozef 
87081ebf06SWludzik, Jozef     nlohmann::json metrics = nlohmann::json::array();
88081ebf06SWludzik, Jozef     for (auto& [sensorPath, operationType, id, metadata] : *readingParams)
89081ebf06SWludzik, Jozef     {
90081ebf06SWludzik, Jozef         metrics.push_back({
91081ebf06SWludzik, Jozef             {"MetricId", id},
92081ebf06SWludzik, Jozef             {"MetricProperties", {metadata}},
93081ebf06SWludzik, Jozef         });
94081ebf06SWludzik, Jozef     }
95081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["Metrics"] = metrics;
96081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["MetricReportDefinitionType"] = *reportingType;
97081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["ReportActions"] = redfishReportActions;
98081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["Schedule"]["RecurrenceInterval"] =
99081ebf06SWludzik, Jozef         time_utils::toDurationString(std::chrono::milliseconds(*interval));
100081ebf06SWludzik, Jozef }
1014dbb8aeaSWludzik, Jozef 
1024dbb8aeaSWludzik, Jozef struct AddReportArgs
1034dbb8aeaSWludzik, Jozef {
1044dbb8aeaSWludzik, Jozef     std::string name;
1054dbb8aeaSWludzik, Jozef     std::string reportingType;
1064dbb8aeaSWludzik, Jozef     bool emitsReadingsUpdate = false;
1074dbb8aeaSWludzik, Jozef     bool logToMetricReportsCollection = false;
1084dbb8aeaSWludzik, Jozef     uint64_t interval = 0;
1094dbb8aeaSWludzik, Jozef     std::vector<std::pair<std::string, std::vector<std::string>>> metrics;
1104dbb8aeaSWludzik, Jozef };
1114dbb8aeaSWludzik, Jozef 
1124dbb8aeaSWludzik, Jozef inline bool toDbusReportActions(crow::Response& res,
1134dbb8aeaSWludzik, Jozef                                 std::vector<std::string>& actions,
1144dbb8aeaSWludzik, Jozef                                 AddReportArgs& args)
1154dbb8aeaSWludzik, Jozef {
1164dbb8aeaSWludzik, Jozef     size_t index = 0;
1174dbb8aeaSWludzik, Jozef     for (auto& action : actions)
1184dbb8aeaSWludzik, Jozef     {
1194dbb8aeaSWludzik, Jozef         if (action == "RedfishEvent")
1204dbb8aeaSWludzik, Jozef         {
1214dbb8aeaSWludzik, Jozef             args.emitsReadingsUpdate = true;
1224dbb8aeaSWludzik, Jozef         }
1234dbb8aeaSWludzik, Jozef         else if (action == "LogToMetricReportsCollection")
1244dbb8aeaSWludzik, Jozef         {
1254dbb8aeaSWludzik, Jozef             args.logToMetricReportsCollection = true;
1264dbb8aeaSWludzik, Jozef         }
1274dbb8aeaSWludzik, Jozef         else
1284dbb8aeaSWludzik, Jozef         {
1294dbb8aeaSWludzik, Jozef             messages::propertyValueNotInList(
1304dbb8aeaSWludzik, Jozef                 res, action, "ReportActions/" + std::to_string(index));
1314dbb8aeaSWludzik, Jozef             return false;
1324dbb8aeaSWludzik, Jozef         }
1334dbb8aeaSWludzik, Jozef         index++;
1344dbb8aeaSWludzik, Jozef     }
1354dbb8aeaSWludzik, Jozef     return true;
1364dbb8aeaSWludzik, Jozef }
1374dbb8aeaSWludzik, Jozef 
1384dbb8aeaSWludzik, Jozef inline bool getUserParameters(crow::Response& res, const crow::Request& req,
1394dbb8aeaSWludzik, Jozef                               AddReportArgs& args)
1404dbb8aeaSWludzik, Jozef {
1414dbb8aeaSWludzik, Jozef     std::vector<nlohmann::json> metrics;
1424dbb8aeaSWludzik, Jozef     std::vector<std::string> reportActions;
1434dbb8aeaSWludzik, Jozef     std::optional<nlohmann::json> schedule;
1444dbb8aeaSWludzik, Jozef     if (!json_util::readJson(req, res, "Id", args.name, "Metrics", metrics,
1454dbb8aeaSWludzik, Jozef                              "MetricReportDefinitionType", args.reportingType,
1464dbb8aeaSWludzik, Jozef                              "ReportActions", reportActions, "Schedule",
1474dbb8aeaSWludzik, Jozef                              schedule))
1484dbb8aeaSWludzik, Jozef     {
1494dbb8aeaSWludzik, Jozef         return false;
1504dbb8aeaSWludzik, Jozef     }
1514dbb8aeaSWludzik, Jozef 
1524dbb8aeaSWludzik, Jozef     constexpr const char* allowedCharactersInName =
1534dbb8aeaSWludzik, Jozef         "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
1544dbb8aeaSWludzik, Jozef     if (args.name.empty() || args.name.find_first_not_of(
1554dbb8aeaSWludzik, Jozef                                  allowedCharactersInName) != std::string::npos)
1564dbb8aeaSWludzik, Jozef     {
1574dbb8aeaSWludzik, Jozef         BMCWEB_LOG_ERROR << "Failed to match " << args.name
1584dbb8aeaSWludzik, Jozef                          << " with allowed character "
1594dbb8aeaSWludzik, Jozef                          << allowedCharactersInName;
1604dbb8aeaSWludzik, Jozef         messages::propertyValueIncorrect(res, "Id", args.name);
1614dbb8aeaSWludzik, Jozef         return false;
1624dbb8aeaSWludzik, Jozef     }
1634dbb8aeaSWludzik, Jozef 
1644dbb8aeaSWludzik, Jozef     if (args.reportingType != "Periodic" && args.reportingType != "OnRequest")
1654dbb8aeaSWludzik, Jozef     {
1664dbb8aeaSWludzik, Jozef         messages::propertyValueNotInList(res, args.reportingType,
1674dbb8aeaSWludzik, Jozef                                          "MetricReportDefinitionType");
1684dbb8aeaSWludzik, Jozef         return false;
1694dbb8aeaSWludzik, Jozef     }
1704dbb8aeaSWludzik, Jozef 
1714dbb8aeaSWludzik, Jozef     if (!toDbusReportActions(res, reportActions, args))
1724dbb8aeaSWludzik, Jozef     {
1734dbb8aeaSWludzik, Jozef         return false;
1744dbb8aeaSWludzik, Jozef     }
1754dbb8aeaSWludzik, Jozef 
1764dbb8aeaSWludzik, Jozef     if (args.reportingType == "Periodic")
1774dbb8aeaSWludzik, Jozef     {
1784dbb8aeaSWludzik, Jozef         if (!schedule)
1794dbb8aeaSWludzik, Jozef         {
1804dbb8aeaSWludzik, Jozef             messages::createFailedMissingReqProperties(res, "Schedule");
1814dbb8aeaSWludzik, Jozef             return false;
1824dbb8aeaSWludzik, Jozef         }
1834dbb8aeaSWludzik, Jozef 
1844dbb8aeaSWludzik, Jozef         std::string durationStr;
1854dbb8aeaSWludzik, Jozef         if (!json_util::readJson(*schedule, res, "RecurrenceInterval",
1864dbb8aeaSWludzik, Jozef                                  durationStr))
1874dbb8aeaSWludzik, Jozef         {
1884dbb8aeaSWludzik, Jozef             return false;
1894dbb8aeaSWludzik, Jozef         }
1904dbb8aeaSWludzik, Jozef 
1914dbb8aeaSWludzik, Jozef         std::optional<std::chrono::milliseconds> durationNum =
1924dbb8aeaSWludzik, Jozef             time_utils::fromDurationString(durationStr);
1934dbb8aeaSWludzik, Jozef         if (!durationNum)
1944dbb8aeaSWludzik, Jozef         {
1954dbb8aeaSWludzik, Jozef             messages::propertyValueIncorrect(res, "RecurrenceInterval",
1964dbb8aeaSWludzik, Jozef                                              durationStr);
1974dbb8aeaSWludzik, Jozef             return false;
1984dbb8aeaSWludzik, Jozef         }
1994dbb8aeaSWludzik, Jozef         args.interval = static_cast<uint64_t>(durationNum->count());
2004dbb8aeaSWludzik, Jozef     }
2014dbb8aeaSWludzik, Jozef 
2024dbb8aeaSWludzik, Jozef     args.metrics.reserve(metrics.size());
2034dbb8aeaSWludzik, Jozef     for (auto& m : metrics)
2044dbb8aeaSWludzik, Jozef     {
2054dbb8aeaSWludzik, Jozef         std::string id;
2064dbb8aeaSWludzik, Jozef         std::vector<std::string> uris;
2074dbb8aeaSWludzik, Jozef         if (!json_util::readJson(m, res, "MetricId", id, "MetricProperties",
2084dbb8aeaSWludzik, Jozef                                  uris))
2094dbb8aeaSWludzik, Jozef         {
2104dbb8aeaSWludzik, Jozef             return false;
2114dbb8aeaSWludzik, Jozef         }
2124dbb8aeaSWludzik, Jozef 
2134dbb8aeaSWludzik, Jozef         args.metrics.emplace_back(std::move(id), std::move(uris));
2144dbb8aeaSWludzik, Jozef     }
2154dbb8aeaSWludzik, Jozef 
2164dbb8aeaSWludzik, Jozef     return true;
2174dbb8aeaSWludzik, Jozef }
2184dbb8aeaSWludzik, Jozef 
2194dbb8aeaSWludzik, Jozef inline bool getChassisSensorNode(
2208d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2214dbb8aeaSWludzik, Jozef     const std::vector<std::pair<std::string, std::vector<std::string>>>&
2224dbb8aeaSWludzik, Jozef         metrics,
2234dbb8aeaSWludzik, Jozef     boost::container::flat_set<std::pair<std::string, std::string>>& matched)
2244dbb8aeaSWludzik, Jozef {
2254dbb8aeaSWludzik, Jozef     for (const auto& [id, uris] : metrics)
2264dbb8aeaSWludzik, Jozef     {
2274dbb8aeaSWludzik, Jozef         for (size_t i = 0; i < uris.size(); i++)
2284dbb8aeaSWludzik, Jozef         {
2294dbb8aeaSWludzik, Jozef             const std::string& uri = uris[i];
2304dbb8aeaSWludzik, Jozef             std::string chassis;
2314dbb8aeaSWludzik, Jozef             std::string node;
2324dbb8aeaSWludzik, Jozef 
2334dbb8aeaSWludzik, Jozef             if (!boost::starts_with(uri, "/redfish/v1/Chassis/") ||
2344dbb8aeaSWludzik, Jozef                 !dbus::utility::getNthStringFromPath(uri, 3, chassis) ||
2354dbb8aeaSWludzik, Jozef                 !dbus::utility::getNthStringFromPath(uri, 4, node))
2364dbb8aeaSWludzik, Jozef             {
2374dbb8aeaSWludzik, Jozef                 BMCWEB_LOG_ERROR << "Failed to get chassis and sensor Node "
2384dbb8aeaSWludzik, Jozef                                     "from "
2394dbb8aeaSWludzik, Jozef                                  << uri;
2404dbb8aeaSWludzik, Jozef                 messages::propertyValueIncorrect(asyncResp->res, uri,
2414dbb8aeaSWludzik, Jozef                                                  "MetricProperties/" +
2424dbb8aeaSWludzik, Jozef                                                      std::to_string(i));
2434dbb8aeaSWludzik, Jozef                 return false;
2444dbb8aeaSWludzik, Jozef             }
2454dbb8aeaSWludzik, Jozef 
2464dbb8aeaSWludzik, Jozef             if (boost::ends_with(node, "#"))
2474dbb8aeaSWludzik, Jozef             {
2484dbb8aeaSWludzik, Jozef                 node.pop_back();
2494dbb8aeaSWludzik, Jozef             }
2504dbb8aeaSWludzik, Jozef 
2514dbb8aeaSWludzik, Jozef             matched.emplace(std::move(chassis), std::move(node));
2524dbb8aeaSWludzik, Jozef         }
2534dbb8aeaSWludzik, Jozef     }
2544dbb8aeaSWludzik, Jozef     return true;
2554dbb8aeaSWludzik, Jozef }
2564dbb8aeaSWludzik, Jozef 
2574dbb8aeaSWludzik, Jozef class AddReport
2584dbb8aeaSWludzik, Jozef {
2594dbb8aeaSWludzik, Jozef   public:
2608d1b46d7Szhanghch05     AddReport(AddReportArgs argsIn,
2618d1b46d7Szhanghch05               const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) :
2628d1b46d7Szhanghch05         asyncResp(asyncResp),
2638d1b46d7Szhanghch05         args{std::move(argsIn)}
2644dbb8aeaSWludzik, Jozef     {}
2654dbb8aeaSWludzik, Jozef     ~AddReport()
2664dbb8aeaSWludzik, Jozef     {
2674dbb8aeaSWludzik, Jozef         if (asyncResp->res.result() != boost::beast::http::status::ok)
2684dbb8aeaSWludzik, Jozef         {
2694dbb8aeaSWludzik, Jozef             return;
2704dbb8aeaSWludzik, Jozef         }
2714dbb8aeaSWludzik, Jozef 
2724dbb8aeaSWludzik, Jozef         telemetry::ReadingParameters readingParams;
2734dbb8aeaSWludzik, Jozef         readingParams.reserve(args.metrics.size());
2744dbb8aeaSWludzik, Jozef 
2754dbb8aeaSWludzik, Jozef         for (const auto& [id, uris] : args.metrics)
2764dbb8aeaSWludzik, Jozef         {
2774dbb8aeaSWludzik, Jozef             for (size_t i = 0; i < uris.size(); i++)
2784dbb8aeaSWludzik, Jozef             {
2794dbb8aeaSWludzik, Jozef                 const std::string& uri = uris[i];
2804dbb8aeaSWludzik, Jozef                 auto el = uriToDbus.find(uri);
2814dbb8aeaSWludzik, Jozef                 if (el == uriToDbus.end())
2824dbb8aeaSWludzik, Jozef                 {
2834dbb8aeaSWludzik, Jozef                     BMCWEB_LOG_ERROR << "Failed to find DBus sensor "
2844dbb8aeaSWludzik, Jozef                                         "corresponding to URI "
2854dbb8aeaSWludzik, Jozef                                      << uri;
2864dbb8aeaSWludzik, Jozef                     messages::propertyValueNotInList(asyncResp->res, uri,
2874dbb8aeaSWludzik, Jozef                                                      "MetricProperties/" +
2884dbb8aeaSWludzik, Jozef                                                          std::to_string(i));
2894dbb8aeaSWludzik, Jozef                     return;
2904dbb8aeaSWludzik, Jozef                 }
2914dbb8aeaSWludzik, Jozef 
2924dbb8aeaSWludzik, Jozef                 const std::string& dbusPath = el->second;
2934dbb8aeaSWludzik, Jozef                 readingParams.emplace_back(dbusPath, "SINGLE", id, uri);
2944dbb8aeaSWludzik, Jozef             }
2954dbb8aeaSWludzik, Jozef         }
2968d1b46d7Szhanghch05         const std::shared_ptr<bmcweb::AsyncResp> aResp = asyncResp;
2974dbb8aeaSWludzik, Jozef         crow::connections::systemBus->async_method_call(
2988d1b46d7Szhanghch05             [aResp, name = args.name, uriToDbus = std::move(uriToDbus)](
2994dbb8aeaSWludzik, Jozef                 const boost::system::error_code ec, const std::string&) {
3004dbb8aeaSWludzik, Jozef                 if (ec == boost::system::errc::file_exists)
3014dbb8aeaSWludzik, Jozef                 {
3024dbb8aeaSWludzik, Jozef                     messages::resourceAlreadyExists(
3038d1b46d7Szhanghch05                         aResp->res, "MetricReportDefinition", "Id", name);
3044dbb8aeaSWludzik, Jozef                     return;
3054dbb8aeaSWludzik, Jozef                 }
3064dbb8aeaSWludzik, Jozef                 if (ec == boost::system::errc::too_many_files_open)
3074dbb8aeaSWludzik, Jozef                 {
3088d1b46d7Szhanghch05                     messages::createLimitReachedForResource(aResp->res);
3094dbb8aeaSWludzik, Jozef                     return;
3104dbb8aeaSWludzik, Jozef                 }
3114dbb8aeaSWludzik, Jozef                 if (ec == boost::system::errc::argument_list_too_long)
3124dbb8aeaSWludzik, Jozef                 {
3134dbb8aeaSWludzik, Jozef                     nlohmann::json metricProperties = nlohmann::json::array();
3144dbb8aeaSWludzik, Jozef                     for (const auto& [uri, _] : uriToDbus)
3154dbb8aeaSWludzik, Jozef                     {
3164dbb8aeaSWludzik, Jozef                         metricProperties.emplace_back(uri);
3174dbb8aeaSWludzik, Jozef                     }
3184dbb8aeaSWludzik, Jozef                     messages::propertyValueIncorrect(
3198d1b46d7Szhanghch05                         aResp->res, metricProperties, "MetricProperties");
3204dbb8aeaSWludzik, Jozef                     return;
3214dbb8aeaSWludzik, Jozef                 }
3224dbb8aeaSWludzik, Jozef                 if (ec)
3234dbb8aeaSWludzik, Jozef                 {
3248d1b46d7Szhanghch05                     messages::internalError(aResp->res);
3254dbb8aeaSWludzik, Jozef                     BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
3264dbb8aeaSWludzik, Jozef                     return;
3274dbb8aeaSWludzik, Jozef                 }
3284dbb8aeaSWludzik, Jozef 
3298d1b46d7Szhanghch05                 messages::created(aResp->res);
3304dbb8aeaSWludzik, Jozef             },
3314dbb8aeaSWludzik, Jozef             telemetry::service, "/xyz/openbmc_project/Telemetry/Reports",
3324dbb8aeaSWludzik, Jozef             "xyz.openbmc_project.Telemetry.ReportManager", "AddReport",
3334dbb8aeaSWludzik, Jozef             "TelemetryService/" + args.name, args.reportingType,
3344dbb8aeaSWludzik, Jozef             args.emitsReadingsUpdate, args.logToMetricReportsCollection,
3354dbb8aeaSWludzik, Jozef             args.interval, readingParams);
3364dbb8aeaSWludzik, Jozef     }
3374dbb8aeaSWludzik, Jozef 
3384dbb8aeaSWludzik, Jozef     void insert(const boost::container::flat_map<std::string, std::string>& el)
3394dbb8aeaSWludzik, Jozef     {
3404dbb8aeaSWludzik, Jozef         uriToDbus.insert(el.begin(), el.end());
3414dbb8aeaSWludzik, Jozef     }
3424dbb8aeaSWludzik, Jozef 
3434dbb8aeaSWludzik, Jozef   private:
3448d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp> asyncResp;
3454dbb8aeaSWludzik, Jozef     AddReportArgs args;
3464dbb8aeaSWludzik, Jozef     boost::container::flat_map<std::string, std::string> uriToDbus{};
3474dbb8aeaSWludzik, Jozef };
348081ebf06SWludzik, Jozef } // namespace telemetry
349081ebf06SWludzik, Jozef 
350*7e860f15SJohn Edward Broadbent inline void requestRoutesMetricReportDefinitionCollection(App& app)
351081ebf06SWludzik, Jozef {
352*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/")
353*7e860f15SJohn Edward Broadbent         .privileges({"Login"})
354*7e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
355*7e860f15SJohn Edward Broadbent             [](const crow::Request&,
356*7e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
3578d1b46d7Szhanghch05                 asyncResp->res.jsonValue["@odata.type"] =
3588d1b46d7Szhanghch05                     "#MetricReportDefinitionCollection."
359081ebf06SWludzik, Jozef                     "MetricReportDefinitionCollection";
3608d1b46d7Szhanghch05                 asyncResp->res.jsonValue["@odata.id"] =
361081ebf06SWludzik, Jozef                     "/redfish/v1/TelemetryService/MetricReportDefinitions";
362*7e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["Name"] =
363*7e860f15SJohn Edward Broadbent                     "Metric Definition Collection";
364081ebf06SWludzik, Jozef 
365*7e860f15SJohn Edward Broadbent                 telemetry::getReportCollection(
366*7e860f15SJohn Edward Broadbent                     asyncResp, telemetry::metricReportDefinitionUri);
367*7e860f15SJohn Edward Broadbent             });
3684dbb8aeaSWludzik, Jozef 
369*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/")
370*7e860f15SJohn Edward Broadbent         .privileges({"ConfigureManager"})
371*7e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
372*7e860f15SJohn Edward Broadbent             [](const crow::Request& req,
373*7e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
3744dbb8aeaSWludzik, Jozef                 telemetry::AddReportArgs args;
3758d1b46d7Szhanghch05                 if (!telemetry::getUserParameters(asyncResp->res, req, args))
3764dbb8aeaSWludzik, Jozef                 {
3774dbb8aeaSWludzik, Jozef                     return;
3784dbb8aeaSWludzik, Jozef                 }
3794dbb8aeaSWludzik, Jozef 
3804dbb8aeaSWludzik, Jozef                 boost::container::flat_set<std::pair<std::string, std::string>>
3814dbb8aeaSWludzik, Jozef                     chassisSensors;
3824dbb8aeaSWludzik, Jozef                 if (!telemetry::getChassisSensorNode(asyncResp, args.metrics,
3834dbb8aeaSWludzik, Jozef                                                      chassisSensors))
3844dbb8aeaSWludzik, Jozef                 {
3854dbb8aeaSWludzik, Jozef                     return;
3864dbb8aeaSWludzik, Jozef                 }
3874dbb8aeaSWludzik, Jozef 
388*7e860f15SJohn Edward Broadbent                 auto addReportReq = std::make_shared<telemetry::AddReport>(
389*7e860f15SJohn Edward Broadbent                     std::move(args), asyncResp);
3904dbb8aeaSWludzik, Jozef                 for (const auto& [chassis, sensorType] : chassisSensors)
3914dbb8aeaSWludzik, Jozef                 {
3924dbb8aeaSWludzik, Jozef                     retrieveUriToDbusMap(
3934dbb8aeaSWludzik, Jozef                         chassis, sensorType,
3944dbb8aeaSWludzik, Jozef                         [asyncResp, addReportReq](
3954dbb8aeaSWludzik, Jozef                             const boost::beast::http::status status,
396*7e860f15SJohn Edward Broadbent                             const boost::container::flat_map<
397*7e860f15SJohn Edward Broadbent                                 std::string, std::string>& uriToDbus) {
3984dbb8aeaSWludzik, Jozef                             if (status != boost::beast::http::status::ok)
3994dbb8aeaSWludzik, Jozef                             {
400*7e860f15SJohn Edward Broadbent                                 BMCWEB_LOG_ERROR
401*7e860f15SJohn Edward Broadbent                                     << "Failed to retrieve URI to dbus "
4024dbb8aeaSWludzik, Jozef                                        "sensors map with err "
4034dbb8aeaSWludzik, Jozef                                     << static_cast<unsigned>(status);
4044dbb8aeaSWludzik, Jozef                                 return;
4054dbb8aeaSWludzik, Jozef                             }
4064dbb8aeaSWludzik, Jozef                             addReportReq->insert(uriToDbus);
4074dbb8aeaSWludzik, Jozef                         });
4084dbb8aeaSWludzik, Jozef                 }
409*7e860f15SJohn Edward Broadbent             });
410081ebf06SWludzik, Jozef }
411081ebf06SWludzik, Jozef 
412*7e860f15SJohn Edward Broadbent inline void requestRoutesMetricReportDefinition(App& app)
413081ebf06SWludzik, Jozef {
414*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
415*7e860f15SJohn Edward Broadbent                  "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/")
416*7e860f15SJohn Edward Broadbent         .privileges({"Login"})
417*7e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
418*7e860f15SJohn Edward Broadbent             [](const crow::Request&,
419*7e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
420*7e860f15SJohn Edward Broadbent                const std::string& id) {
421081ebf06SWludzik, Jozef                 crow::connections::systemBus->async_method_call(
422*7e860f15SJohn Edward Broadbent                     [asyncResp, id](
423*7e860f15SJohn Edward Broadbent                         const boost::system::error_code ec,
424081ebf06SWludzik, Jozef                         const std::vector<std::pair<
425*7e860f15SJohn Edward Broadbent                             std::string,
426*7e860f15SJohn Edward Broadbent                             std::variant<std::string, bool, uint64_t,
427*7e860f15SJohn Edward Broadbent                                          telemetry::ReadingParameters>>>& ret) {
428081ebf06SWludzik, Jozef                         if (ec.value() == EBADR ||
429081ebf06SWludzik, Jozef                             ec == boost::system::errc::host_unreachable)
430081ebf06SWludzik, Jozef                         {
431*7e860f15SJohn Edward Broadbent                             messages::resourceNotFound(
432*7e860f15SJohn Edward Broadbent                                 asyncResp->res, "MetricReportDefinition", id);
433081ebf06SWludzik, Jozef                             return;
434081ebf06SWludzik, Jozef                         }
435081ebf06SWludzik, Jozef                         if (ec)
436081ebf06SWludzik, Jozef                         {
437081ebf06SWludzik, Jozef                             BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
438081ebf06SWludzik, Jozef                             messages::internalError(asyncResp->res);
439081ebf06SWludzik, Jozef                             return;
440081ebf06SWludzik, Jozef                         }
441081ebf06SWludzik, Jozef 
442081ebf06SWludzik, Jozef                         telemetry::fillReportDefinition(asyncResp, id, ret);
443081ebf06SWludzik, Jozef                     },
444081ebf06SWludzik, Jozef                     telemetry::service, telemetry::getDbusReportPath(id),
445081ebf06SWludzik, Jozef                     "org.freedesktop.DBus.Properties", "GetAll",
446081ebf06SWludzik, Jozef                     telemetry::reportInterface);
447*7e860f15SJohn Edward Broadbent             });
448*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
449*7e860f15SJohn Edward Broadbent                  "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/")
450*7e860f15SJohn Edward Broadbent         .privileges({"ConfigureManager"})
451*7e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::delete_)(
452*7e860f15SJohn Edward Broadbent             [](const crow::Request&,
453*7e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
454*7e860f15SJohn Edward Broadbent                const std::string& id)
4554dbb8aeaSWludzik, Jozef 
4564dbb8aeaSWludzik, Jozef             {
4574dbb8aeaSWludzik, Jozef                 const std::string reportPath = telemetry::getDbusReportPath(id);
4584dbb8aeaSWludzik, Jozef 
4594dbb8aeaSWludzik, Jozef                 crow::connections::systemBus->async_method_call(
4604dbb8aeaSWludzik, Jozef                     [asyncResp, id](const boost::system::error_code ec) {
4614dbb8aeaSWludzik, Jozef                         /*
462*7e860f15SJohn Edward Broadbent                          * boost::system::errc and std::errc are missing value
463*7e860f15SJohn Edward Broadbent                          * for EBADR error that is defined in Linux.
4644dbb8aeaSWludzik, Jozef                          */
4654dbb8aeaSWludzik, Jozef                         if (ec.value() == EBADR)
4664dbb8aeaSWludzik, Jozef                         {
467*7e860f15SJohn Edward Broadbent                             messages::resourceNotFound(
468*7e860f15SJohn Edward Broadbent                                 asyncResp->res, "MetricReportDefinition", id);
4694dbb8aeaSWludzik, Jozef                             return;
4704dbb8aeaSWludzik, Jozef                         }
4714dbb8aeaSWludzik, Jozef 
4724dbb8aeaSWludzik, Jozef                         if (ec)
4734dbb8aeaSWludzik, Jozef                         {
4744dbb8aeaSWludzik, Jozef                             BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
4754dbb8aeaSWludzik, Jozef                             messages::internalError(asyncResp->res);
4764dbb8aeaSWludzik, Jozef                             return;
4774dbb8aeaSWludzik, Jozef                         }
4784dbb8aeaSWludzik, Jozef 
479*7e860f15SJohn Edward Broadbent                         asyncResp->res.result(
480*7e860f15SJohn Edward Broadbent                             boost::beast::http::status::no_content);
4814dbb8aeaSWludzik, Jozef                     },
482*7e860f15SJohn Edward Broadbent                     telemetry::service, reportPath,
483*7e860f15SJohn Edward Broadbent                     "xyz.openbmc_project.Object.Delete", "Delete");
484*7e860f15SJohn Edward Broadbent             });
4854dbb8aeaSWludzik, Jozef }
486081ebf06SWludzik, Jozef } // namespace redfish
487