xref: /openbmc/bmcweb/features/redfish/lib/metric_report.hpp (revision 8d1b46d7f8d39db2ba048f9e9007106ca3a28c9b)
1081ebf06SWludzik, Jozef #pragma once
2081ebf06SWludzik, Jozef 
3081ebf06SWludzik, Jozef #include "node.hpp"
4081ebf06SWludzik, Jozef #include "utils/telemetry_utils.hpp"
5081ebf06SWludzik, Jozef 
6081ebf06SWludzik, Jozef namespace redfish
7081ebf06SWludzik, Jozef {
8081ebf06SWludzik, Jozef 
9081ebf06SWludzik, Jozef namespace telemetry
10081ebf06SWludzik, Jozef {
11081ebf06SWludzik, Jozef 
12081ebf06SWludzik, Jozef using Readings =
13081ebf06SWludzik, Jozef     std::vector<std::tuple<std::string, std::string, double, uint64_t>>;
14081ebf06SWludzik, Jozef using TimestampReadings = std::tuple<uint64_t, Readings>;
15081ebf06SWludzik, Jozef 
16081ebf06SWludzik, Jozef inline nlohmann::json toMetricValues(const Readings& readings)
17081ebf06SWludzik, Jozef {
18081ebf06SWludzik, Jozef     nlohmann::json metricValues = nlohmann::json::array_t();
19081ebf06SWludzik, Jozef 
20081ebf06SWludzik, Jozef     for (auto& [id, metadata, sensorValue, timestamp] : readings)
21081ebf06SWludzik, Jozef     {
22081ebf06SWludzik, Jozef         metricValues.push_back({
23081ebf06SWludzik, Jozef             {"MetricId", id},
24081ebf06SWludzik, Jozef             {"MetricProperty", metadata},
25081ebf06SWludzik, Jozef             {"MetricValue", std::to_string(sensorValue)},
26081ebf06SWludzik, Jozef             {"Timestamp",
27081ebf06SWludzik, Jozef              crow::utility::getDateTime(static_cast<time_t>(timestamp))},
28081ebf06SWludzik, Jozef         });
29081ebf06SWludzik, Jozef     }
30081ebf06SWludzik, Jozef 
31081ebf06SWludzik, Jozef     return metricValues;
32081ebf06SWludzik, Jozef }
33081ebf06SWludzik, Jozef 
34*8d1b46d7Szhanghch05 inline void fillReport(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
35081ebf06SWludzik, Jozef                        const std::string& id,
36081ebf06SWludzik, Jozef                        const std::variant<TimestampReadings>& var)
37081ebf06SWludzik, Jozef {
38081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["@odata.type"] =
39081ebf06SWludzik, Jozef         "#MetricReport.v1_3_0.MetricReport";
40081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["@odata.id"] = telemetry::metricReportUri + id;
41081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["Id"] = id;
42081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["Name"] = id;
43081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["MetricReportDefinition"]["@odata.id"] =
44081ebf06SWludzik, Jozef         telemetry::metricReportDefinitionUri + id;
45081ebf06SWludzik, Jozef 
46081ebf06SWludzik, Jozef     const TimestampReadings* timestampReadings =
47081ebf06SWludzik, Jozef         std::get_if<TimestampReadings>(&var);
48081ebf06SWludzik, Jozef     if (!timestampReadings)
49081ebf06SWludzik, Jozef     {
50081ebf06SWludzik, Jozef         BMCWEB_LOG_ERROR << "Property type mismatch or property is missing";
51081ebf06SWludzik, Jozef         messages::internalError(asyncResp->res);
52081ebf06SWludzik, Jozef         return;
53081ebf06SWludzik, Jozef     }
54081ebf06SWludzik, Jozef 
55081ebf06SWludzik, Jozef     const auto& [timestamp, readings] = *timestampReadings;
56081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["Timestamp"] =
57081ebf06SWludzik, Jozef         crow::utility::getDateTime(static_cast<time_t>(timestamp));
58081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["MetricValues"] = toMetricValues(readings);
59081ebf06SWludzik, Jozef }
60081ebf06SWludzik, Jozef } // namespace telemetry
61081ebf06SWludzik, Jozef 
62081ebf06SWludzik, Jozef class MetricReportCollection : public Node
63081ebf06SWludzik, Jozef {
64081ebf06SWludzik, Jozef   public:
65081ebf06SWludzik, Jozef     MetricReportCollection(App& app) :
66081ebf06SWludzik, Jozef         Node(app, "/redfish/v1/TelemetryService/MetricReports/")
67081ebf06SWludzik, Jozef     {
68081ebf06SWludzik, Jozef         entityPrivileges = {
69081ebf06SWludzik, Jozef             {boost::beast::http::verb::get, {{"Login"}}},
70081ebf06SWludzik, Jozef             {boost::beast::http::verb::head, {{"Login"}}},
71081ebf06SWludzik, Jozef             {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
72081ebf06SWludzik, Jozef             {boost::beast::http::verb::put, {{"ConfigureManager"}}},
73081ebf06SWludzik, Jozef             {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
74081ebf06SWludzik, Jozef             {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
75081ebf06SWludzik, Jozef     }
76081ebf06SWludzik, Jozef 
77081ebf06SWludzik, Jozef   private:
78*8d1b46d7Szhanghch05     void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
79*8d1b46d7Szhanghch05                const crow::Request&, const std::vector<std::string>&) override
80081ebf06SWludzik, Jozef     {
81*8d1b46d7Szhanghch05         asyncResp->res.jsonValue["@odata.type"] =
82081ebf06SWludzik, Jozef             "#MetricReportCollection.MetricReportCollection";
83*8d1b46d7Szhanghch05         asyncResp->res.jsonValue["@odata.id"] =
84081ebf06SWludzik, Jozef             "/redfish/v1/TelemetryService/MetricReports";
85*8d1b46d7Szhanghch05         asyncResp->res.jsonValue["Name"] = "Metric Report Collection";
86081ebf06SWludzik, Jozef 
87081ebf06SWludzik, Jozef         telemetry::getReportCollection(asyncResp, telemetry::metricReportUri);
88081ebf06SWludzik, Jozef     }
89081ebf06SWludzik, Jozef };
90081ebf06SWludzik, Jozef 
91081ebf06SWludzik, Jozef class MetricReport : public Node
92081ebf06SWludzik, Jozef {
93081ebf06SWludzik, Jozef   public:
94081ebf06SWludzik, Jozef     MetricReport(App& app) :
95081ebf06SWludzik, Jozef         Node(app, "/redfish/v1/TelemetryService/MetricReports/<str>/",
96081ebf06SWludzik, Jozef              std::string())
97081ebf06SWludzik, Jozef     {
98081ebf06SWludzik, Jozef         entityPrivileges = {
99081ebf06SWludzik, Jozef             {boost::beast::http::verb::get, {{"Login"}}},
100081ebf06SWludzik, Jozef             {boost::beast::http::verb::head, {{"Login"}}},
101081ebf06SWludzik, Jozef             {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
102081ebf06SWludzik, Jozef             {boost::beast::http::verb::put, {{"ConfigureManager"}}},
103081ebf06SWludzik, Jozef             {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
104081ebf06SWludzik, Jozef             {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
105081ebf06SWludzik, Jozef     }
106081ebf06SWludzik, Jozef 
107081ebf06SWludzik, Jozef   private:
108*8d1b46d7Szhanghch05     void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
109*8d1b46d7Szhanghch05                const crow::Request&,
110081ebf06SWludzik, Jozef                const std::vector<std::string>& params) override
111081ebf06SWludzik, Jozef     {
112081ebf06SWludzik, Jozef 
113081ebf06SWludzik, Jozef         if (params.size() != 1)
114081ebf06SWludzik, Jozef         {
115081ebf06SWludzik, Jozef             messages::internalError(asyncResp->res);
116081ebf06SWludzik, Jozef             return;
117081ebf06SWludzik, Jozef         }
118081ebf06SWludzik, Jozef 
119081ebf06SWludzik, Jozef         const std::string& id = params[0];
120081ebf06SWludzik, Jozef         const std::string reportPath = telemetry::getDbusReportPath(id);
121081ebf06SWludzik, Jozef         crow::connections::systemBus->async_method_call(
122081ebf06SWludzik, Jozef             [asyncResp, id, reportPath](const boost::system::error_code& ec) {
123081ebf06SWludzik, Jozef                 if (ec.value() == EBADR ||
124081ebf06SWludzik, Jozef                     ec == boost::system::errc::host_unreachable)
125081ebf06SWludzik, Jozef                 {
126081ebf06SWludzik, Jozef                     messages::resourceNotFound(asyncResp->res, "MetricReport",
127081ebf06SWludzik, Jozef                                                id);
128081ebf06SWludzik, Jozef                     return;
129081ebf06SWludzik, Jozef                 }
130081ebf06SWludzik, Jozef                 if (ec)
131081ebf06SWludzik, Jozef                 {
132081ebf06SWludzik, Jozef                     BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
133081ebf06SWludzik, Jozef                     messages::internalError(asyncResp->res);
134081ebf06SWludzik, Jozef                     return;
135081ebf06SWludzik, Jozef                 }
136081ebf06SWludzik, Jozef 
137081ebf06SWludzik, Jozef                 crow::connections::systemBus->async_method_call(
138081ebf06SWludzik, Jozef                     [asyncResp, id](
139081ebf06SWludzik, Jozef                         const boost::system::error_code ec,
140081ebf06SWludzik, Jozef                         const std::variant<telemetry::TimestampReadings>& ret) {
141081ebf06SWludzik, Jozef                         if (ec)
142081ebf06SWludzik, Jozef                         {
143081ebf06SWludzik, Jozef                             BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
144081ebf06SWludzik, Jozef                             messages::internalError(asyncResp->res);
145081ebf06SWludzik, Jozef                             return;
146081ebf06SWludzik, Jozef                         }
147081ebf06SWludzik, Jozef 
148081ebf06SWludzik, Jozef                         telemetry::fillReport(asyncResp, id, ret);
149081ebf06SWludzik, Jozef                     },
150081ebf06SWludzik, Jozef                     telemetry::service, reportPath,
151081ebf06SWludzik, Jozef                     "org.freedesktop.DBus.Properties", "Get",
152081ebf06SWludzik, Jozef                     telemetry::reportInterface, "Readings");
153081ebf06SWludzik, Jozef             },
154081ebf06SWludzik, Jozef             telemetry::service, reportPath, telemetry::reportInterface,
155081ebf06SWludzik, Jozef             "Update");
156081ebf06SWludzik, Jozef     }
157081ebf06SWludzik, Jozef };
158081ebf06SWludzik, Jozef } // namespace redfish
159