xref: /openbmc/bmcweb/features/redfish/lib/metric_report_definition.hpp (revision 081ebf06b4c947e828408029273699ff2d49a54f)
1*081ebf06SWludzik, Jozef #pragma once
2*081ebf06SWludzik, Jozef 
3*081ebf06SWludzik, Jozef #include "node.hpp"
4*081ebf06SWludzik, Jozef #include "utils/telemetry_utils.hpp"
5*081ebf06SWludzik, Jozef #include "utils/time_utils.hpp"
6*081ebf06SWludzik, Jozef 
7*081ebf06SWludzik, Jozef #include <tuple>
8*081ebf06SWludzik, Jozef #include <variant>
9*081ebf06SWludzik, Jozef 
10*081ebf06SWludzik, Jozef namespace redfish
11*081ebf06SWludzik, Jozef {
12*081ebf06SWludzik, Jozef 
13*081ebf06SWludzik, Jozef namespace telemetry
14*081ebf06SWludzik, Jozef {
15*081ebf06SWludzik, Jozef 
16*081ebf06SWludzik, Jozef using ReadingParameters =
17*081ebf06SWludzik, Jozef     std::vector<std::tuple<sdbusplus::message::object_path, std::string,
18*081ebf06SWludzik, Jozef                            std::string, std::string>>;
19*081ebf06SWludzik, Jozef 
20*081ebf06SWludzik, Jozef inline void fillReportDefinition(
21*081ebf06SWludzik, Jozef     const std::shared_ptr<AsyncResp>& asyncResp, const std::string& id,
22*081ebf06SWludzik, Jozef     const std::vector<
23*081ebf06SWludzik, Jozef         std::pair<std::string, std::variant<std::string, bool, uint64_t,
24*081ebf06SWludzik, Jozef                                             ReadingParameters>>>& ret)
25*081ebf06SWludzik, Jozef {
26*081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["@odata.type"] =
27*081ebf06SWludzik, Jozef         "#MetricReportDefinition.v1_3_0.MetricReportDefinition";
28*081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["@odata.id"] =
29*081ebf06SWludzik, Jozef         telemetry::metricReportDefinitionUri + id;
30*081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["Id"] = id;
31*081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["Name"] = id;
32*081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["MetricReport"]["@odata.id"] =
33*081ebf06SWludzik, Jozef         telemetry::metricReportUri + id;
34*081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
35*081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["ReportUpdates"] = "Overwrite";
36*081ebf06SWludzik, Jozef 
37*081ebf06SWludzik, Jozef     const bool* emitsReadingsUpdate = nullptr;
38*081ebf06SWludzik, Jozef     const bool* logToMetricReportsCollection = nullptr;
39*081ebf06SWludzik, Jozef     const ReadingParameters* readingParams = nullptr;
40*081ebf06SWludzik, Jozef     const std::string* reportingType = nullptr;
41*081ebf06SWludzik, Jozef     const uint64_t* interval = nullptr;
42*081ebf06SWludzik, Jozef     for (const auto& [key, var] : ret)
43*081ebf06SWludzik, Jozef     {
44*081ebf06SWludzik, Jozef         if (key == "EmitsReadingsUpdate")
45*081ebf06SWludzik, Jozef         {
46*081ebf06SWludzik, Jozef             emitsReadingsUpdate = std::get_if<bool>(&var);
47*081ebf06SWludzik, Jozef         }
48*081ebf06SWludzik, Jozef         else if (key == "LogToMetricReportsCollection")
49*081ebf06SWludzik, Jozef         {
50*081ebf06SWludzik, Jozef             logToMetricReportsCollection = std::get_if<bool>(&var);
51*081ebf06SWludzik, Jozef         }
52*081ebf06SWludzik, Jozef         else if (key == "ReadingParameters")
53*081ebf06SWludzik, Jozef         {
54*081ebf06SWludzik, Jozef             readingParams = std::get_if<ReadingParameters>(&var);
55*081ebf06SWludzik, Jozef         }
56*081ebf06SWludzik, Jozef         else if (key == "ReportingType")
57*081ebf06SWludzik, Jozef         {
58*081ebf06SWludzik, Jozef             reportingType = std::get_if<std::string>(&var);
59*081ebf06SWludzik, Jozef         }
60*081ebf06SWludzik, Jozef         else if (key == "Interval")
61*081ebf06SWludzik, Jozef         {
62*081ebf06SWludzik, Jozef             interval = std::get_if<uint64_t>(&var);
63*081ebf06SWludzik, Jozef         }
64*081ebf06SWludzik, Jozef     }
65*081ebf06SWludzik, Jozef     if (!emitsReadingsUpdate || !logToMetricReportsCollection ||
66*081ebf06SWludzik, Jozef         !readingParams || !reportingType || !interval)
67*081ebf06SWludzik, Jozef     {
68*081ebf06SWludzik, Jozef         BMCWEB_LOG_ERROR << "Property type mismatch or property is missing";
69*081ebf06SWludzik, Jozef         messages::internalError(asyncResp->res);
70*081ebf06SWludzik, Jozef         return;
71*081ebf06SWludzik, Jozef     }
72*081ebf06SWludzik, Jozef 
73*081ebf06SWludzik, Jozef     std::vector<std::string> redfishReportActions;
74*081ebf06SWludzik, Jozef     redfishReportActions.reserve(2);
75*081ebf06SWludzik, Jozef     if (*emitsReadingsUpdate)
76*081ebf06SWludzik, Jozef     {
77*081ebf06SWludzik, Jozef         redfishReportActions.emplace_back("RedfishEvent");
78*081ebf06SWludzik, Jozef     }
79*081ebf06SWludzik, Jozef     if (*logToMetricReportsCollection)
80*081ebf06SWludzik, Jozef     {
81*081ebf06SWludzik, Jozef         redfishReportActions.emplace_back("LogToMetricReportsCollection");
82*081ebf06SWludzik, Jozef     }
83*081ebf06SWludzik, Jozef 
84*081ebf06SWludzik, Jozef     nlohmann::json metrics = nlohmann::json::array();
85*081ebf06SWludzik, Jozef     for (auto& [sensorPath, operationType, id, metadata] : *readingParams)
86*081ebf06SWludzik, Jozef     {
87*081ebf06SWludzik, Jozef         metrics.push_back({
88*081ebf06SWludzik, Jozef             {"MetricId", id},
89*081ebf06SWludzik, Jozef             {"MetricProperties", {metadata}},
90*081ebf06SWludzik, Jozef         });
91*081ebf06SWludzik, Jozef     }
92*081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["Metrics"] = metrics;
93*081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["MetricReportDefinitionType"] = *reportingType;
94*081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["ReportActions"] = redfishReportActions;
95*081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["Schedule"]["RecurrenceInterval"] =
96*081ebf06SWludzik, Jozef         time_utils::toDurationString(std::chrono::milliseconds(*interval));
97*081ebf06SWludzik, Jozef }
98*081ebf06SWludzik, Jozef } // namespace telemetry
99*081ebf06SWludzik, Jozef 
100*081ebf06SWludzik, Jozef class MetricReportDefinitionCollection : public Node
101*081ebf06SWludzik, Jozef {
102*081ebf06SWludzik, Jozef   public:
103*081ebf06SWludzik, Jozef     MetricReportDefinitionCollection(App& app) :
104*081ebf06SWludzik, Jozef         Node(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/")
105*081ebf06SWludzik, Jozef     {
106*081ebf06SWludzik, Jozef         entityPrivileges = {
107*081ebf06SWludzik, Jozef             {boost::beast::http::verb::get, {{"Login"}}},
108*081ebf06SWludzik, Jozef             {boost::beast::http::verb::head, {{"Login"}}},
109*081ebf06SWludzik, Jozef             {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
110*081ebf06SWludzik, Jozef             {boost::beast::http::verb::put, {{"ConfigureManager"}}},
111*081ebf06SWludzik, Jozef             {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
112*081ebf06SWludzik, Jozef             {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
113*081ebf06SWludzik, Jozef     }
114*081ebf06SWludzik, Jozef 
115*081ebf06SWludzik, Jozef   private:
116*081ebf06SWludzik, Jozef     void doGet(crow::Response& res, const crow::Request&,
117*081ebf06SWludzik, Jozef                const std::vector<std::string>&) override
118*081ebf06SWludzik, Jozef     {
119*081ebf06SWludzik, Jozef         res.jsonValue["@odata.type"] = "#MetricReportDefinitionCollection."
120*081ebf06SWludzik, Jozef                                        "MetricReportDefinitionCollection";
121*081ebf06SWludzik, Jozef         res.jsonValue["@odata.id"] =
122*081ebf06SWludzik, Jozef             "/redfish/v1/TelemetryService/MetricReportDefinitions";
123*081ebf06SWludzik, Jozef         res.jsonValue["Name"] = "Metric Definition Collection";
124*081ebf06SWludzik, Jozef 
125*081ebf06SWludzik, Jozef         auto asyncResp = std::make_shared<AsyncResp>(res);
126*081ebf06SWludzik, Jozef         telemetry::getReportCollection(asyncResp,
127*081ebf06SWludzik, Jozef                                        telemetry::metricReportDefinitionUri);
128*081ebf06SWludzik, Jozef     }
129*081ebf06SWludzik, Jozef };
130*081ebf06SWludzik, Jozef 
131*081ebf06SWludzik, Jozef class MetricReportDefinition : public Node
132*081ebf06SWludzik, Jozef {
133*081ebf06SWludzik, Jozef   public:
134*081ebf06SWludzik, Jozef     MetricReportDefinition(App& app) :
135*081ebf06SWludzik, Jozef         Node(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/",
136*081ebf06SWludzik, Jozef              std::string())
137*081ebf06SWludzik, Jozef     {
138*081ebf06SWludzik, Jozef         entityPrivileges = {
139*081ebf06SWludzik, Jozef             {boost::beast::http::verb::get, {{"Login"}}},
140*081ebf06SWludzik, Jozef             {boost::beast::http::verb::head, {{"Login"}}},
141*081ebf06SWludzik, Jozef             {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
142*081ebf06SWludzik, Jozef             {boost::beast::http::verb::put, {{"ConfigureManager"}}},
143*081ebf06SWludzik, Jozef             {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
144*081ebf06SWludzik, Jozef             {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
145*081ebf06SWludzik, Jozef     }
146*081ebf06SWludzik, Jozef 
147*081ebf06SWludzik, Jozef   private:
148*081ebf06SWludzik, Jozef     void doGet(crow::Response& res, const crow::Request&,
149*081ebf06SWludzik, Jozef                const std::vector<std::string>& params) override
150*081ebf06SWludzik, Jozef     {
151*081ebf06SWludzik, Jozef         auto asyncResp = std::make_shared<AsyncResp>(res);
152*081ebf06SWludzik, Jozef 
153*081ebf06SWludzik, Jozef         if (params.size() != 1)
154*081ebf06SWludzik, Jozef         {
155*081ebf06SWludzik, Jozef             messages::internalError(asyncResp->res);
156*081ebf06SWludzik, Jozef             return;
157*081ebf06SWludzik, Jozef         }
158*081ebf06SWludzik, Jozef 
159*081ebf06SWludzik, Jozef         const std::string& id = params[0];
160*081ebf06SWludzik, Jozef         crow::connections::systemBus->async_method_call(
161*081ebf06SWludzik, Jozef             [asyncResp,
162*081ebf06SWludzik, Jozef              id](const boost::system::error_code ec,
163*081ebf06SWludzik, Jozef                  const std::vector<std::pair<
164*081ebf06SWludzik, Jozef                      std::string, std::variant<std::string, bool, uint64_t,
165*081ebf06SWludzik, Jozef                                                telemetry::ReadingParameters>>>&
166*081ebf06SWludzik, Jozef                      ret) {
167*081ebf06SWludzik, Jozef                 if (ec.value() == EBADR ||
168*081ebf06SWludzik, Jozef                     ec == boost::system::errc::host_unreachable)
169*081ebf06SWludzik, Jozef                 {
170*081ebf06SWludzik, Jozef                     messages::resourceNotFound(asyncResp->res,
171*081ebf06SWludzik, Jozef                                                "MetricReportDefinition", id);
172*081ebf06SWludzik, Jozef                     return;
173*081ebf06SWludzik, Jozef                 }
174*081ebf06SWludzik, Jozef                 if (ec)
175*081ebf06SWludzik, Jozef                 {
176*081ebf06SWludzik, Jozef                     BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
177*081ebf06SWludzik, Jozef                     messages::internalError(asyncResp->res);
178*081ebf06SWludzik, Jozef                     return;
179*081ebf06SWludzik, Jozef                 }
180*081ebf06SWludzik, Jozef 
181*081ebf06SWludzik, Jozef                 telemetry::fillReportDefinition(asyncResp, id, ret);
182*081ebf06SWludzik, Jozef             },
183*081ebf06SWludzik, Jozef             telemetry::service, telemetry::getDbusReportPath(id),
184*081ebf06SWludzik, Jozef             "org.freedesktop.DBus.Properties", "GetAll",
185*081ebf06SWludzik, Jozef             telemetry::reportInterface);
186*081ebf06SWludzik, Jozef     }
187*081ebf06SWludzik, Jozef };
188*081ebf06SWludzik, Jozef } // namespace redfish
189