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