xref: /openbmc/bmcweb/features/redfish/lib/metric_report_definition.hpp (revision 479e899d5f57a67647f83b7f615d2c8565290bcf)
1081ebf06SWludzik, Jozef #pragma once
2081ebf06SWludzik, Jozef 
33ccb3adbSEd Tanous #include "app.hpp"
43ccb3adbSEd Tanous #include "dbus_utility.hpp"
5*479e899dSKrzysztof Grobelny #include "generated/enums/metric_report_definition.hpp"
63ccb3adbSEd Tanous #include "query.hpp"
73ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
84dbb8aeaSWludzik, Jozef #include "sensors.hpp"
93ccb3adbSEd Tanous #include "utils/collection.hpp"
103ccb3adbSEd Tanous #include "utils/dbus_utils.hpp"
11081ebf06SWludzik, Jozef #include "utils/telemetry_utils.hpp"
12081ebf06SWludzik, Jozef #include "utils/time_utils.hpp"
13081ebf06SWludzik, Jozef 
144dbb8aeaSWludzik, Jozef #include <boost/container/flat_map.hpp>
15ef4c65b7SEd Tanous #include <boost/url/format.hpp>
1689474494SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp>
1789474494SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp>
184dbb8aeaSWludzik, Jozef 
197a1dbc48SGeorge Liu #include <array>
20fe04d49cSNan Zhou #include <map>
217a1dbc48SGeorge Liu #include <string_view>
22081ebf06SWludzik, Jozef #include <tuple>
23081ebf06SWludzik, Jozef #include <variant>
24081ebf06SWludzik, Jozef 
25081ebf06SWludzik, Jozef namespace redfish
26081ebf06SWludzik, Jozef {
27081ebf06SWludzik, Jozef 
28081ebf06SWludzik, Jozef namespace telemetry
29081ebf06SWludzik, Jozef {
30081ebf06SWludzik, Jozef 
31*479e899dSKrzysztof Grobelny using ReadingParameters = std::vector<std::tuple<
32*479e899dSKrzysztof Grobelny     std::vector<std::tuple<sdbusplus::message::object_path, std::string>>,
33*479e899dSKrzysztof Grobelny     std::string, std::string, uint64_t>>;
34*479e899dSKrzysztof Grobelny 
35*479e899dSKrzysztof Grobelny inline metric_report_definition::ReportActionsEnum
36*479e899dSKrzysztof Grobelny     toRedfishReportAction(std::string_view dbusValue)
37*479e899dSKrzysztof Grobelny {
38*479e899dSKrzysztof Grobelny     if (dbusValue ==
39*479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportActions.EmitsReadingsUpdate")
40*479e899dSKrzysztof Grobelny     {
41*479e899dSKrzysztof Grobelny         return metric_report_definition::ReportActionsEnum::RedfishEvent;
42*479e899dSKrzysztof Grobelny     }
43*479e899dSKrzysztof Grobelny     if (dbusValue ==
44*479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportActions.LogToMetricReportsCollection")
45*479e899dSKrzysztof Grobelny     {
46*479e899dSKrzysztof Grobelny         return metric_report_definition::ReportActionsEnum::
47*479e899dSKrzysztof Grobelny             LogToMetricReportsCollection;
48*479e899dSKrzysztof Grobelny     }
49*479e899dSKrzysztof Grobelny     return metric_report_definition::ReportActionsEnum::Invalid;
50*479e899dSKrzysztof Grobelny }
51*479e899dSKrzysztof Grobelny 
52*479e899dSKrzysztof Grobelny inline std::string toDbusReportAction(std::string_view redfishValue)
53*479e899dSKrzysztof Grobelny {
54*479e899dSKrzysztof Grobelny     if (redfishValue == "RedfishEvent")
55*479e899dSKrzysztof Grobelny     {
56*479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportActions.EmitsReadingsUpdate";
57*479e899dSKrzysztof Grobelny     }
58*479e899dSKrzysztof Grobelny     if (redfishValue == "LogToMetricReportsCollection")
59*479e899dSKrzysztof Grobelny     {
60*479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportActions.LogToMetricReportsCollection";
61*479e899dSKrzysztof Grobelny     }
62*479e899dSKrzysztof Grobelny     return "";
63*479e899dSKrzysztof Grobelny }
64*479e899dSKrzysztof Grobelny 
65*479e899dSKrzysztof Grobelny inline metric_report_definition::MetricReportDefinitionType
66*479e899dSKrzysztof Grobelny     toRedfishReportingType(std::string_view dbusValue)
67*479e899dSKrzysztof Grobelny {
68*479e899dSKrzysztof Grobelny     if (dbusValue ==
69*479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportingType.OnChange")
70*479e899dSKrzysztof Grobelny     {
71*479e899dSKrzysztof Grobelny         return metric_report_definition::MetricReportDefinitionType::OnChange;
72*479e899dSKrzysztof Grobelny     }
73*479e899dSKrzysztof Grobelny     if (dbusValue ==
74*479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportingType.OnRequest")
75*479e899dSKrzysztof Grobelny     {
76*479e899dSKrzysztof Grobelny         return metric_report_definition::MetricReportDefinitionType::OnRequest;
77*479e899dSKrzysztof Grobelny     }
78*479e899dSKrzysztof Grobelny     if (dbusValue ==
79*479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportingType.Periodic")
80*479e899dSKrzysztof Grobelny     {
81*479e899dSKrzysztof Grobelny         return metric_report_definition::MetricReportDefinitionType::Periodic;
82*479e899dSKrzysztof Grobelny     }
83*479e899dSKrzysztof Grobelny     return metric_report_definition::MetricReportDefinitionType::Invalid;
84*479e899dSKrzysztof Grobelny }
85*479e899dSKrzysztof Grobelny 
86*479e899dSKrzysztof Grobelny inline std::string toDbusReportingType(std::string_view redfishValue)
87*479e899dSKrzysztof Grobelny {
88*479e899dSKrzysztof Grobelny     if (redfishValue == "OnChange")
89*479e899dSKrzysztof Grobelny     {
90*479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportingType.OnChange";
91*479e899dSKrzysztof Grobelny     }
92*479e899dSKrzysztof Grobelny     if (redfishValue == "OnRequest")
93*479e899dSKrzysztof Grobelny     {
94*479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportingType.OnRequest";
95*479e899dSKrzysztof Grobelny     }
96*479e899dSKrzysztof Grobelny     if (redfishValue == "Periodic")
97*479e899dSKrzysztof Grobelny     {
98*479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportingType.Periodic";
99*479e899dSKrzysztof Grobelny     }
100*479e899dSKrzysztof Grobelny     return "";
101*479e899dSKrzysztof Grobelny }
102*479e899dSKrzysztof Grobelny 
103*479e899dSKrzysztof Grobelny inline metric_report_definition::CollectionTimeScope
104*479e899dSKrzysztof Grobelny     toRedfishCollectionTimeScope(std::string_view dbusValue)
105*479e899dSKrzysztof Grobelny {
106*479e899dSKrzysztof Grobelny     if (dbusValue ==
107*479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.Point")
108*479e899dSKrzysztof Grobelny     {
109*479e899dSKrzysztof Grobelny         return metric_report_definition::CollectionTimeScope::Point;
110*479e899dSKrzysztof Grobelny     }
111*479e899dSKrzysztof Grobelny     if (dbusValue ==
112*479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.Interval")
113*479e899dSKrzysztof Grobelny     {
114*479e899dSKrzysztof Grobelny         return metric_report_definition::CollectionTimeScope::Interval;
115*479e899dSKrzysztof Grobelny     }
116*479e899dSKrzysztof Grobelny     if (dbusValue ==
117*479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.StartupInterval")
118*479e899dSKrzysztof Grobelny     {
119*479e899dSKrzysztof Grobelny         return metric_report_definition::CollectionTimeScope::StartupInterval;
120*479e899dSKrzysztof Grobelny     }
121*479e899dSKrzysztof Grobelny     return metric_report_definition::CollectionTimeScope::Invalid;
122*479e899dSKrzysztof Grobelny }
123*479e899dSKrzysztof Grobelny 
124*479e899dSKrzysztof Grobelny inline std::string toDbusCollectionTimeScope(std::string_view redfishValue)
125*479e899dSKrzysztof Grobelny {
126*479e899dSKrzysztof Grobelny     if (redfishValue == "Point")
127*479e899dSKrzysztof Grobelny     {
128*479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.Point";
129*479e899dSKrzysztof Grobelny     }
130*479e899dSKrzysztof Grobelny     if (redfishValue == "Interval")
131*479e899dSKrzysztof Grobelny     {
132*479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.Interval";
133*479e899dSKrzysztof Grobelny     }
134*479e899dSKrzysztof Grobelny     if (redfishValue == "StartupInterval")
135*479e899dSKrzysztof Grobelny     {
136*479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.StartupInterval";
137*479e899dSKrzysztof Grobelny     }
138*479e899dSKrzysztof Grobelny     return "";
139*479e899dSKrzysztof Grobelny }
140*479e899dSKrzysztof Grobelny 
141*479e899dSKrzysztof Grobelny inline metric_report_definition::ReportUpdatesEnum
142*479e899dSKrzysztof Grobelny     toRedfishReportUpdates(std::string_view dbusValue)
143*479e899dSKrzysztof Grobelny {
144*479e899dSKrzysztof Grobelny     if (dbusValue ==
145*479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportUpdates.Overwrite")
146*479e899dSKrzysztof Grobelny     {
147*479e899dSKrzysztof Grobelny         return metric_report_definition::ReportUpdatesEnum::Overwrite;
148*479e899dSKrzysztof Grobelny     }
149*479e899dSKrzysztof Grobelny     if (dbusValue ==
150*479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportUpdates.AppendWrapsWhenFull")
151*479e899dSKrzysztof Grobelny     {
152*479e899dSKrzysztof Grobelny         return metric_report_definition::ReportUpdatesEnum::AppendWrapsWhenFull;
153*479e899dSKrzysztof Grobelny     }
154*479e899dSKrzysztof Grobelny     if (dbusValue ==
155*479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportUpdates.AppendStopsWhenFull")
156*479e899dSKrzysztof Grobelny     {
157*479e899dSKrzysztof Grobelny         return metric_report_definition::ReportUpdatesEnum::AppendStopsWhenFull;
158*479e899dSKrzysztof Grobelny     }
159*479e899dSKrzysztof Grobelny     return metric_report_definition::ReportUpdatesEnum::Invalid;
160*479e899dSKrzysztof Grobelny }
161*479e899dSKrzysztof Grobelny 
162*479e899dSKrzysztof Grobelny inline std::string toDbusReportUpdates(std::string_view redfishValue)
163*479e899dSKrzysztof Grobelny {
164*479e899dSKrzysztof Grobelny     if (redfishValue == "Overwrite")
165*479e899dSKrzysztof Grobelny     {
166*479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportUpdates.Overwrite";
167*479e899dSKrzysztof Grobelny     }
168*479e899dSKrzysztof Grobelny     if (redfishValue == "AppendWrapsWhenFull")
169*479e899dSKrzysztof Grobelny     {
170*479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportUpdates.AppendWrapsWhenFull";
171*479e899dSKrzysztof Grobelny     }
172*479e899dSKrzysztof Grobelny     if (redfishValue == "AppendStopsWhenFull")
173*479e899dSKrzysztof Grobelny     {
174*479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportUpdates.AppendStopsWhenFull";
175*479e899dSKrzysztof Grobelny     }
176*479e899dSKrzysztof Grobelny     return "";
177*479e899dSKrzysztof Grobelny }
178081ebf06SWludzik, Jozef 
179b9d36b47SEd Tanous inline void
180b9d36b47SEd Tanous     fillReportDefinition(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
181b9d36b47SEd Tanous                          const std::string& id,
182*479e899dSKrzysztof Grobelny                          const dbus::utility::DBusPropertiesMap& properties)
183081ebf06SWludzik, Jozef {
184*479e899dSKrzysztof Grobelny     std::vector<std::string> reportActions;
185*479e899dSKrzysztof Grobelny     ReadingParameters readingParams;
186*479e899dSKrzysztof Grobelny     std::string reportingType;
187*479e899dSKrzysztof Grobelny     std::string reportUpdates;
188*479e899dSKrzysztof Grobelny     std::string name;
189*479e899dSKrzysztof Grobelny     uint64_t appendLimit = 0;
190*479e899dSKrzysztof Grobelny     uint64_t interval = 0;
191*479e899dSKrzysztof Grobelny     bool enabled = false;
19289474494SKrzysztof Grobelny 
19389474494SKrzysztof Grobelny     const bool success = sdbusplus::unpackPropertiesNoThrow(
194*479e899dSKrzysztof Grobelny         dbus_utils::UnpackErrorPrinter(), properties, "ReportingType",
195*479e899dSKrzysztof Grobelny         reportingType, "Interval", interval, "ReportActions", reportActions,
196*479e899dSKrzysztof Grobelny         "ReportUpdates", reportUpdates, "AppendLimit", appendLimit,
197*479e899dSKrzysztof Grobelny         "ReadingParameters", readingParams, "Name", name, "Enabled", enabled);
19889474494SKrzysztof Grobelny 
19989474494SKrzysztof Grobelny     if (!success)
200081ebf06SWludzik, Jozef     {
201081ebf06SWludzik, Jozef         messages::internalError(asyncResp->res);
202081ebf06SWludzik, Jozef         return;
203081ebf06SWludzik, Jozef     }
204081ebf06SWludzik, Jozef 
205*479e899dSKrzysztof Grobelny     metric_report_definition::MetricReportDefinitionType redfishReportingType =
206*479e899dSKrzysztof Grobelny         toRedfishReportingType(reportingType);
207*479e899dSKrzysztof Grobelny     if (redfishReportingType ==
208*479e899dSKrzysztof Grobelny         metric_report_definition::MetricReportDefinitionType::Invalid)
209081ebf06SWludzik, Jozef     {
210*479e899dSKrzysztof Grobelny         messages::internalError(asyncResp->res);
211*479e899dSKrzysztof Grobelny         return;
212081ebf06SWludzik, Jozef     }
21389474494SKrzysztof Grobelny 
214*479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["MetricReportDefinitionType"] =
215*479e899dSKrzysztof Grobelny         redfishReportingType;
216*479e899dSKrzysztof Grobelny 
217*479e899dSKrzysztof Grobelny     nlohmann::json::array_t redfishReportActions;
218*479e899dSKrzysztof Grobelny     for (const std::string& action : reportActions)
219081ebf06SWludzik, Jozef     {
220*479e899dSKrzysztof Grobelny         metric_report_definition::ReportActionsEnum redfishAction =
221*479e899dSKrzysztof Grobelny             toRedfishReportAction(action);
222*479e899dSKrzysztof Grobelny         if (redfishAction ==
223*479e899dSKrzysztof Grobelny             metric_report_definition::ReportActionsEnum::Invalid)
224*479e899dSKrzysztof Grobelny         {
225*479e899dSKrzysztof Grobelny             messages::internalError(asyncResp->res);
226*479e899dSKrzysztof Grobelny             return;
227081ebf06SWludzik, Jozef         }
228081ebf06SWludzik, Jozef 
229*479e899dSKrzysztof Grobelny         redfishReportActions.emplace_back(redfishAction);
230*479e899dSKrzysztof Grobelny     }
231*479e899dSKrzysztof Grobelny 
232*479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["ReportActions"] = std::move(redfishReportActions);
233*479e899dSKrzysztof Grobelny 
234*479e899dSKrzysztof Grobelny     nlohmann::json::array_t metrics = nlohmann::json::array();
235*479e899dSKrzysztof Grobelny     for (const auto& [sensorData, collectionFunction, collectionTimeScope,
236*479e899dSKrzysztof Grobelny                       collectionDuration] : readingParams)
23789474494SKrzysztof Grobelny     {
238*479e899dSKrzysztof Grobelny         nlohmann::json::array_t metricProperties;
239*479e899dSKrzysztof Grobelny 
240*479e899dSKrzysztof Grobelny         for (const auto& [sensorPath, sensorMetadata] : sensorData)
241081ebf06SWludzik, Jozef         {
242*479e899dSKrzysztof Grobelny             metricProperties.emplace_back(sensorMetadata);
243*479e899dSKrzysztof Grobelny         }
244*479e899dSKrzysztof Grobelny 
245613dabeaSEd Tanous         nlohmann::json::object_t metric;
246*479e899dSKrzysztof Grobelny 
247*479e899dSKrzysztof Grobelny         metric_report_definition::CalculationAlgorithmEnum
248*479e899dSKrzysztof Grobelny             redfishCollectionFunction =
249*479e899dSKrzysztof Grobelny                 telemetry::toRedfishCollectionFunction(collectionFunction);
250*479e899dSKrzysztof Grobelny         if (redfishCollectionFunction ==
251*479e899dSKrzysztof Grobelny             metric_report_definition::CalculationAlgorithmEnum::Invalid)
252*479e899dSKrzysztof Grobelny         {
253*479e899dSKrzysztof Grobelny             messages::internalError(asyncResp->res);
254*479e899dSKrzysztof Grobelny             return;
255*479e899dSKrzysztof Grobelny         }
256*479e899dSKrzysztof Grobelny         metric["CollectionFunction"] = redfishCollectionFunction;
257*479e899dSKrzysztof Grobelny 
258*479e899dSKrzysztof Grobelny         metric_report_definition::CollectionTimeScope
259*479e899dSKrzysztof Grobelny             redfishCollectionTimeScope =
260*479e899dSKrzysztof Grobelny                 toRedfishCollectionTimeScope(collectionTimeScope);
261*479e899dSKrzysztof Grobelny         if (redfishCollectionTimeScope ==
262*479e899dSKrzysztof Grobelny             metric_report_definition::CollectionTimeScope::Invalid)
263*479e899dSKrzysztof Grobelny         {
264*479e899dSKrzysztof Grobelny             messages::internalError(asyncResp->res);
265*479e899dSKrzysztof Grobelny             return;
266*479e899dSKrzysztof Grobelny         }
267*479e899dSKrzysztof Grobelny         metric["CollectionTimeScope"] = redfishCollectionTimeScope;
268*479e899dSKrzysztof Grobelny 
269*479e899dSKrzysztof Grobelny         metric["MetricProperties"] = std::move(metricProperties);
270*479e899dSKrzysztof Grobelny         metric["CollectionDuration"] = time_utils::toDurationString(
271*479e899dSKrzysztof Grobelny             std::chrono::milliseconds(collectionDuration));
272b2ba3072SPatrick Williams         metrics.emplace_back(std::move(metric));
273081ebf06SWludzik, Jozef     }
274*479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["Metrics"] = std::move(metrics);
275*479e899dSKrzysztof Grobelny 
276*479e899dSKrzysztof Grobelny     if (enabled)
277*479e899dSKrzysztof Grobelny     {
278*479e899dSKrzysztof Grobelny         asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
279*479e899dSKrzysztof Grobelny     }
280*479e899dSKrzysztof Grobelny     else
281*479e899dSKrzysztof Grobelny     {
282*479e899dSKrzysztof Grobelny         asyncResp->res.jsonValue["Status"]["State"] = "Disabled";
28389474494SKrzysztof Grobelny     }
28489474494SKrzysztof Grobelny 
285*479e899dSKrzysztof Grobelny     metric_report_definition::ReportUpdatesEnum redfishReportUpdates =
286*479e899dSKrzysztof Grobelny         toRedfishReportUpdates(reportUpdates);
287*479e899dSKrzysztof Grobelny     if (redfishReportUpdates ==
288*479e899dSKrzysztof Grobelny         metric_report_definition::ReportUpdatesEnum::Invalid)
28989474494SKrzysztof Grobelny     {
290*479e899dSKrzysztof Grobelny         messages::internalError(asyncResp->res);
291*479e899dSKrzysztof Grobelny         return;
29289474494SKrzysztof Grobelny     }
293*479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["ReportUpdates"] = redfishReportUpdates;
29489474494SKrzysztof Grobelny 
295*479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["MetricReportDefinitionEnabled"] = enabled;
296*479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["AppendLimit"] = appendLimit;
297*479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["Name"] = name;
298081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["Schedule"]["RecurrenceInterval"] =
299*479e899dSKrzysztof Grobelny         time_utils::toDurationString(std::chrono::milliseconds(interval));
300*479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["@odata.type"] =
301*479e899dSKrzysztof Grobelny         "#MetricReportDefinition.v1_3_0.MetricReportDefinition";
302*479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
303*479e899dSKrzysztof Grobelny         "/redfish/v1/TelemetryService/MetricReportDefinitions/{}", id);
304*479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["Id"] = id;
305*479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["MetricReport"]["@odata.id"] = boost::urls::format(
306*479e899dSKrzysztof Grobelny         "/redfish/v1/TelemetryService/MetricReports/{}", id);
30789474494SKrzysztof Grobelny }
30889474494SKrzysztof Grobelny 
3094dbb8aeaSWludzik, Jozef struct AddReportArgs
3104dbb8aeaSWludzik, Jozef {
311*479e899dSKrzysztof Grobelny     struct MetricArgs
312*479e899dSKrzysztof Grobelny     {
313*479e899dSKrzysztof Grobelny         std::vector<std::string> uris;
314*479e899dSKrzysztof Grobelny         std::string collectionFunction;
315*479e899dSKrzysztof Grobelny         std::string collectionTimeScope;
316*479e899dSKrzysztof Grobelny         uint64_t collectionDuration = 0;
317*479e899dSKrzysztof Grobelny     };
318*479e899dSKrzysztof Grobelny 
319*479e899dSKrzysztof Grobelny     std::string id;
3204dbb8aeaSWludzik, Jozef     std::string name;
3214dbb8aeaSWludzik, Jozef     std::string reportingType;
322*479e899dSKrzysztof Grobelny     std::string reportUpdates;
323*479e899dSKrzysztof Grobelny     uint64_t appendLimit = std::numeric_limits<uint64_t>::max();
324*479e899dSKrzysztof Grobelny     std::vector<std::string> reportActions;
325*479e899dSKrzysztof Grobelny     uint64_t interval = std::numeric_limits<uint64_t>::max();
326*479e899dSKrzysztof Grobelny     std::vector<MetricArgs> metrics;
327*479e899dSKrzysztof Grobelny     bool metricReportDefinitionEnabled = true;
3284dbb8aeaSWludzik, Jozef };
3294dbb8aeaSWludzik, Jozef 
3304dbb8aeaSWludzik, Jozef inline bool toDbusReportActions(crow::Response& res,
331*479e899dSKrzysztof Grobelny                                 const std::vector<std::string>& actions,
3324dbb8aeaSWludzik, Jozef                                 AddReportArgs& args)
3334dbb8aeaSWludzik, Jozef {
3344dbb8aeaSWludzik, Jozef     size_t index = 0;
335*479e899dSKrzysztof Grobelny     for (const std::string& action : actions)
3364dbb8aeaSWludzik, Jozef     {
337*479e899dSKrzysztof Grobelny         std::string dbusReportAction = toDbusReportAction(action);
338*479e899dSKrzysztof Grobelny         if (dbusReportAction.empty())
3394dbb8aeaSWludzik, Jozef         {
340*479e899dSKrzysztof Grobelny             messages::propertyValueNotInList(res, nlohmann::json(action).dump(),
341*479e899dSKrzysztof Grobelny                                              "ReportActions/" +
342*479e899dSKrzysztof Grobelny                                                  std::to_string(index));
3434dbb8aeaSWludzik, Jozef             return false;
3444dbb8aeaSWludzik, Jozef         }
345*479e899dSKrzysztof Grobelny 
346*479e899dSKrzysztof Grobelny         args.reportActions.emplace_back(std::move(dbusReportAction));
3474dbb8aeaSWludzik, Jozef         index++;
3484dbb8aeaSWludzik, Jozef     }
3494dbb8aeaSWludzik, Jozef     return true;
3504dbb8aeaSWludzik, Jozef }
3514dbb8aeaSWludzik, Jozef 
352*479e899dSKrzysztof Grobelny inline bool getUserMetric(crow::Response& res, nlohmann::json& metric,
353*479e899dSKrzysztof Grobelny                           AddReportArgs::MetricArgs& metricArgs)
354*479e899dSKrzysztof Grobelny {
355*479e899dSKrzysztof Grobelny     std::optional<std::vector<std::string>> uris;
356*479e899dSKrzysztof Grobelny     std::optional<std::string> collectionDurationStr;
357*479e899dSKrzysztof Grobelny     std::optional<std::string> collectionFunction;
358*479e899dSKrzysztof Grobelny     std::optional<std::string> collectionTimeScopeStr;
359*479e899dSKrzysztof Grobelny 
360*479e899dSKrzysztof Grobelny     if (!json_util::readJson(metric, res, "MetricProperties", uris,
361*479e899dSKrzysztof Grobelny                              "CollectionFunction", collectionFunction,
362*479e899dSKrzysztof Grobelny                              "CollectionTimeScope", collectionTimeScopeStr,
363*479e899dSKrzysztof Grobelny                              "CollectionDuration", collectionDurationStr))
364*479e899dSKrzysztof Grobelny     {
365*479e899dSKrzysztof Grobelny         return false;
366*479e899dSKrzysztof Grobelny     }
367*479e899dSKrzysztof Grobelny 
368*479e899dSKrzysztof Grobelny     if (uris)
369*479e899dSKrzysztof Grobelny     {
370*479e899dSKrzysztof Grobelny         metricArgs.uris = std::move(*uris);
371*479e899dSKrzysztof Grobelny     }
372*479e899dSKrzysztof Grobelny 
373*479e899dSKrzysztof Grobelny     if (collectionFunction)
374*479e899dSKrzysztof Grobelny     {
375*479e899dSKrzysztof Grobelny         std::string dbusCollectionFunction =
376*479e899dSKrzysztof Grobelny             telemetry::toDbusCollectionFunction(*collectionFunction);
377*479e899dSKrzysztof Grobelny         if (dbusCollectionFunction.empty())
378*479e899dSKrzysztof Grobelny         {
379*479e899dSKrzysztof Grobelny             messages::propertyValueIncorrect(res, "CollectionFunction",
380*479e899dSKrzysztof Grobelny                                              *collectionFunction);
381*479e899dSKrzysztof Grobelny             return false;
382*479e899dSKrzysztof Grobelny         }
383*479e899dSKrzysztof Grobelny         metricArgs.collectionFunction = std::move(dbusCollectionFunction);
384*479e899dSKrzysztof Grobelny     }
385*479e899dSKrzysztof Grobelny 
386*479e899dSKrzysztof Grobelny     if (collectionTimeScopeStr)
387*479e899dSKrzysztof Grobelny     {
388*479e899dSKrzysztof Grobelny         std::string dbusCollectionTimeScope =
389*479e899dSKrzysztof Grobelny             toDbusCollectionTimeScope(*collectionTimeScopeStr);
390*479e899dSKrzysztof Grobelny         if (dbusCollectionTimeScope.empty())
391*479e899dSKrzysztof Grobelny         {
392*479e899dSKrzysztof Grobelny             messages::propertyValueIncorrect(res, "CollectionTimeScope",
393*479e899dSKrzysztof Grobelny                                              *collectionTimeScopeStr);
394*479e899dSKrzysztof Grobelny             return false;
395*479e899dSKrzysztof Grobelny         }
396*479e899dSKrzysztof Grobelny         metricArgs.collectionTimeScope = std::move(dbusCollectionTimeScope);
397*479e899dSKrzysztof Grobelny     }
398*479e899dSKrzysztof Grobelny 
399*479e899dSKrzysztof Grobelny     if (collectionDurationStr)
400*479e899dSKrzysztof Grobelny     {
401*479e899dSKrzysztof Grobelny         std::optional<std::chrono::milliseconds> duration =
402*479e899dSKrzysztof Grobelny             time_utils::fromDurationString(*collectionDurationStr);
403*479e899dSKrzysztof Grobelny 
404*479e899dSKrzysztof Grobelny         if (!duration || duration->count() < 0)
405*479e899dSKrzysztof Grobelny         {
406*479e899dSKrzysztof Grobelny             messages::propertyValueIncorrect(res, "CollectionDuration",
407*479e899dSKrzysztof Grobelny                                              *collectionDurationStr);
408*479e899dSKrzysztof Grobelny             return false;
409*479e899dSKrzysztof Grobelny         }
410*479e899dSKrzysztof Grobelny 
411*479e899dSKrzysztof Grobelny         metricArgs.collectionDuration =
412*479e899dSKrzysztof Grobelny             static_cast<uint64_t>(duration->count());
413*479e899dSKrzysztof Grobelny     }
414*479e899dSKrzysztof Grobelny 
415*479e899dSKrzysztof Grobelny     return true;
416*479e899dSKrzysztof Grobelny }
417*479e899dSKrzysztof Grobelny 
418*479e899dSKrzysztof Grobelny inline bool getUserMetrics(crow::Response& res,
419*479e899dSKrzysztof Grobelny                            std::span<nlohmann::json> metrics,
420*479e899dSKrzysztof Grobelny                            std::vector<AddReportArgs::MetricArgs>& result)
421*479e899dSKrzysztof Grobelny {
422*479e899dSKrzysztof Grobelny     result.reserve(metrics.size());
423*479e899dSKrzysztof Grobelny 
424*479e899dSKrzysztof Grobelny     for (nlohmann::json& m : metrics)
425*479e899dSKrzysztof Grobelny     {
426*479e899dSKrzysztof Grobelny         AddReportArgs::MetricArgs metricArgs;
427*479e899dSKrzysztof Grobelny 
428*479e899dSKrzysztof Grobelny         if (!getUserMetric(res, m, metricArgs))
429*479e899dSKrzysztof Grobelny         {
430*479e899dSKrzysztof Grobelny             return false;
431*479e899dSKrzysztof Grobelny         }
432*479e899dSKrzysztof Grobelny 
433*479e899dSKrzysztof Grobelny         result.emplace_back(std::move(metricArgs));
434*479e899dSKrzysztof Grobelny     }
435*479e899dSKrzysztof Grobelny 
436*479e899dSKrzysztof Grobelny     return true;
437*479e899dSKrzysztof Grobelny }
438*479e899dSKrzysztof Grobelny 
4394dbb8aeaSWludzik, Jozef inline bool getUserParameters(crow::Response& res, const crow::Request& req,
4404dbb8aeaSWludzik, Jozef                               AddReportArgs& args)
4414dbb8aeaSWludzik, Jozef {
442*479e899dSKrzysztof Grobelny     std::optional<std::string> id;
443*479e899dSKrzysztof Grobelny     std::optional<std::string> name;
444*479e899dSKrzysztof Grobelny     std::optional<std::string> reportingTypeStr;
445*479e899dSKrzysztof Grobelny     std::optional<std::string> reportUpdatesStr;
446*479e899dSKrzysztof Grobelny     std::optional<uint64_t> appendLimit;
447*479e899dSKrzysztof Grobelny     std::optional<bool> metricReportDefinitionEnabled;
448*479e899dSKrzysztof Grobelny     std::optional<std::vector<nlohmann::json>> metrics;
449*479e899dSKrzysztof Grobelny     std::optional<std::vector<std::string>> reportActionsStr;
4504dbb8aeaSWludzik, Jozef     std::optional<nlohmann::json> schedule;
451*479e899dSKrzysztof Grobelny 
452*479e899dSKrzysztof Grobelny     if (!json_util::readJsonPatch(
453*479e899dSKrzysztof Grobelny             req, res, "Id", id, "Name", name, "Metrics", metrics,
454*479e899dSKrzysztof Grobelny             "MetricReportDefinitionType", reportingTypeStr, "ReportUpdates",
455*479e899dSKrzysztof Grobelny             reportUpdatesStr, "AppendLimit", appendLimit, "ReportActions",
456*479e899dSKrzysztof Grobelny             reportActionsStr, "Schedule", schedule,
457*479e899dSKrzysztof Grobelny             "MetricReportDefinitionEnabled", metricReportDefinitionEnabled))
4584dbb8aeaSWludzik, Jozef     {
4594dbb8aeaSWludzik, Jozef         return false;
4604dbb8aeaSWludzik, Jozef     }
4614dbb8aeaSWludzik, Jozef 
462*479e899dSKrzysztof Grobelny     if (id)
463*479e899dSKrzysztof Grobelny     {
464*479e899dSKrzysztof Grobelny         constexpr const char* allowedCharactersInId =
4654dbb8aeaSWludzik, Jozef             "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
466*479e899dSKrzysztof Grobelny         if (id->empty() ||
467*479e899dSKrzysztof Grobelny             id->find_first_not_of(allowedCharactersInId) != std::string::npos)
4684dbb8aeaSWludzik, Jozef         {
469*479e899dSKrzysztof Grobelny             messages::propertyValueIncorrect(res, "Id", *id);
4704dbb8aeaSWludzik, Jozef             return false;
4714dbb8aeaSWludzik, Jozef         }
472*479e899dSKrzysztof Grobelny         args.id = *id;
473*479e899dSKrzysztof Grobelny     }
4744dbb8aeaSWludzik, Jozef 
475*479e899dSKrzysztof Grobelny     if (name)
4764dbb8aeaSWludzik, Jozef     {
477*479e899dSKrzysztof Grobelny         args.name = *name;
478*479e899dSKrzysztof Grobelny     }
479*479e899dSKrzysztof Grobelny 
480*479e899dSKrzysztof Grobelny     if (reportingTypeStr)
481*479e899dSKrzysztof Grobelny     {
482*479e899dSKrzysztof Grobelny         std::string dbusReportingType = toDbusReportingType(*reportingTypeStr);
483*479e899dSKrzysztof Grobelny         if (dbusReportingType.empty())
484*479e899dSKrzysztof Grobelny         {
485*479e899dSKrzysztof Grobelny             messages::propertyValueNotInList(res, *reportingTypeStr,
4864dbb8aeaSWludzik, Jozef                                              "MetricReportDefinitionType");
4874dbb8aeaSWludzik, Jozef             return false;
4884dbb8aeaSWludzik, Jozef         }
489*479e899dSKrzysztof Grobelny         args.reportingType = dbusReportingType;
490*479e899dSKrzysztof Grobelny     }
4914dbb8aeaSWludzik, Jozef 
492*479e899dSKrzysztof Grobelny     if (reportUpdatesStr)
493*479e899dSKrzysztof Grobelny     {
494*479e899dSKrzysztof Grobelny         std::string dbusReportUpdates = toDbusReportUpdates(*reportUpdatesStr);
495*479e899dSKrzysztof Grobelny         if (dbusReportUpdates.empty())
496*479e899dSKrzysztof Grobelny         {
497*479e899dSKrzysztof Grobelny             messages::propertyValueNotInList(res, *reportUpdatesStr,
498*479e899dSKrzysztof Grobelny                                              "ReportUpdates");
499*479e899dSKrzysztof Grobelny             return false;
500*479e899dSKrzysztof Grobelny         }
501*479e899dSKrzysztof Grobelny         args.reportUpdates = dbusReportUpdates;
502*479e899dSKrzysztof Grobelny     }
503*479e899dSKrzysztof Grobelny 
504*479e899dSKrzysztof Grobelny     if (appendLimit)
505*479e899dSKrzysztof Grobelny     {
506*479e899dSKrzysztof Grobelny         args.appendLimit = *appendLimit;
507*479e899dSKrzysztof Grobelny     }
508*479e899dSKrzysztof Grobelny 
509*479e899dSKrzysztof Grobelny     if (metricReportDefinitionEnabled)
510*479e899dSKrzysztof Grobelny     {
511*479e899dSKrzysztof Grobelny         args.metricReportDefinitionEnabled = *metricReportDefinitionEnabled;
512*479e899dSKrzysztof Grobelny     }
513*479e899dSKrzysztof Grobelny 
514*479e899dSKrzysztof Grobelny     if (reportActionsStr)
515*479e899dSKrzysztof Grobelny     {
516*479e899dSKrzysztof Grobelny         if (!toDbusReportActions(res, *reportActionsStr, args))
5174dbb8aeaSWludzik, Jozef         {
5184dbb8aeaSWludzik, Jozef             return false;
5194dbb8aeaSWludzik, Jozef         }
520*479e899dSKrzysztof Grobelny     }
5214dbb8aeaSWludzik, Jozef 
522*479e899dSKrzysztof Grobelny     if (reportingTypeStr == "Periodic")
5234dbb8aeaSWludzik, Jozef     {
5244dbb8aeaSWludzik, Jozef         if (!schedule)
5254dbb8aeaSWludzik, Jozef         {
5264dbb8aeaSWludzik, Jozef             messages::createFailedMissingReqProperties(res, "Schedule");
5274dbb8aeaSWludzik, Jozef             return false;
5284dbb8aeaSWludzik, Jozef         }
5294dbb8aeaSWludzik, Jozef 
5304dbb8aeaSWludzik, Jozef         std::string durationStr;
5314dbb8aeaSWludzik, Jozef         if (!json_util::readJson(*schedule, res, "RecurrenceInterval",
5324dbb8aeaSWludzik, Jozef                                  durationStr))
5334dbb8aeaSWludzik, Jozef         {
5344dbb8aeaSWludzik, Jozef             return false;
5354dbb8aeaSWludzik, Jozef         }
5364dbb8aeaSWludzik, Jozef 
5374dbb8aeaSWludzik, Jozef         std::optional<std::chrono::milliseconds> durationNum =
5384dbb8aeaSWludzik, Jozef             time_utils::fromDurationString(durationStr);
539*479e899dSKrzysztof Grobelny         if (!durationNum || durationNum->count() < 0)
5404dbb8aeaSWludzik, Jozef         {
5414dbb8aeaSWludzik, Jozef             messages::propertyValueIncorrect(res, "RecurrenceInterval",
5424dbb8aeaSWludzik, Jozef                                              durationStr);
5434dbb8aeaSWludzik, Jozef             return false;
5444dbb8aeaSWludzik, Jozef         }
5454dbb8aeaSWludzik, Jozef         args.interval = static_cast<uint64_t>(durationNum->count());
5464dbb8aeaSWludzik, Jozef     }
5474dbb8aeaSWludzik, Jozef 
548*479e899dSKrzysztof Grobelny     if (metrics)
5494dbb8aeaSWludzik, Jozef     {
550*479e899dSKrzysztof Grobelny         if (!getUserMetrics(res, *metrics, args.metrics))
5514dbb8aeaSWludzik, Jozef         {
5524dbb8aeaSWludzik, Jozef             return false;
5534dbb8aeaSWludzik, Jozef         }
5544dbb8aeaSWludzik, Jozef     }
5554dbb8aeaSWludzik, Jozef 
5564dbb8aeaSWludzik, Jozef     return true;
5574dbb8aeaSWludzik, Jozef }
5584dbb8aeaSWludzik, Jozef 
559ca1600c1SSzymon Dompke inline bool getChassisSensorNodeFromMetrics(
5608d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
561*479e899dSKrzysztof Grobelny     std::span<const AddReportArgs::MetricArgs> metrics,
5624dbb8aeaSWludzik, Jozef     boost::container::flat_set<std::pair<std::string, std::string>>& matched)
5634dbb8aeaSWludzik, Jozef {
564ca1600c1SSzymon Dompke     for (const auto& metric : metrics)
5654dbb8aeaSWludzik, Jozef     {
566*479e899dSKrzysztof Grobelny         std::optional<IncorrectMetricUri> error =
567*479e899dSKrzysztof Grobelny             getChassisSensorNode(metric.uris, matched);
568ca1600c1SSzymon Dompke         if (error)
5694dbb8aeaSWludzik, Jozef         {
570ca1600c1SSzymon Dompke             messages::propertyValueIncorrect(asyncResp->res, error->uri,
5714dbb8aeaSWludzik, Jozef                                              "MetricProperties/" +
572ca1600c1SSzymon Dompke                                                  std::to_string(error->index));
5734dbb8aeaSWludzik, Jozef             return false;
5744dbb8aeaSWludzik, Jozef         }
5754dbb8aeaSWludzik, Jozef     }
5764dbb8aeaSWludzik, Jozef     return true;
5774dbb8aeaSWludzik, Jozef }
5784dbb8aeaSWludzik, Jozef 
5794dbb8aeaSWludzik, Jozef class AddReport
5804dbb8aeaSWludzik, Jozef {
5814dbb8aeaSWludzik, Jozef   public:
5828d1b46d7Szhanghch05     AddReport(AddReportArgs argsIn,
5838a592810SEd Tanous               const std::shared_ptr<bmcweb::AsyncResp>& asyncRespIn) :
5848a592810SEd Tanous         asyncResp(asyncRespIn),
5858d1b46d7Szhanghch05         args{std::move(argsIn)}
5864dbb8aeaSWludzik, Jozef     {}
587*479e899dSKrzysztof Grobelny 
5884dbb8aeaSWludzik, Jozef     ~AddReport()
5894dbb8aeaSWludzik, Jozef     {
590*479e899dSKrzysztof Grobelny         boost::asio::post(crow::connections::systemBus->get_io_context(),
591*479e899dSKrzysztof Grobelny                           std::bind_front(&performAddReport, asyncResp, args,
592*479e899dSKrzysztof Grobelny                                           std::move(uriToDbus)));
593*479e899dSKrzysztof Grobelny     }
594*479e899dSKrzysztof Grobelny 
595*479e899dSKrzysztof Grobelny     static void performAddReport(
596*479e899dSKrzysztof Grobelny         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
597*479e899dSKrzysztof Grobelny         const AddReportArgs& args,
598*479e899dSKrzysztof Grobelny         const boost::container::flat_map<std::string, std::string>& uriToDbus)
599*479e899dSKrzysztof Grobelny     {
6004dbb8aeaSWludzik, Jozef         if (asyncResp->res.result() != boost::beast::http::status::ok)
6014dbb8aeaSWludzik, Jozef         {
6024dbb8aeaSWludzik, Jozef             return;
6034dbb8aeaSWludzik, Jozef         }
6044dbb8aeaSWludzik, Jozef 
6054dbb8aeaSWludzik, Jozef         telemetry::ReadingParameters readingParams;
6064dbb8aeaSWludzik, Jozef         readingParams.reserve(args.metrics.size());
6074dbb8aeaSWludzik, Jozef 
608*479e899dSKrzysztof Grobelny         for (const auto& metric : args.metrics)
6094dbb8aeaSWludzik, Jozef         {
610*479e899dSKrzysztof Grobelny             std::vector<
611*479e899dSKrzysztof Grobelny                 std::tuple<sdbusplus::message::object_path, std::string>>
612*479e899dSKrzysztof Grobelny                 sensorParams;
613*479e899dSKrzysztof Grobelny             sensorParams.reserve(metric.uris.size());
614*479e899dSKrzysztof Grobelny 
615*479e899dSKrzysztof Grobelny             for (size_t i = 0; i < metric.uris.size(); i++)
6164dbb8aeaSWludzik, Jozef             {
617*479e899dSKrzysztof Grobelny                 const std::string& uri = metric.uris[i];
6184dbb8aeaSWludzik, Jozef                 auto el = uriToDbus.find(uri);
6194dbb8aeaSWludzik, Jozef                 if (el == uriToDbus.end())
6204dbb8aeaSWludzik, Jozef                 {
6210fda0f12SGeorge Liu                     BMCWEB_LOG_ERROR
6220fda0f12SGeorge Liu                         << "Failed to find DBus sensor corresponding to URI "
6234dbb8aeaSWludzik, Jozef                         << uri;
6244dbb8aeaSWludzik, Jozef                     messages::propertyValueNotInList(asyncResp->res, uri,
6254dbb8aeaSWludzik, Jozef                                                      "MetricProperties/" +
6264dbb8aeaSWludzik, Jozef                                                          std::to_string(i));
6274dbb8aeaSWludzik, Jozef                     return;
6284dbb8aeaSWludzik, Jozef                 }
6294dbb8aeaSWludzik, Jozef 
6304dbb8aeaSWludzik, Jozef                 const std::string& dbusPath = el->second;
631*479e899dSKrzysztof Grobelny                 sensorParams.emplace_back(dbusPath, uri);
6324dbb8aeaSWludzik, Jozef             }
633*479e899dSKrzysztof Grobelny 
634*479e899dSKrzysztof Grobelny             readingParams.emplace_back(
635*479e899dSKrzysztof Grobelny                 std::move(sensorParams), metric.collectionFunction,
636*479e899dSKrzysztof Grobelny                 metric.collectionTimeScope, metric.collectionDuration);
6374dbb8aeaSWludzik, Jozef         }
638*479e899dSKrzysztof Grobelny 
6394dbb8aeaSWludzik, Jozef         crow::connections::systemBus->async_method_call(
640*479e899dSKrzysztof Grobelny             [asyncResp, id = args.id, uriToDbus](
6415e7e2dc5SEd Tanous                 const boost::system::error_code& ec, const std::string&) {
6424dbb8aeaSWludzik, Jozef             if (ec == boost::system::errc::file_exists)
6434dbb8aeaSWludzik, Jozef             {
6444dbb8aeaSWludzik, Jozef                 messages::resourceAlreadyExists(
645*479e899dSKrzysztof Grobelny                     asyncResp->res, "MetricReportDefinition", "Id", id);
6464dbb8aeaSWludzik, Jozef                 return;
6474dbb8aeaSWludzik, Jozef             }
6484dbb8aeaSWludzik, Jozef             if (ec == boost::system::errc::too_many_files_open)
6494dbb8aeaSWludzik, Jozef             {
650*479e899dSKrzysztof Grobelny                 messages::createLimitReachedForResource(asyncResp->res);
6514dbb8aeaSWludzik, Jozef                 return;
6524dbb8aeaSWludzik, Jozef             }
6534dbb8aeaSWludzik, Jozef             if (ec == boost::system::errc::argument_list_too_long)
6544dbb8aeaSWludzik, Jozef             {
6554dbb8aeaSWludzik, Jozef                 nlohmann::json metricProperties = nlohmann::json::array();
6564dbb8aeaSWludzik, Jozef                 for (const auto& [uri, _] : uriToDbus)
6574dbb8aeaSWludzik, Jozef                 {
6584dbb8aeaSWludzik, Jozef                     metricProperties.emplace_back(uri);
6594dbb8aeaSWludzik, Jozef                 }
660*479e899dSKrzysztof Grobelny                 messages::propertyValueIncorrect(asyncResp->res,
661*479e899dSKrzysztof Grobelny                                                  metricProperties.dump(),
662*479e899dSKrzysztof Grobelny                                                  "MetricProperties");
6634dbb8aeaSWludzik, Jozef                 return;
6644dbb8aeaSWludzik, Jozef             }
6654dbb8aeaSWludzik, Jozef             if (ec)
6664dbb8aeaSWludzik, Jozef             {
667*479e899dSKrzysztof Grobelny                 messages::internalError(asyncResp->res);
6684dbb8aeaSWludzik, Jozef                 BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
6694dbb8aeaSWludzik, Jozef                 return;
6704dbb8aeaSWludzik, Jozef             }
6714dbb8aeaSWludzik, Jozef 
672*479e899dSKrzysztof Grobelny             messages::created(asyncResp->res);
6734dbb8aeaSWludzik, Jozef             },
6744dbb8aeaSWludzik, Jozef             telemetry::service, "/xyz/openbmc_project/Telemetry/Reports",
6754dbb8aeaSWludzik, Jozef             "xyz.openbmc_project.Telemetry.ReportManager", "AddReport",
676*479e899dSKrzysztof Grobelny             "TelemetryService/" + args.id, args.name, args.reportingType,
677*479e899dSKrzysztof Grobelny             args.reportUpdates, args.appendLimit, args.reportActions,
678*479e899dSKrzysztof Grobelny             args.interval, readingParams, args.metricReportDefinitionEnabled);
6794dbb8aeaSWludzik, Jozef     }
6804dbb8aeaSWludzik, Jozef 
681ecd6a3a2SEd Tanous     AddReport(const AddReport&) = delete;
682ecd6a3a2SEd Tanous     AddReport(AddReport&&) = delete;
683ecd6a3a2SEd Tanous     AddReport& operator=(const AddReport&) = delete;
684ecd6a3a2SEd Tanous     AddReport& operator=(AddReport&&) = delete;
685ecd6a3a2SEd Tanous 
686fe04d49cSNan Zhou     void insert(const std::map<std::string, std::string>& el)
6874dbb8aeaSWludzik, Jozef     {
6884dbb8aeaSWludzik, Jozef         uriToDbus.insert(el.begin(), el.end());
6894dbb8aeaSWludzik, Jozef     }
6904dbb8aeaSWludzik, Jozef 
6914dbb8aeaSWludzik, Jozef   private:
692*479e899dSKrzysztof Grobelny     std::shared_ptr<bmcweb::AsyncResp> asyncResp;
6934dbb8aeaSWludzik, Jozef     AddReportArgs args;
6944dbb8aeaSWludzik, Jozef     boost::container::flat_map<std::string, std::string> uriToDbus{};
6954dbb8aeaSWludzik, Jozef };
696081ebf06SWludzik, Jozef } // namespace telemetry
697081ebf06SWludzik, Jozef 
6987e860f15SJohn Edward Broadbent inline void requestRoutesMetricReportDefinitionCollection(App& app)
699081ebf06SWludzik, Jozef {
7007e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/")
701ed398213SEd Tanous         .privileges(redfish::privileges::getMetricReportDefinitionCollection)
7027e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
70345ca1b86SEd Tanous             [&app](const crow::Request& req,
7047e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
7053ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
70645ca1b86SEd Tanous         {
70745ca1b86SEd Tanous             return;
70845ca1b86SEd Tanous         }
70945ca1b86SEd Tanous 
7108d1b46d7Szhanghch05         asyncResp->res.jsonValue["@odata.type"] =
7118d1b46d7Szhanghch05             "#MetricReportDefinitionCollection."
712081ebf06SWludzik, Jozef             "MetricReportDefinitionCollection";
7138d1b46d7Szhanghch05         asyncResp->res.jsonValue["@odata.id"] =
714ae9031f0SWilly Tu             "/redfish/v1/TelemetryService/MetricReportDefinitions";
715002d39b4SEd Tanous         asyncResp->res.jsonValue["Name"] = "Metric Definition Collection";
7167a1dbc48SGeorge Liu         constexpr std::array<std::string_view, 1> interfaces{
7177a1dbc48SGeorge Liu             telemetry::reportInterface};
7184028ff77SEd Tanous         collection_util::getCollectionMembers(
719ae9031f0SWilly Tu             asyncResp,
720ae9031f0SWilly Tu             boost::urls::url(
721ae9031f0SWilly Tu                 "/redfish/v1/TelemetryService/MetricReportDefinitions"),
722ae9031f0SWilly Tu             interfaces,
7234028ff77SEd Tanous             "/xyz/openbmc_project/Telemetry/Reports/TelemetryService");
7247e860f15SJohn Edward Broadbent         });
7254dbb8aeaSWludzik, Jozef 
7267e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/")
727ed398213SEd Tanous         .privileges(redfish::privileges::postMetricReportDefinitionCollection)
728002d39b4SEd Tanous         .methods(boost::beast::http::verb::post)(
729002d39b4SEd Tanous             [&app](const crow::Request& req,
7307e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
7313ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
73245ca1b86SEd Tanous         {
73345ca1b86SEd Tanous             return;
73445ca1b86SEd Tanous         }
73545ca1b86SEd Tanous 
7364dbb8aeaSWludzik, Jozef         telemetry::AddReportArgs args;
7378d1b46d7Szhanghch05         if (!telemetry::getUserParameters(asyncResp->res, req, args))
7384dbb8aeaSWludzik, Jozef         {
7394dbb8aeaSWludzik, Jozef             return;
7404dbb8aeaSWludzik, Jozef         }
7414dbb8aeaSWludzik, Jozef 
7424dbb8aeaSWludzik, Jozef         boost::container::flat_set<std::pair<std::string, std::string>>
7434dbb8aeaSWludzik, Jozef             chassisSensors;
744002d39b4SEd Tanous         if (!telemetry::getChassisSensorNodeFromMetrics(asyncResp, args.metrics,
745002d39b4SEd Tanous                                                         chassisSensors))
7464dbb8aeaSWludzik, Jozef         {
7474dbb8aeaSWludzik, Jozef             return;
7484dbb8aeaSWludzik, Jozef         }
7494dbb8aeaSWludzik, Jozef 
750002d39b4SEd Tanous         auto addReportReq =
751002d39b4SEd Tanous             std::make_shared<telemetry::AddReport>(std::move(args), asyncResp);
7524dbb8aeaSWludzik, Jozef         for (const auto& [chassis, sensorType] : chassisSensors)
7534dbb8aeaSWludzik, Jozef         {
7544dbb8aeaSWludzik, Jozef             retrieveUriToDbusMap(
755021d32cfSKrzysztof Grobelny                 chassis, sensorType,
756002d39b4SEd Tanous                 [asyncResp, addReportReq](
757002d39b4SEd Tanous                     const boost::beast::http::status status,
758fe04d49cSNan Zhou                     const std::map<std::string, std::string>& uriToDbus) {
7594dbb8aeaSWludzik, Jozef                 if (status != boost::beast::http::status::ok)
7604dbb8aeaSWludzik, Jozef                 {
7617e860f15SJohn Edward Broadbent                     BMCWEB_LOG_ERROR
7620fda0f12SGeorge Liu                         << "Failed to retrieve URI to dbus sensors map with err "
7634dbb8aeaSWludzik, Jozef                         << static_cast<unsigned>(status);
7644dbb8aeaSWludzik, Jozef                     return;
7654dbb8aeaSWludzik, Jozef                 }
7664dbb8aeaSWludzik, Jozef                 addReportReq->insert(uriToDbus);
7674dbb8aeaSWludzik, Jozef                 });
7684dbb8aeaSWludzik, Jozef         }
7697e860f15SJohn Edward Broadbent         });
770081ebf06SWludzik, Jozef }
771081ebf06SWludzik, Jozef 
7727e860f15SJohn Edward Broadbent inline void requestRoutesMetricReportDefinition(App& app)
773081ebf06SWludzik, Jozef {
7747e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
7757e860f15SJohn Edward Broadbent                  "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/")
776ed398213SEd Tanous         .privileges(redfish::privileges::getMetricReportDefinition)
7777e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
77845ca1b86SEd Tanous             [&app](const crow::Request& req,
7797e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
7807e860f15SJohn Edward Broadbent                    const std::string& id) {
7813ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
78245ca1b86SEd Tanous         {
78345ca1b86SEd Tanous             return;
78445ca1b86SEd Tanous         }
78545ca1b86SEd Tanous 
78689474494SKrzysztof Grobelny         sdbusplus::asio::getAllProperties(
78789474494SKrzysztof Grobelny             *crow::connections::systemBus, telemetry::service,
78889474494SKrzysztof Grobelny             telemetry::getDbusReportPath(id), telemetry::reportInterface,
789168e20c1SEd Tanous             [asyncResp,
7905e7e2dc5SEd Tanous              id](const boost::system::error_code& ec,
791*479e899dSKrzysztof Grobelny                  const dbus::utility::DBusPropertiesMap& properties) {
792081ebf06SWludzik, Jozef             if (ec.value() == EBADR ||
793081ebf06SWludzik, Jozef                 ec == boost::system::errc::host_unreachable)
794081ebf06SWludzik, Jozef             {
795002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res,
796002d39b4SEd Tanous                                            "MetricReportDefinition", id);
797081ebf06SWludzik, Jozef                 return;
798081ebf06SWludzik, Jozef             }
799081ebf06SWludzik, Jozef             if (ec)
800081ebf06SWludzik, Jozef             {
801081ebf06SWludzik, Jozef                 BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
802081ebf06SWludzik, Jozef                 messages::internalError(asyncResp->res);
803081ebf06SWludzik, Jozef                 return;
804081ebf06SWludzik, Jozef             }
805081ebf06SWludzik, Jozef 
806*479e899dSKrzysztof Grobelny             telemetry::fillReportDefinition(asyncResp, id, properties);
80789474494SKrzysztof Grobelny             });
8087e860f15SJohn Edward Broadbent         });
809*479e899dSKrzysztof Grobelny 
8107e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
8117e860f15SJohn Edward Broadbent                  "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/")
812ed398213SEd Tanous         .privileges(redfish::privileges::deleteMetricReportDefinitionCollection)
8137e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::delete_)(
81445ca1b86SEd Tanous             [&app](const crow::Request& req,
8157e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
8167e860f15SJohn Edward Broadbent                    const std::string& id)
8174dbb8aeaSWludzik, Jozef 
8184dbb8aeaSWludzik, Jozef             {
8193ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
82045ca1b86SEd Tanous         {
82145ca1b86SEd Tanous             return;
82245ca1b86SEd Tanous         }
82345ca1b86SEd Tanous 
8244dbb8aeaSWludzik, Jozef         const std::string reportPath = telemetry::getDbusReportPath(id);
8254dbb8aeaSWludzik, Jozef 
8264dbb8aeaSWludzik, Jozef         crow::connections::systemBus->async_method_call(
8275e7e2dc5SEd Tanous             [asyncResp, id](const boost::system::error_code& ec) {
8284dbb8aeaSWludzik, Jozef             /*
8297e860f15SJohn Edward Broadbent              * boost::system::errc and std::errc are missing value
8307e860f15SJohn Edward Broadbent              * for EBADR error that is defined in Linux.
8314dbb8aeaSWludzik, Jozef              */
8324dbb8aeaSWludzik, Jozef             if (ec.value() == EBADR)
8334dbb8aeaSWludzik, Jozef             {
834002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res,
835002d39b4SEd Tanous                                            "MetricReportDefinition", id);
8364dbb8aeaSWludzik, Jozef                 return;
8374dbb8aeaSWludzik, Jozef             }
8384dbb8aeaSWludzik, Jozef 
8394dbb8aeaSWludzik, Jozef             if (ec)
8404dbb8aeaSWludzik, Jozef             {
8414dbb8aeaSWludzik, Jozef                 BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
8424dbb8aeaSWludzik, Jozef                 messages::internalError(asyncResp->res);
8434dbb8aeaSWludzik, Jozef                 return;
8444dbb8aeaSWludzik, Jozef             }
8454dbb8aeaSWludzik, Jozef 
846002d39b4SEd Tanous             asyncResp->res.result(boost::beast::http::status::no_content);
8474dbb8aeaSWludzik, Jozef             },
848002d39b4SEd Tanous             telemetry::service, reportPath, "xyz.openbmc_project.Object.Delete",
849002d39b4SEd Tanous             "Delete");
8507e860f15SJohn Edward Broadbent         });
8514dbb8aeaSWludzik, Jozef }
852081ebf06SWludzik, Jozef } // namespace redfish
853