xref: /openbmc/bmcweb/redfish-core/lib/metric_report.hpp (revision 90e97e1d26b78d899a543831a8051dacbbdde71a)
1 #pragma once
2 
3 #include "utils/telemetry_utils.hpp"
4 
5 #include <app.hpp>
6 
7 namespace redfish
8 {
9 
10 namespace telemetry
11 {
12 
13 using Readings =
14     std::vector<std::tuple<std::string, std::string, double, uint64_t>>;
15 using TimestampReadings = std::tuple<uint64_t, Readings>;
16 
17 inline nlohmann::json toMetricValues(const Readings& readings)
18 {
19     nlohmann::json metricValues = nlohmann::json::array_t();
20 
21     for (auto& [id, metadata, sensorValue, timestamp] : readings)
22     {
23         metricValues.push_back({
24             {"MetricId", id},
25             {"MetricProperty", metadata},
26             {"MetricValue", std::to_string(sensorValue)},
27             {"Timestamp",
28              crow::utility::getDateTime(static_cast<time_t>(timestamp))},
29         });
30     }
31 
32     return metricValues;
33 }
34 
35 inline void fillReport(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
36                        const std::string& id,
37                        const std::variant<TimestampReadings>& var)
38 {
39     asyncResp->res.jsonValue["@odata.type"] =
40         "#MetricReport.v1_3_0.MetricReport";
41     asyncResp->res.jsonValue["@odata.id"] = telemetry::metricReportUri + id;
42     asyncResp->res.jsonValue["Id"] = id;
43     asyncResp->res.jsonValue["Name"] = id;
44     asyncResp->res.jsonValue["MetricReportDefinition"]["@odata.id"] =
45         telemetry::metricReportDefinitionUri + id;
46 
47     const TimestampReadings* timestampReadings =
48         std::get_if<TimestampReadings>(&var);
49     if (!timestampReadings)
50     {
51         BMCWEB_LOG_ERROR << "Property type mismatch or property is missing";
52         messages::internalError(asyncResp->res);
53         return;
54     }
55 
56     const auto& [timestamp, readings] = *timestampReadings;
57     asyncResp->res.jsonValue["Timestamp"] =
58         crow::utility::getDateTime(static_cast<time_t>(timestamp));
59     asyncResp->res.jsonValue["MetricValues"] = toMetricValues(readings);
60 }
61 } // namespace telemetry
62 
63 inline void requestRoutesMetricReportCollection(App& app)
64 {
65     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReports/")
66         .privileges({"Login"})
67         .methods(boost::beast::http::verb::get)(
68             [](const crow::Request&,
69                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
70                 asyncResp->res.jsonValue["@odata.type"] =
71                     "#MetricReportCollection.MetricReportCollection";
72                 asyncResp->res.jsonValue["@odata.id"] =
73                     "/redfish/v1/TelemetryService/MetricReports";
74                 asyncResp->res.jsonValue["Name"] = "Metric Report Collection";
75 
76                 telemetry::getReportCollection(asyncResp,
77                                                telemetry::metricReportUri);
78             });
79 }
80 
81 inline void requestRoutesMetricReport(App& app)
82 {
83     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReports/<str>/")
84         .privileges({"Login"})
85         .methods(boost::beast::http::verb::get)(
86             [](const crow::Request&,
87                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
88                const std::string& id) {
89                 const std::string reportPath = telemetry::getDbusReportPath(id);
90                 crow::connections::systemBus->async_method_call(
91                     [asyncResp, id,
92                      reportPath](const boost::system::error_code& ec) {
93                         if (ec.value() == EBADR ||
94                             ec == boost::system::errc::host_unreachable)
95                         {
96                             messages::resourceNotFound(asyncResp->res,
97                                                        "MetricReport", id);
98                             return;
99                         }
100                         if (ec)
101                         {
102                             BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
103                             messages::internalError(asyncResp->res);
104                             return;
105                         }
106 
107                         crow::connections::systemBus->async_method_call(
108                             [asyncResp,
109                              id](const boost::system::error_code ec,
110                                  const std::variant<
111                                      telemetry::TimestampReadings>& ret) {
112                                 if (ec)
113                                 {
114                                     BMCWEB_LOG_ERROR
115                                         << "respHandler DBus error " << ec;
116                                     messages::internalError(asyncResp->res);
117                                     return;
118                                 }
119 
120                                 telemetry::fillReport(asyncResp, id, ret);
121                             },
122                             telemetry::service, reportPath,
123                             "org.freedesktop.DBus.Properties", "Get",
124                             telemetry::reportInterface, "Readings");
125                     },
126                     telemetry::service, reportPath, telemetry::reportInterface,
127                     "Update");
128             });
129 }
130 } // namespace redfish
131