xref: /openbmc/bmcweb/features/redfish/lib/metric_report_definition.hpp (revision dd1c4a9ca36e742fc4796a152cd72b850738a648)
1081ebf06SWludzik, Jozef #pragma once
2081ebf06SWludzik, Jozef 
33ccb3adbSEd Tanous #include "app.hpp"
43ccb3adbSEd Tanous #include "dbus_utility.hpp"
5479e899dSKrzysztof 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>
21f19ab44aSSzymon Dompke #include <optional>
22f19ab44aSSzymon Dompke #include <span>
23f19ab44aSSzymon Dompke #include <string>
247a1dbc48SGeorge Liu #include <string_view>
25081ebf06SWludzik, Jozef #include <tuple>
26f19ab44aSSzymon Dompke #include <utility>
27081ebf06SWludzik, Jozef #include <variant>
28f19ab44aSSzymon Dompke #include <vector>
29081ebf06SWludzik, Jozef 
30081ebf06SWludzik, Jozef namespace redfish
31081ebf06SWludzik, Jozef {
32081ebf06SWludzik, Jozef 
33081ebf06SWludzik, Jozef namespace telemetry
34081ebf06SWludzik, Jozef {
35081ebf06SWludzik, Jozef 
36479e899dSKrzysztof Grobelny using ReadingParameters = std::vector<std::tuple<
37479e899dSKrzysztof Grobelny     std::vector<std::tuple<sdbusplus::message::object_path, std::string>>,
38479e899dSKrzysztof Grobelny     std::string, std::string, uint64_t>>;
39479e899dSKrzysztof Grobelny 
40479e899dSKrzysztof Grobelny inline metric_report_definition::ReportActionsEnum
41479e899dSKrzysztof Grobelny     toRedfishReportAction(std::string_view dbusValue)
42479e899dSKrzysztof Grobelny {
43479e899dSKrzysztof Grobelny     if (dbusValue ==
44479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportActions.EmitsReadingsUpdate")
45479e899dSKrzysztof Grobelny     {
46479e899dSKrzysztof Grobelny         return metric_report_definition::ReportActionsEnum::RedfishEvent;
47479e899dSKrzysztof Grobelny     }
48479e899dSKrzysztof Grobelny     if (dbusValue ==
49479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportActions.LogToMetricReportsCollection")
50479e899dSKrzysztof Grobelny     {
51479e899dSKrzysztof Grobelny         return metric_report_definition::ReportActionsEnum::
52479e899dSKrzysztof Grobelny             LogToMetricReportsCollection;
53479e899dSKrzysztof Grobelny     }
54479e899dSKrzysztof Grobelny     return metric_report_definition::ReportActionsEnum::Invalid;
55479e899dSKrzysztof Grobelny }
56479e899dSKrzysztof Grobelny 
57479e899dSKrzysztof Grobelny inline std::string toDbusReportAction(std::string_view redfishValue)
58479e899dSKrzysztof Grobelny {
59479e899dSKrzysztof Grobelny     if (redfishValue == "RedfishEvent")
60479e899dSKrzysztof Grobelny     {
61479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportActions.EmitsReadingsUpdate";
62479e899dSKrzysztof Grobelny     }
63479e899dSKrzysztof Grobelny     if (redfishValue == "LogToMetricReportsCollection")
64479e899dSKrzysztof Grobelny     {
65479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportActions.LogToMetricReportsCollection";
66479e899dSKrzysztof Grobelny     }
67479e899dSKrzysztof Grobelny     return "";
68479e899dSKrzysztof Grobelny }
69479e899dSKrzysztof Grobelny 
70479e899dSKrzysztof Grobelny inline metric_report_definition::MetricReportDefinitionType
71479e899dSKrzysztof Grobelny     toRedfishReportingType(std::string_view dbusValue)
72479e899dSKrzysztof Grobelny {
73479e899dSKrzysztof Grobelny     if (dbusValue ==
74479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportingType.OnChange")
75479e899dSKrzysztof Grobelny     {
76479e899dSKrzysztof Grobelny         return metric_report_definition::MetricReportDefinitionType::OnChange;
77479e899dSKrzysztof Grobelny     }
78479e899dSKrzysztof Grobelny     if (dbusValue ==
79479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportingType.OnRequest")
80479e899dSKrzysztof Grobelny     {
81479e899dSKrzysztof Grobelny         return metric_report_definition::MetricReportDefinitionType::OnRequest;
82479e899dSKrzysztof Grobelny     }
83479e899dSKrzysztof Grobelny     if (dbusValue ==
84479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportingType.Periodic")
85479e899dSKrzysztof Grobelny     {
86479e899dSKrzysztof Grobelny         return metric_report_definition::MetricReportDefinitionType::Periodic;
87479e899dSKrzysztof Grobelny     }
88479e899dSKrzysztof Grobelny     return metric_report_definition::MetricReportDefinitionType::Invalid;
89479e899dSKrzysztof Grobelny }
90479e899dSKrzysztof Grobelny 
91479e899dSKrzysztof Grobelny inline std::string toDbusReportingType(std::string_view redfishValue)
92479e899dSKrzysztof Grobelny {
93479e899dSKrzysztof Grobelny     if (redfishValue == "OnChange")
94479e899dSKrzysztof Grobelny     {
95479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportingType.OnChange";
96479e899dSKrzysztof Grobelny     }
97479e899dSKrzysztof Grobelny     if (redfishValue == "OnRequest")
98479e899dSKrzysztof Grobelny     {
99479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportingType.OnRequest";
100479e899dSKrzysztof Grobelny     }
101479e899dSKrzysztof Grobelny     if (redfishValue == "Periodic")
102479e899dSKrzysztof Grobelny     {
103479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportingType.Periodic";
104479e899dSKrzysztof Grobelny     }
105479e899dSKrzysztof Grobelny     return "";
106479e899dSKrzysztof Grobelny }
107479e899dSKrzysztof Grobelny 
108479e899dSKrzysztof Grobelny inline metric_report_definition::CollectionTimeScope
109479e899dSKrzysztof Grobelny     toRedfishCollectionTimeScope(std::string_view dbusValue)
110479e899dSKrzysztof Grobelny {
111479e899dSKrzysztof Grobelny     if (dbusValue ==
112479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.Point")
113479e899dSKrzysztof Grobelny     {
114479e899dSKrzysztof Grobelny         return metric_report_definition::CollectionTimeScope::Point;
115479e899dSKrzysztof Grobelny     }
116479e899dSKrzysztof Grobelny     if (dbusValue ==
117479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.Interval")
118479e899dSKrzysztof Grobelny     {
119479e899dSKrzysztof Grobelny         return metric_report_definition::CollectionTimeScope::Interval;
120479e899dSKrzysztof Grobelny     }
121479e899dSKrzysztof Grobelny     if (dbusValue ==
122479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.StartupInterval")
123479e899dSKrzysztof Grobelny     {
124479e899dSKrzysztof Grobelny         return metric_report_definition::CollectionTimeScope::StartupInterval;
125479e899dSKrzysztof Grobelny     }
126479e899dSKrzysztof Grobelny     return metric_report_definition::CollectionTimeScope::Invalid;
127479e899dSKrzysztof Grobelny }
128479e899dSKrzysztof Grobelny 
129479e899dSKrzysztof Grobelny inline std::string toDbusCollectionTimeScope(std::string_view redfishValue)
130479e899dSKrzysztof Grobelny {
131479e899dSKrzysztof Grobelny     if (redfishValue == "Point")
132479e899dSKrzysztof Grobelny     {
133479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.Point";
134479e899dSKrzysztof Grobelny     }
135479e899dSKrzysztof Grobelny     if (redfishValue == "Interval")
136479e899dSKrzysztof Grobelny     {
137479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.Interval";
138479e899dSKrzysztof Grobelny     }
139479e899dSKrzysztof Grobelny     if (redfishValue == "StartupInterval")
140479e899dSKrzysztof Grobelny     {
141479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.CollectionTimescope.StartupInterval";
142479e899dSKrzysztof Grobelny     }
143479e899dSKrzysztof Grobelny     return "";
144479e899dSKrzysztof Grobelny }
145479e899dSKrzysztof Grobelny 
146479e899dSKrzysztof Grobelny inline metric_report_definition::ReportUpdatesEnum
147479e899dSKrzysztof Grobelny     toRedfishReportUpdates(std::string_view dbusValue)
148479e899dSKrzysztof Grobelny {
149479e899dSKrzysztof Grobelny     if (dbusValue ==
150479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportUpdates.Overwrite")
151479e899dSKrzysztof Grobelny     {
152479e899dSKrzysztof Grobelny         return metric_report_definition::ReportUpdatesEnum::Overwrite;
153479e899dSKrzysztof Grobelny     }
154479e899dSKrzysztof Grobelny     if (dbusValue ==
155479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportUpdates.AppendWrapsWhenFull")
156479e899dSKrzysztof Grobelny     {
157479e899dSKrzysztof Grobelny         return metric_report_definition::ReportUpdatesEnum::AppendWrapsWhenFull;
158479e899dSKrzysztof Grobelny     }
159479e899dSKrzysztof Grobelny     if (dbusValue ==
160479e899dSKrzysztof Grobelny         "xyz.openbmc_project.Telemetry.Report.ReportUpdates.AppendStopsWhenFull")
161479e899dSKrzysztof Grobelny     {
162479e899dSKrzysztof Grobelny         return metric_report_definition::ReportUpdatesEnum::AppendStopsWhenFull;
163479e899dSKrzysztof Grobelny     }
164479e899dSKrzysztof Grobelny     return metric_report_definition::ReportUpdatesEnum::Invalid;
165479e899dSKrzysztof Grobelny }
166479e899dSKrzysztof Grobelny 
167479e899dSKrzysztof Grobelny inline std::string toDbusReportUpdates(std::string_view redfishValue)
168479e899dSKrzysztof Grobelny {
169479e899dSKrzysztof Grobelny     if (redfishValue == "Overwrite")
170479e899dSKrzysztof Grobelny     {
171479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportUpdates.Overwrite";
172479e899dSKrzysztof Grobelny     }
173479e899dSKrzysztof Grobelny     if (redfishValue == "AppendWrapsWhenFull")
174479e899dSKrzysztof Grobelny     {
175479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportUpdates.AppendWrapsWhenFull";
176479e899dSKrzysztof Grobelny     }
177479e899dSKrzysztof Grobelny     if (redfishValue == "AppendStopsWhenFull")
178479e899dSKrzysztof Grobelny     {
179479e899dSKrzysztof Grobelny         return "xyz.openbmc_project.Telemetry.Report.ReportUpdates.AppendStopsWhenFull";
180479e899dSKrzysztof Grobelny     }
181479e899dSKrzysztof Grobelny     return "";
182479e899dSKrzysztof Grobelny }
183081ebf06SWludzik, Jozef 
184f19ab44aSSzymon Dompke inline std::optional<nlohmann::json::array_t> getLinkedTriggers(
185f19ab44aSSzymon Dompke     std::span<const sdbusplus::message::object_path> triggerPaths)
186f19ab44aSSzymon Dompke {
187f19ab44aSSzymon Dompke     nlohmann::json::array_t triggers;
188f19ab44aSSzymon Dompke 
189f19ab44aSSzymon Dompke     for (const sdbusplus::message::object_path& path : triggerPaths)
190f19ab44aSSzymon Dompke     {
191f19ab44aSSzymon Dompke         if (path.parent_path() !=
192f19ab44aSSzymon Dompke             "/xyz/openbmc_project/Telemetry/Triggers/TelemetryService")
193f19ab44aSSzymon Dompke         {
194f19ab44aSSzymon Dompke             BMCWEB_LOG_ERROR << "Property Triggers contains invalid value: "
195f19ab44aSSzymon Dompke                              << path.str;
196f19ab44aSSzymon Dompke             return std::nullopt;
197f19ab44aSSzymon Dompke         }
198f19ab44aSSzymon Dompke 
199f19ab44aSSzymon Dompke         std::string id = path.filename();
200f19ab44aSSzymon Dompke         if (id.empty())
201f19ab44aSSzymon Dompke         {
202f19ab44aSSzymon Dompke             BMCWEB_LOG_ERROR << "Property Triggers contains invalid value: "
203f19ab44aSSzymon Dompke                              << path.str;
204f19ab44aSSzymon Dompke             return std::nullopt;
205f19ab44aSSzymon Dompke         }
206f19ab44aSSzymon Dompke         nlohmann::json::object_t trigger;
207f19ab44aSSzymon Dompke         trigger["@odata.id"] =
208f19ab44aSSzymon Dompke             boost::urls::format("/redfish/v1/TelemetryService/Triggers/{}", id);
209f19ab44aSSzymon Dompke         triggers.emplace_back(std::move(trigger));
210f19ab44aSSzymon Dompke     }
211f19ab44aSSzymon Dompke 
212f19ab44aSSzymon Dompke     return triggers;
213f19ab44aSSzymon Dompke }
214f19ab44aSSzymon Dompke 
215b9d36b47SEd Tanous inline void
216b9d36b47SEd Tanous     fillReportDefinition(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
217b9d36b47SEd Tanous                          const std::string& id,
218479e899dSKrzysztof Grobelny                          const dbus::utility::DBusPropertiesMap& properties)
219081ebf06SWludzik, Jozef {
220479e899dSKrzysztof Grobelny     std::vector<std::string> reportActions;
221479e899dSKrzysztof Grobelny     ReadingParameters readingParams;
222479e899dSKrzysztof Grobelny     std::string reportingType;
223479e899dSKrzysztof Grobelny     std::string reportUpdates;
224479e899dSKrzysztof Grobelny     std::string name;
225479e899dSKrzysztof Grobelny     uint64_t appendLimit = 0;
226479e899dSKrzysztof Grobelny     uint64_t interval = 0;
227479e899dSKrzysztof Grobelny     bool enabled = false;
228f19ab44aSSzymon Dompke     std::vector<sdbusplus::message::object_path> triggers;
22989474494SKrzysztof Grobelny 
23089474494SKrzysztof Grobelny     const bool success = sdbusplus::unpackPropertiesNoThrow(
231479e899dSKrzysztof Grobelny         dbus_utils::UnpackErrorPrinter(), properties, "ReportingType",
232479e899dSKrzysztof Grobelny         reportingType, "Interval", interval, "ReportActions", reportActions,
233479e899dSKrzysztof Grobelny         "ReportUpdates", reportUpdates, "AppendLimit", appendLimit,
234f19ab44aSSzymon Dompke         "ReadingParameters", readingParams, "Name", name, "Enabled", enabled,
235f19ab44aSSzymon Dompke         "Triggers", triggers);
23689474494SKrzysztof Grobelny 
23789474494SKrzysztof Grobelny     if (!success)
238081ebf06SWludzik, Jozef     {
239081ebf06SWludzik, Jozef         messages::internalError(asyncResp->res);
240081ebf06SWludzik, Jozef         return;
241081ebf06SWludzik, Jozef     }
242081ebf06SWludzik, Jozef 
243479e899dSKrzysztof Grobelny     metric_report_definition::MetricReportDefinitionType redfishReportingType =
244479e899dSKrzysztof Grobelny         toRedfishReportingType(reportingType);
245479e899dSKrzysztof Grobelny     if (redfishReportingType ==
246479e899dSKrzysztof Grobelny         metric_report_definition::MetricReportDefinitionType::Invalid)
247081ebf06SWludzik, Jozef     {
248479e899dSKrzysztof Grobelny         messages::internalError(asyncResp->res);
249479e899dSKrzysztof Grobelny         return;
250081ebf06SWludzik, Jozef     }
25189474494SKrzysztof Grobelny 
252479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["MetricReportDefinitionType"] =
253479e899dSKrzysztof Grobelny         redfishReportingType;
254479e899dSKrzysztof Grobelny 
255f19ab44aSSzymon Dompke     std::optional<nlohmann::json::array_t> linkedTriggers =
256f19ab44aSSzymon Dompke         getLinkedTriggers(triggers);
257f19ab44aSSzymon Dompke     if (!linkedTriggers)
258f19ab44aSSzymon Dompke     {
259f19ab44aSSzymon Dompke         messages::internalError(asyncResp->res);
260f19ab44aSSzymon Dompke         return;
261f19ab44aSSzymon Dompke     }
262f19ab44aSSzymon Dompke 
263f19ab44aSSzymon Dompke     asyncResp->res.jsonValue["Links"]["Triggers"] = std::move(*linkedTriggers);
264f19ab44aSSzymon Dompke 
265479e899dSKrzysztof Grobelny     nlohmann::json::array_t redfishReportActions;
266479e899dSKrzysztof Grobelny     for (const std::string& action : reportActions)
267081ebf06SWludzik, Jozef     {
268479e899dSKrzysztof Grobelny         metric_report_definition::ReportActionsEnum redfishAction =
269479e899dSKrzysztof Grobelny             toRedfishReportAction(action);
270479e899dSKrzysztof Grobelny         if (redfishAction ==
271479e899dSKrzysztof Grobelny             metric_report_definition::ReportActionsEnum::Invalid)
272479e899dSKrzysztof Grobelny         {
273479e899dSKrzysztof Grobelny             messages::internalError(asyncResp->res);
274479e899dSKrzysztof Grobelny             return;
275081ebf06SWludzik, Jozef         }
276081ebf06SWludzik, Jozef 
277479e899dSKrzysztof Grobelny         redfishReportActions.emplace_back(redfishAction);
278479e899dSKrzysztof Grobelny     }
279479e899dSKrzysztof Grobelny 
280479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["ReportActions"] = std::move(redfishReportActions);
281479e899dSKrzysztof Grobelny 
282479e899dSKrzysztof Grobelny     nlohmann::json::array_t metrics = nlohmann::json::array();
283479e899dSKrzysztof Grobelny     for (const auto& [sensorData, collectionFunction, collectionTimeScope,
284479e899dSKrzysztof Grobelny                       collectionDuration] : readingParams)
28589474494SKrzysztof Grobelny     {
286479e899dSKrzysztof Grobelny         nlohmann::json::array_t metricProperties;
287479e899dSKrzysztof Grobelny 
288479e899dSKrzysztof Grobelny         for (const auto& [sensorPath, sensorMetadata] : sensorData)
289081ebf06SWludzik, Jozef         {
290479e899dSKrzysztof Grobelny             metricProperties.emplace_back(sensorMetadata);
291479e899dSKrzysztof Grobelny         }
292479e899dSKrzysztof Grobelny 
293613dabeaSEd Tanous         nlohmann::json::object_t metric;
294479e899dSKrzysztof Grobelny 
295479e899dSKrzysztof Grobelny         metric_report_definition::CalculationAlgorithmEnum
296479e899dSKrzysztof Grobelny             redfishCollectionFunction =
297479e899dSKrzysztof Grobelny                 telemetry::toRedfishCollectionFunction(collectionFunction);
298479e899dSKrzysztof Grobelny         if (redfishCollectionFunction ==
299479e899dSKrzysztof Grobelny             metric_report_definition::CalculationAlgorithmEnum::Invalid)
300479e899dSKrzysztof Grobelny         {
301479e899dSKrzysztof Grobelny             messages::internalError(asyncResp->res);
302479e899dSKrzysztof Grobelny             return;
303479e899dSKrzysztof Grobelny         }
304479e899dSKrzysztof Grobelny         metric["CollectionFunction"] = redfishCollectionFunction;
305479e899dSKrzysztof Grobelny 
306479e899dSKrzysztof Grobelny         metric_report_definition::CollectionTimeScope
307479e899dSKrzysztof Grobelny             redfishCollectionTimeScope =
308479e899dSKrzysztof Grobelny                 toRedfishCollectionTimeScope(collectionTimeScope);
309479e899dSKrzysztof Grobelny         if (redfishCollectionTimeScope ==
310479e899dSKrzysztof Grobelny             metric_report_definition::CollectionTimeScope::Invalid)
311479e899dSKrzysztof Grobelny         {
312479e899dSKrzysztof Grobelny             messages::internalError(asyncResp->res);
313479e899dSKrzysztof Grobelny             return;
314479e899dSKrzysztof Grobelny         }
315479e899dSKrzysztof Grobelny         metric["CollectionTimeScope"] = redfishCollectionTimeScope;
316479e899dSKrzysztof Grobelny 
317479e899dSKrzysztof Grobelny         metric["MetricProperties"] = std::move(metricProperties);
318479e899dSKrzysztof Grobelny         metric["CollectionDuration"] = time_utils::toDurationString(
319479e899dSKrzysztof Grobelny             std::chrono::milliseconds(collectionDuration));
320b2ba3072SPatrick Williams         metrics.emplace_back(std::move(metric));
321081ebf06SWludzik, Jozef     }
322479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["Metrics"] = std::move(metrics);
323479e899dSKrzysztof Grobelny 
324479e899dSKrzysztof Grobelny     if (enabled)
325479e899dSKrzysztof Grobelny     {
326479e899dSKrzysztof Grobelny         asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
327479e899dSKrzysztof Grobelny     }
328479e899dSKrzysztof Grobelny     else
329479e899dSKrzysztof Grobelny     {
330479e899dSKrzysztof Grobelny         asyncResp->res.jsonValue["Status"]["State"] = "Disabled";
33189474494SKrzysztof Grobelny     }
33289474494SKrzysztof Grobelny 
333479e899dSKrzysztof Grobelny     metric_report_definition::ReportUpdatesEnum redfishReportUpdates =
334479e899dSKrzysztof Grobelny         toRedfishReportUpdates(reportUpdates);
335479e899dSKrzysztof Grobelny     if (redfishReportUpdates ==
336479e899dSKrzysztof Grobelny         metric_report_definition::ReportUpdatesEnum::Invalid)
33789474494SKrzysztof Grobelny     {
338479e899dSKrzysztof Grobelny         messages::internalError(asyncResp->res);
339479e899dSKrzysztof Grobelny         return;
34089474494SKrzysztof Grobelny     }
341479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["ReportUpdates"] = redfishReportUpdates;
34289474494SKrzysztof Grobelny 
343479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["MetricReportDefinitionEnabled"] = enabled;
344479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["AppendLimit"] = appendLimit;
345479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["Name"] = name;
346081ebf06SWludzik, Jozef     asyncResp->res.jsonValue["Schedule"]["RecurrenceInterval"] =
347479e899dSKrzysztof Grobelny         time_utils::toDurationString(std::chrono::milliseconds(interval));
348479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["@odata.type"] =
349479e899dSKrzysztof Grobelny         "#MetricReportDefinition.v1_3_0.MetricReportDefinition";
350479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
351479e899dSKrzysztof Grobelny         "/redfish/v1/TelemetryService/MetricReportDefinitions/{}", id);
352479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["Id"] = id;
353479e899dSKrzysztof Grobelny     asyncResp->res.jsonValue["MetricReport"]["@odata.id"] = boost::urls::format(
354479e899dSKrzysztof Grobelny         "/redfish/v1/TelemetryService/MetricReports/{}", id);
35589474494SKrzysztof Grobelny }
35689474494SKrzysztof Grobelny 
3574dbb8aeaSWludzik, Jozef struct AddReportArgs
3584dbb8aeaSWludzik, Jozef {
359479e899dSKrzysztof Grobelny     struct MetricArgs
360479e899dSKrzysztof Grobelny     {
361479e899dSKrzysztof Grobelny         std::vector<std::string> uris;
362479e899dSKrzysztof Grobelny         std::string collectionFunction;
363479e899dSKrzysztof Grobelny         std::string collectionTimeScope;
364479e899dSKrzysztof Grobelny         uint64_t collectionDuration = 0;
365479e899dSKrzysztof Grobelny     };
366479e899dSKrzysztof Grobelny 
367479e899dSKrzysztof Grobelny     std::string id;
3684dbb8aeaSWludzik, Jozef     std::string name;
3694dbb8aeaSWludzik, Jozef     std::string reportingType;
370479e899dSKrzysztof Grobelny     std::string reportUpdates;
371479e899dSKrzysztof Grobelny     uint64_t appendLimit = std::numeric_limits<uint64_t>::max();
372479e899dSKrzysztof Grobelny     std::vector<std::string> reportActions;
373479e899dSKrzysztof Grobelny     uint64_t interval = std::numeric_limits<uint64_t>::max();
374479e899dSKrzysztof Grobelny     std::vector<MetricArgs> metrics;
375479e899dSKrzysztof Grobelny     bool metricReportDefinitionEnabled = true;
3764dbb8aeaSWludzik, Jozef };
3774dbb8aeaSWludzik, Jozef 
3784dbb8aeaSWludzik, Jozef inline bool toDbusReportActions(crow::Response& res,
379479e899dSKrzysztof Grobelny                                 const std::vector<std::string>& actions,
3804dbb8aeaSWludzik, Jozef                                 AddReportArgs& args)
3814dbb8aeaSWludzik, Jozef {
3824dbb8aeaSWludzik, Jozef     size_t index = 0;
383479e899dSKrzysztof Grobelny     for (const std::string& action : actions)
3844dbb8aeaSWludzik, Jozef     {
385479e899dSKrzysztof Grobelny         std::string dbusReportAction = toDbusReportAction(action);
386479e899dSKrzysztof Grobelny         if (dbusReportAction.empty())
3874dbb8aeaSWludzik, Jozef         {
388479e899dSKrzysztof Grobelny             messages::propertyValueNotInList(res, nlohmann::json(action).dump(),
389479e899dSKrzysztof Grobelny                                              "ReportActions/" +
390479e899dSKrzysztof Grobelny                                                  std::to_string(index));
3914dbb8aeaSWludzik, Jozef             return false;
3924dbb8aeaSWludzik, Jozef         }
393479e899dSKrzysztof Grobelny 
394479e899dSKrzysztof Grobelny         args.reportActions.emplace_back(std::move(dbusReportAction));
3954dbb8aeaSWludzik, Jozef         index++;
3964dbb8aeaSWludzik, Jozef     }
3974dbb8aeaSWludzik, Jozef     return true;
3984dbb8aeaSWludzik, Jozef }
3994dbb8aeaSWludzik, Jozef 
400479e899dSKrzysztof Grobelny inline bool getUserMetric(crow::Response& res, nlohmann::json& metric,
401479e899dSKrzysztof Grobelny                           AddReportArgs::MetricArgs& metricArgs)
402479e899dSKrzysztof Grobelny {
403479e899dSKrzysztof Grobelny     std::optional<std::vector<std::string>> uris;
404479e899dSKrzysztof Grobelny     std::optional<std::string> collectionDurationStr;
405479e899dSKrzysztof Grobelny     std::optional<std::string> collectionFunction;
406479e899dSKrzysztof Grobelny     std::optional<std::string> collectionTimeScopeStr;
407479e899dSKrzysztof Grobelny 
408479e899dSKrzysztof Grobelny     if (!json_util::readJson(metric, res, "MetricProperties", uris,
409479e899dSKrzysztof Grobelny                              "CollectionFunction", collectionFunction,
410479e899dSKrzysztof Grobelny                              "CollectionTimeScope", collectionTimeScopeStr,
411479e899dSKrzysztof Grobelny                              "CollectionDuration", collectionDurationStr))
412479e899dSKrzysztof Grobelny     {
413479e899dSKrzysztof Grobelny         return false;
414479e899dSKrzysztof Grobelny     }
415479e899dSKrzysztof Grobelny 
416479e899dSKrzysztof Grobelny     if (uris)
417479e899dSKrzysztof Grobelny     {
418479e899dSKrzysztof Grobelny         metricArgs.uris = std::move(*uris);
419479e899dSKrzysztof Grobelny     }
420479e899dSKrzysztof Grobelny 
421479e899dSKrzysztof Grobelny     if (collectionFunction)
422479e899dSKrzysztof Grobelny     {
423479e899dSKrzysztof Grobelny         std::string dbusCollectionFunction =
424479e899dSKrzysztof Grobelny             telemetry::toDbusCollectionFunction(*collectionFunction);
425479e899dSKrzysztof Grobelny         if (dbusCollectionFunction.empty())
426479e899dSKrzysztof Grobelny         {
427479e899dSKrzysztof Grobelny             messages::propertyValueIncorrect(res, "CollectionFunction",
428479e899dSKrzysztof Grobelny                                              *collectionFunction);
429479e899dSKrzysztof Grobelny             return false;
430479e899dSKrzysztof Grobelny         }
431479e899dSKrzysztof Grobelny         metricArgs.collectionFunction = std::move(dbusCollectionFunction);
432479e899dSKrzysztof Grobelny     }
433479e899dSKrzysztof Grobelny 
434479e899dSKrzysztof Grobelny     if (collectionTimeScopeStr)
435479e899dSKrzysztof Grobelny     {
436479e899dSKrzysztof Grobelny         std::string dbusCollectionTimeScope =
437479e899dSKrzysztof Grobelny             toDbusCollectionTimeScope(*collectionTimeScopeStr);
438479e899dSKrzysztof Grobelny         if (dbusCollectionTimeScope.empty())
439479e899dSKrzysztof Grobelny         {
440479e899dSKrzysztof Grobelny             messages::propertyValueIncorrect(res, "CollectionTimeScope",
441479e899dSKrzysztof Grobelny                                              *collectionTimeScopeStr);
442479e899dSKrzysztof Grobelny             return false;
443479e899dSKrzysztof Grobelny         }
444479e899dSKrzysztof Grobelny         metricArgs.collectionTimeScope = std::move(dbusCollectionTimeScope);
445479e899dSKrzysztof Grobelny     }
446479e899dSKrzysztof Grobelny 
447479e899dSKrzysztof Grobelny     if (collectionDurationStr)
448479e899dSKrzysztof Grobelny     {
449479e899dSKrzysztof Grobelny         std::optional<std::chrono::milliseconds> duration =
450479e899dSKrzysztof Grobelny             time_utils::fromDurationString(*collectionDurationStr);
451479e899dSKrzysztof Grobelny 
452479e899dSKrzysztof Grobelny         if (!duration || duration->count() < 0)
453479e899dSKrzysztof Grobelny         {
454479e899dSKrzysztof Grobelny             messages::propertyValueIncorrect(res, "CollectionDuration",
455479e899dSKrzysztof Grobelny                                              *collectionDurationStr);
456479e899dSKrzysztof Grobelny             return false;
457479e899dSKrzysztof Grobelny         }
458479e899dSKrzysztof Grobelny 
459479e899dSKrzysztof Grobelny         metricArgs.collectionDuration =
460479e899dSKrzysztof Grobelny             static_cast<uint64_t>(duration->count());
461479e899dSKrzysztof Grobelny     }
462479e899dSKrzysztof Grobelny 
463479e899dSKrzysztof Grobelny     return true;
464479e899dSKrzysztof Grobelny }
465479e899dSKrzysztof Grobelny 
466479e899dSKrzysztof Grobelny inline bool getUserMetrics(crow::Response& res,
467479e899dSKrzysztof Grobelny                            std::span<nlohmann::json> metrics,
468479e899dSKrzysztof Grobelny                            std::vector<AddReportArgs::MetricArgs>& result)
469479e899dSKrzysztof Grobelny {
470479e899dSKrzysztof Grobelny     result.reserve(metrics.size());
471479e899dSKrzysztof Grobelny 
472479e899dSKrzysztof Grobelny     for (nlohmann::json& m : metrics)
473479e899dSKrzysztof Grobelny     {
474479e899dSKrzysztof Grobelny         AddReportArgs::MetricArgs metricArgs;
475479e899dSKrzysztof Grobelny 
476479e899dSKrzysztof Grobelny         if (!getUserMetric(res, m, metricArgs))
477479e899dSKrzysztof Grobelny         {
478479e899dSKrzysztof Grobelny             return false;
479479e899dSKrzysztof Grobelny         }
480479e899dSKrzysztof Grobelny 
481479e899dSKrzysztof Grobelny         result.emplace_back(std::move(metricArgs));
482479e899dSKrzysztof Grobelny     }
483479e899dSKrzysztof Grobelny 
484479e899dSKrzysztof Grobelny     return true;
485479e899dSKrzysztof Grobelny }
486479e899dSKrzysztof Grobelny 
4874dbb8aeaSWludzik, Jozef inline bool getUserParameters(crow::Response& res, const crow::Request& req,
4884dbb8aeaSWludzik, Jozef                               AddReportArgs& args)
4894dbb8aeaSWludzik, Jozef {
490479e899dSKrzysztof Grobelny     std::optional<std::string> id;
491479e899dSKrzysztof Grobelny     std::optional<std::string> name;
492479e899dSKrzysztof Grobelny     std::optional<std::string> reportingTypeStr;
493479e899dSKrzysztof Grobelny     std::optional<std::string> reportUpdatesStr;
494479e899dSKrzysztof Grobelny     std::optional<uint64_t> appendLimit;
495479e899dSKrzysztof Grobelny     std::optional<bool> metricReportDefinitionEnabled;
496479e899dSKrzysztof Grobelny     std::optional<std::vector<nlohmann::json>> metrics;
497479e899dSKrzysztof Grobelny     std::optional<std::vector<std::string>> reportActionsStr;
4984dbb8aeaSWludzik, Jozef     std::optional<nlohmann::json> schedule;
499479e899dSKrzysztof Grobelny 
500479e899dSKrzysztof Grobelny     if (!json_util::readJsonPatch(
501479e899dSKrzysztof Grobelny             req, res, "Id", id, "Name", name, "Metrics", metrics,
502479e899dSKrzysztof Grobelny             "MetricReportDefinitionType", reportingTypeStr, "ReportUpdates",
503479e899dSKrzysztof Grobelny             reportUpdatesStr, "AppendLimit", appendLimit, "ReportActions",
504479e899dSKrzysztof Grobelny             reportActionsStr, "Schedule", schedule,
505479e899dSKrzysztof Grobelny             "MetricReportDefinitionEnabled", metricReportDefinitionEnabled))
5064dbb8aeaSWludzik, Jozef     {
5074dbb8aeaSWludzik, Jozef         return false;
5084dbb8aeaSWludzik, Jozef     }
5094dbb8aeaSWludzik, Jozef 
510479e899dSKrzysztof Grobelny     if (id)
511479e899dSKrzysztof Grobelny     {
512479e899dSKrzysztof Grobelny         constexpr const char* allowedCharactersInId =
5134dbb8aeaSWludzik, Jozef             "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
514479e899dSKrzysztof Grobelny         if (id->empty() ||
515479e899dSKrzysztof Grobelny             id->find_first_not_of(allowedCharactersInId) != std::string::npos)
5164dbb8aeaSWludzik, Jozef         {
517479e899dSKrzysztof Grobelny             messages::propertyValueIncorrect(res, "Id", *id);
5184dbb8aeaSWludzik, Jozef             return false;
5194dbb8aeaSWludzik, Jozef         }
520479e899dSKrzysztof Grobelny         args.id = *id;
521479e899dSKrzysztof Grobelny     }
5224dbb8aeaSWludzik, Jozef 
523479e899dSKrzysztof Grobelny     if (name)
5244dbb8aeaSWludzik, Jozef     {
525479e899dSKrzysztof Grobelny         args.name = *name;
526479e899dSKrzysztof Grobelny     }
527479e899dSKrzysztof Grobelny 
528479e899dSKrzysztof Grobelny     if (reportingTypeStr)
529479e899dSKrzysztof Grobelny     {
530479e899dSKrzysztof Grobelny         std::string dbusReportingType = toDbusReportingType(*reportingTypeStr);
531479e899dSKrzysztof Grobelny         if (dbusReportingType.empty())
532479e899dSKrzysztof Grobelny         {
533479e899dSKrzysztof Grobelny             messages::propertyValueNotInList(res, *reportingTypeStr,
5344dbb8aeaSWludzik, Jozef                                              "MetricReportDefinitionType");
5354dbb8aeaSWludzik, Jozef             return false;
5364dbb8aeaSWludzik, Jozef         }
537479e899dSKrzysztof Grobelny         args.reportingType = dbusReportingType;
538479e899dSKrzysztof Grobelny     }
5394dbb8aeaSWludzik, Jozef 
540479e899dSKrzysztof Grobelny     if (reportUpdatesStr)
541479e899dSKrzysztof Grobelny     {
542479e899dSKrzysztof Grobelny         std::string dbusReportUpdates = toDbusReportUpdates(*reportUpdatesStr);
543479e899dSKrzysztof Grobelny         if (dbusReportUpdates.empty())
544479e899dSKrzysztof Grobelny         {
545479e899dSKrzysztof Grobelny             messages::propertyValueNotInList(res, *reportUpdatesStr,
546479e899dSKrzysztof Grobelny                                              "ReportUpdates");
547479e899dSKrzysztof Grobelny             return false;
548479e899dSKrzysztof Grobelny         }
549479e899dSKrzysztof Grobelny         args.reportUpdates = dbusReportUpdates;
550479e899dSKrzysztof Grobelny     }
551479e899dSKrzysztof Grobelny 
552479e899dSKrzysztof Grobelny     if (appendLimit)
553479e899dSKrzysztof Grobelny     {
554479e899dSKrzysztof Grobelny         args.appendLimit = *appendLimit;
555479e899dSKrzysztof Grobelny     }
556479e899dSKrzysztof Grobelny 
557479e899dSKrzysztof Grobelny     if (metricReportDefinitionEnabled)
558479e899dSKrzysztof Grobelny     {
559479e899dSKrzysztof Grobelny         args.metricReportDefinitionEnabled = *metricReportDefinitionEnabled;
560479e899dSKrzysztof Grobelny     }
561479e899dSKrzysztof Grobelny 
562479e899dSKrzysztof Grobelny     if (reportActionsStr)
563479e899dSKrzysztof Grobelny     {
564479e899dSKrzysztof Grobelny         if (!toDbusReportActions(res, *reportActionsStr, args))
5654dbb8aeaSWludzik, Jozef         {
5664dbb8aeaSWludzik, Jozef             return false;
5674dbb8aeaSWludzik, Jozef         }
568479e899dSKrzysztof Grobelny     }
5694dbb8aeaSWludzik, Jozef 
570479e899dSKrzysztof Grobelny     if (reportingTypeStr == "Periodic")
5714dbb8aeaSWludzik, Jozef     {
5724dbb8aeaSWludzik, Jozef         if (!schedule)
5734dbb8aeaSWludzik, Jozef         {
5744dbb8aeaSWludzik, Jozef             messages::createFailedMissingReqProperties(res, "Schedule");
5754dbb8aeaSWludzik, Jozef             return false;
5764dbb8aeaSWludzik, Jozef         }
5774dbb8aeaSWludzik, Jozef 
5784dbb8aeaSWludzik, Jozef         std::string durationStr;
5794dbb8aeaSWludzik, Jozef         if (!json_util::readJson(*schedule, res, "RecurrenceInterval",
5804dbb8aeaSWludzik, Jozef                                  durationStr))
5814dbb8aeaSWludzik, Jozef         {
5824dbb8aeaSWludzik, Jozef             return false;
5834dbb8aeaSWludzik, Jozef         }
5844dbb8aeaSWludzik, Jozef 
5854dbb8aeaSWludzik, Jozef         std::optional<std::chrono::milliseconds> durationNum =
5864dbb8aeaSWludzik, Jozef             time_utils::fromDurationString(durationStr);
587479e899dSKrzysztof Grobelny         if (!durationNum || durationNum->count() < 0)
5884dbb8aeaSWludzik, Jozef         {
5894dbb8aeaSWludzik, Jozef             messages::propertyValueIncorrect(res, "RecurrenceInterval",
5904dbb8aeaSWludzik, Jozef                                              durationStr);
5914dbb8aeaSWludzik, Jozef             return false;
5924dbb8aeaSWludzik, Jozef         }
5934dbb8aeaSWludzik, Jozef         args.interval = static_cast<uint64_t>(durationNum->count());
5944dbb8aeaSWludzik, Jozef     }
5954dbb8aeaSWludzik, Jozef 
596479e899dSKrzysztof Grobelny     if (metrics)
5974dbb8aeaSWludzik, Jozef     {
598479e899dSKrzysztof Grobelny         if (!getUserMetrics(res, *metrics, args.metrics))
5994dbb8aeaSWludzik, Jozef         {
6004dbb8aeaSWludzik, Jozef             return false;
6014dbb8aeaSWludzik, Jozef         }
6024dbb8aeaSWludzik, Jozef     }
6034dbb8aeaSWludzik, Jozef 
6044dbb8aeaSWludzik, Jozef     return true;
6054dbb8aeaSWludzik, Jozef }
6064dbb8aeaSWludzik, Jozef 
607ca1600c1SSzymon Dompke inline bool getChassisSensorNodeFromMetrics(
6088d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
609479e899dSKrzysztof Grobelny     std::span<const AddReportArgs::MetricArgs> metrics,
6104dbb8aeaSWludzik, Jozef     boost::container::flat_set<std::pair<std::string, std::string>>& matched)
6114dbb8aeaSWludzik, Jozef {
612ca1600c1SSzymon Dompke     for (const auto& metric : metrics)
6134dbb8aeaSWludzik, Jozef     {
614479e899dSKrzysztof Grobelny         std::optional<IncorrectMetricUri> error =
615479e899dSKrzysztof Grobelny             getChassisSensorNode(metric.uris, matched);
616ca1600c1SSzymon Dompke         if (error)
6174dbb8aeaSWludzik, Jozef         {
618ca1600c1SSzymon Dompke             messages::propertyValueIncorrect(asyncResp->res, error->uri,
6194dbb8aeaSWludzik, Jozef                                              "MetricProperties/" +
620ca1600c1SSzymon Dompke                                                  std::to_string(error->index));
6214dbb8aeaSWludzik, Jozef             return false;
6224dbb8aeaSWludzik, Jozef         }
6234dbb8aeaSWludzik, Jozef     }
6244dbb8aeaSWludzik, Jozef     return true;
6254dbb8aeaSWludzik, Jozef }
6264dbb8aeaSWludzik, Jozef 
6274dbb8aeaSWludzik, Jozef class AddReport
6284dbb8aeaSWludzik, Jozef {
6294dbb8aeaSWludzik, Jozef   public:
6308d1b46d7Szhanghch05     AddReport(AddReportArgs argsIn,
6318a592810SEd Tanous               const std::shared_ptr<bmcweb::AsyncResp>& asyncRespIn) :
6328a592810SEd Tanous         asyncResp(asyncRespIn),
6338d1b46d7Szhanghch05         args{std::move(argsIn)}
6344dbb8aeaSWludzik, Jozef     {}
635479e899dSKrzysztof Grobelny 
6364dbb8aeaSWludzik, Jozef     ~AddReport()
6374dbb8aeaSWludzik, Jozef     {
638479e899dSKrzysztof Grobelny         boost::asio::post(crow::connections::systemBus->get_io_context(),
639479e899dSKrzysztof Grobelny                           std::bind_front(&performAddReport, asyncResp, args,
640479e899dSKrzysztof Grobelny                                           std::move(uriToDbus)));
641479e899dSKrzysztof Grobelny     }
642479e899dSKrzysztof Grobelny 
643479e899dSKrzysztof Grobelny     static void performAddReport(
644479e899dSKrzysztof Grobelny         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
645479e899dSKrzysztof Grobelny         const AddReportArgs& args,
646479e899dSKrzysztof Grobelny         const boost::container::flat_map<std::string, std::string>& uriToDbus)
647479e899dSKrzysztof Grobelny     {
6484dbb8aeaSWludzik, Jozef         if (asyncResp->res.result() != boost::beast::http::status::ok)
6494dbb8aeaSWludzik, Jozef         {
6504dbb8aeaSWludzik, Jozef             return;
6514dbb8aeaSWludzik, Jozef         }
6524dbb8aeaSWludzik, Jozef 
6534dbb8aeaSWludzik, Jozef         telemetry::ReadingParameters readingParams;
6544dbb8aeaSWludzik, Jozef         readingParams.reserve(args.metrics.size());
6554dbb8aeaSWludzik, Jozef 
656479e899dSKrzysztof Grobelny         for (const auto& metric : args.metrics)
6574dbb8aeaSWludzik, Jozef         {
658479e899dSKrzysztof Grobelny             std::vector<
659479e899dSKrzysztof Grobelny                 std::tuple<sdbusplus::message::object_path, std::string>>
660479e899dSKrzysztof Grobelny                 sensorParams;
661479e899dSKrzysztof Grobelny             sensorParams.reserve(metric.uris.size());
662479e899dSKrzysztof Grobelny 
663479e899dSKrzysztof Grobelny             for (size_t i = 0; i < metric.uris.size(); i++)
6644dbb8aeaSWludzik, Jozef             {
665479e899dSKrzysztof Grobelny                 const std::string& uri = metric.uris[i];
6664dbb8aeaSWludzik, Jozef                 auto el = uriToDbus.find(uri);
6674dbb8aeaSWludzik, Jozef                 if (el == uriToDbus.end())
6684dbb8aeaSWludzik, Jozef                 {
6690fda0f12SGeorge Liu                     BMCWEB_LOG_ERROR
6700fda0f12SGeorge Liu                         << "Failed to find DBus sensor corresponding to URI "
6714dbb8aeaSWludzik, Jozef                         << uri;
6724dbb8aeaSWludzik, Jozef                     messages::propertyValueNotInList(asyncResp->res, uri,
6734dbb8aeaSWludzik, Jozef                                                      "MetricProperties/" +
6744dbb8aeaSWludzik, Jozef                                                          std::to_string(i));
6754dbb8aeaSWludzik, Jozef                     return;
6764dbb8aeaSWludzik, Jozef                 }
6774dbb8aeaSWludzik, Jozef 
6784dbb8aeaSWludzik, Jozef                 const std::string& dbusPath = el->second;
679479e899dSKrzysztof Grobelny                 sensorParams.emplace_back(dbusPath, uri);
6804dbb8aeaSWludzik, Jozef             }
681479e899dSKrzysztof Grobelny 
682479e899dSKrzysztof Grobelny             readingParams.emplace_back(
683479e899dSKrzysztof Grobelny                 std::move(sensorParams), metric.collectionFunction,
684479e899dSKrzysztof Grobelny                 metric.collectionTimeScope, metric.collectionDuration);
6854dbb8aeaSWludzik, Jozef         }
686479e899dSKrzysztof Grobelny 
6874dbb8aeaSWludzik, Jozef         crow::connections::systemBus->async_method_call(
688479e899dSKrzysztof Grobelny             [asyncResp, id = args.id, uriToDbus](
6895e7e2dc5SEd Tanous                 const boost::system::error_code& ec, const std::string&) {
6904dbb8aeaSWludzik, Jozef             if (ec == boost::system::errc::file_exists)
6914dbb8aeaSWludzik, Jozef             {
6924dbb8aeaSWludzik, Jozef                 messages::resourceAlreadyExists(
693479e899dSKrzysztof Grobelny                     asyncResp->res, "MetricReportDefinition", "Id", id);
6944dbb8aeaSWludzik, Jozef                 return;
6954dbb8aeaSWludzik, Jozef             }
6964dbb8aeaSWludzik, Jozef             if (ec == boost::system::errc::too_many_files_open)
6974dbb8aeaSWludzik, Jozef             {
698479e899dSKrzysztof Grobelny                 messages::createLimitReachedForResource(asyncResp->res);
6994dbb8aeaSWludzik, Jozef                 return;
7004dbb8aeaSWludzik, Jozef             }
7014dbb8aeaSWludzik, Jozef             if (ec == boost::system::errc::argument_list_too_long)
7024dbb8aeaSWludzik, Jozef             {
7034dbb8aeaSWludzik, Jozef                 nlohmann::json metricProperties = nlohmann::json::array();
7044dbb8aeaSWludzik, Jozef                 for (const auto& [uri, _] : uriToDbus)
7054dbb8aeaSWludzik, Jozef                 {
7064dbb8aeaSWludzik, Jozef                     metricProperties.emplace_back(uri);
7074dbb8aeaSWludzik, Jozef                 }
708479e899dSKrzysztof Grobelny                 messages::propertyValueIncorrect(asyncResp->res,
709479e899dSKrzysztof Grobelny                                                  metricProperties.dump(),
710479e899dSKrzysztof Grobelny                                                  "MetricProperties");
7114dbb8aeaSWludzik, Jozef                 return;
7124dbb8aeaSWludzik, Jozef             }
7134dbb8aeaSWludzik, Jozef             if (ec)
7144dbb8aeaSWludzik, Jozef             {
715479e899dSKrzysztof Grobelny                 messages::internalError(asyncResp->res);
7164dbb8aeaSWludzik, Jozef                 BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
7174dbb8aeaSWludzik, Jozef                 return;
7184dbb8aeaSWludzik, Jozef             }
7194dbb8aeaSWludzik, Jozef 
720479e899dSKrzysztof Grobelny             messages::created(asyncResp->res);
7214dbb8aeaSWludzik, Jozef             },
7224dbb8aeaSWludzik, Jozef             telemetry::service, "/xyz/openbmc_project/Telemetry/Reports",
7234dbb8aeaSWludzik, Jozef             "xyz.openbmc_project.Telemetry.ReportManager", "AddReport",
724479e899dSKrzysztof Grobelny             "TelemetryService/" + args.id, args.name, args.reportingType,
725479e899dSKrzysztof Grobelny             args.reportUpdates, args.appendLimit, args.reportActions,
726479e899dSKrzysztof Grobelny             args.interval, readingParams, args.metricReportDefinitionEnabled);
7274dbb8aeaSWludzik, Jozef     }
7284dbb8aeaSWludzik, Jozef 
729ecd6a3a2SEd Tanous     AddReport(const AddReport&) = delete;
730ecd6a3a2SEd Tanous     AddReport(AddReport&&) = delete;
731ecd6a3a2SEd Tanous     AddReport& operator=(const AddReport&) = delete;
732ecd6a3a2SEd Tanous     AddReport& operator=(AddReport&&) = delete;
733ecd6a3a2SEd Tanous 
734fe04d49cSNan Zhou     void insert(const std::map<std::string, std::string>& el)
7354dbb8aeaSWludzik, Jozef     {
7364dbb8aeaSWludzik, Jozef         uriToDbus.insert(el.begin(), el.end());
7374dbb8aeaSWludzik, Jozef     }
7384dbb8aeaSWludzik, Jozef 
7394dbb8aeaSWludzik, Jozef   private:
740479e899dSKrzysztof Grobelny     std::shared_ptr<bmcweb::AsyncResp> asyncResp;
7414dbb8aeaSWludzik, Jozef     AddReportArgs args;
7424dbb8aeaSWludzik, Jozef     boost::container::flat_map<std::string, std::string> uriToDbus{};
7434dbb8aeaSWludzik, Jozef };
744081ebf06SWludzik, Jozef } // namespace telemetry
745081ebf06SWludzik, Jozef 
746*dd1c4a9cSSzymon Dompke inline void handleMetricReportDelete(
747*dd1c4a9cSSzymon Dompke     App& app, const crow::Request& req,
748*dd1c4a9cSSzymon Dompke     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id)
749*dd1c4a9cSSzymon Dompke 
750*dd1c4a9cSSzymon Dompke {
751*dd1c4a9cSSzymon Dompke     if (!redfish::setUpRedfishRoute(app, req, asyncResp))
752*dd1c4a9cSSzymon Dompke     {
753*dd1c4a9cSSzymon Dompke         return;
754*dd1c4a9cSSzymon Dompke     }
755*dd1c4a9cSSzymon Dompke 
756*dd1c4a9cSSzymon Dompke     const std::string reportPath = telemetry::getDbusReportPath(id);
757*dd1c4a9cSSzymon Dompke 
758*dd1c4a9cSSzymon Dompke     crow::connections::systemBus->async_method_call(
759*dd1c4a9cSSzymon Dompke         [asyncResp, id](const boost::system::error_code& ec) {
760*dd1c4a9cSSzymon Dompke         /*
761*dd1c4a9cSSzymon Dompke          * boost::system::errc and std::errc are missing value
762*dd1c4a9cSSzymon Dompke          * for EBADR error that is defined in Linux.
763*dd1c4a9cSSzymon Dompke          */
764*dd1c4a9cSSzymon Dompke         if (ec.value() == EBADR)
765*dd1c4a9cSSzymon Dompke         {
766*dd1c4a9cSSzymon Dompke             messages::resourceNotFound(asyncResp->res, "MetricReportDefinition",
767*dd1c4a9cSSzymon Dompke                                        id);
768*dd1c4a9cSSzymon Dompke             return;
769*dd1c4a9cSSzymon Dompke         }
770*dd1c4a9cSSzymon Dompke 
771*dd1c4a9cSSzymon Dompke         if (ec)
772*dd1c4a9cSSzymon Dompke         {
773*dd1c4a9cSSzymon Dompke             BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
774*dd1c4a9cSSzymon Dompke             messages::internalError(asyncResp->res);
775*dd1c4a9cSSzymon Dompke             return;
776*dd1c4a9cSSzymon Dompke         }
777*dd1c4a9cSSzymon Dompke 
778*dd1c4a9cSSzymon Dompke         asyncResp->res.result(boost::beast::http::status::no_content);
779*dd1c4a9cSSzymon Dompke         },
780*dd1c4a9cSSzymon Dompke         telemetry::service, reportPath, "xyz.openbmc_project.Object.Delete",
781*dd1c4a9cSSzymon Dompke         "Delete");
782*dd1c4a9cSSzymon Dompke }
783*dd1c4a9cSSzymon Dompke 
7847e860f15SJohn Edward Broadbent inline void requestRoutesMetricReportDefinitionCollection(App& app)
785081ebf06SWludzik, Jozef {
7867e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/")
787ed398213SEd Tanous         .privileges(redfish::privileges::getMetricReportDefinitionCollection)
7887e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
78945ca1b86SEd Tanous             [&app](const crow::Request& req,
7907e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
7913ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
79245ca1b86SEd Tanous         {
79345ca1b86SEd Tanous             return;
79445ca1b86SEd Tanous         }
79545ca1b86SEd Tanous 
7968d1b46d7Szhanghch05         asyncResp->res.jsonValue["@odata.type"] =
7978d1b46d7Szhanghch05             "#MetricReportDefinitionCollection."
798081ebf06SWludzik, Jozef             "MetricReportDefinitionCollection";
7998d1b46d7Szhanghch05         asyncResp->res.jsonValue["@odata.id"] =
800ae9031f0SWilly Tu             "/redfish/v1/TelemetryService/MetricReportDefinitions";
801002d39b4SEd Tanous         asyncResp->res.jsonValue["Name"] = "Metric Definition Collection";
8027a1dbc48SGeorge Liu         constexpr std::array<std::string_view, 1> interfaces{
8037a1dbc48SGeorge Liu             telemetry::reportInterface};
8044028ff77SEd Tanous         collection_util::getCollectionMembers(
805ae9031f0SWilly Tu             asyncResp,
806ae9031f0SWilly Tu             boost::urls::url(
807ae9031f0SWilly Tu                 "/redfish/v1/TelemetryService/MetricReportDefinitions"),
808ae9031f0SWilly Tu             interfaces,
8094028ff77SEd Tanous             "/xyz/openbmc_project/Telemetry/Reports/TelemetryService");
8107e860f15SJohn Edward Broadbent         });
8114dbb8aeaSWludzik, Jozef 
8127e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/")
813ed398213SEd Tanous         .privileges(redfish::privileges::postMetricReportDefinitionCollection)
814002d39b4SEd Tanous         .methods(boost::beast::http::verb::post)(
815002d39b4SEd Tanous             [&app](const crow::Request& req,
8167e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
8173ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
81845ca1b86SEd Tanous         {
81945ca1b86SEd Tanous             return;
82045ca1b86SEd Tanous         }
82145ca1b86SEd Tanous 
8224dbb8aeaSWludzik, Jozef         telemetry::AddReportArgs args;
8238d1b46d7Szhanghch05         if (!telemetry::getUserParameters(asyncResp->res, req, args))
8244dbb8aeaSWludzik, Jozef         {
8254dbb8aeaSWludzik, Jozef             return;
8264dbb8aeaSWludzik, Jozef         }
8274dbb8aeaSWludzik, Jozef 
8284dbb8aeaSWludzik, Jozef         boost::container::flat_set<std::pair<std::string, std::string>>
8294dbb8aeaSWludzik, Jozef             chassisSensors;
830002d39b4SEd Tanous         if (!telemetry::getChassisSensorNodeFromMetrics(asyncResp, args.metrics,
831002d39b4SEd Tanous                                                         chassisSensors))
8324dbb8aeaSWludzik, Jozef         {
8334dbb8aeaSWludzik, Jozef             return;
8344dbb8aeaSWludzik, Jozef         }
8354dbb8aeaSWludzik, Jozef 
836002d39b4SEd Tanous         auto addReportReq =
837002d39b4SEd Tanous             std::make_shared<telemetry::AddReport>(std::move(args), asyncResp);
8384dbb8aeaSWludzik, Jozef         for (const auto& [chassis, sensorType] : chassisSensors)
8394dbb8aeaSWludzik, Jozef         {
8404dbb8aeaSWludzik, Jozef             retrieveUriToDbusMap(
841021d32cfSKrzysztof Grobelny                 chassis, sensorType,
842002d39b4SEd Tanous                 [asyncResp, addReportReq](
843002d39b4SEd Tanous                     const boost::beast::http::status status,
844fe04d49cSNan Zhou                     const std::map<std::string, std::string>& uriToDbus) {
8454dbb8aeaSWludzik, Jozef                 if (status != boost::beast::http::status::ok)
8464dbb8aeaSWludzik, Jozef                 {
8477e860f15SJohn Edward Broadbent                     BMCWEB_LOG_ERROR
8480fda0f12SGeorge Liu                         << "Failed to retrieve URI to dbus sensors map with err "
8494dbb8aeaSWludzik, Jozef                         << static_cast<unsigned>(status);
8504dbb8aeaSWludzik, Jozef                     return;
8514dbb8aeaSWludzik, Jozef                 }
8524dbb8aeaSWludzik, Jozef                 addReportReq->insert(uriToDbus);
8534dbb8aeaSWludzik, Jozef                 });
8544dbb8aeaSWludzik, Jozef         }
8557e860f15SJohn Edward Broadbent         });
856081ebf06SWludzik, Jozef }
857081ebf06SWludzik, Jozef 
8587e860f15SJohn Edward Broadbent inline void requestRoutesMetricReportDefinition(App& app)
859081ebf06SWludzik, Jozef {
8607e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
8617e860f15SJohn Edward Broadbent                  "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/")
862ed398213SEd Tanous         .privileges(redfish::privileges::getMetricReportDefinition)
8637e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
86445ca1b86SEd Tanous             [&app](const crow::Request& req,
8657e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
8667e860f15SJohn Edward Broadbent                    const std::string& id) {
8673ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
86845ca1b86SEd Tanous         {
86945ca1b86SEd Tanous             return;
87045ca1b86SEd Tanous         }
87145ca1b86SEd Tanous 
87289474494SKrzysztof Grobelny         sdbusplus::asio::getAllProperties(
87389474494SKrzysztof Grobelny             *crow::connections::systemBus, telemetry::service,
87489474494SKrzysztof Grobelny             telemetry::getDbusReportPath(id), telemetry::reportInterface,
875168e20c1SEd Tanous             [asyncResp,
8765e7e2dc5SEd Tanous              id](const boost::system::error_code& ec,
877479e899dSKrzysztof Grobelny                  const dbus::utility::DBusPropertiesMap& properties) {
878081ebf06SWludzik, Jozef             if (ec.value() == EBADR ||
879081ebf06SWludzik, Jozef                 ec == boost::system::errc::host_unreachable)
880081ebf06SWludzik, Jozef             {
881002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res,
882002d39b4SEd Tanous                                            "MetricReportDefinition", id);
883081ebf06SWludzik, Jozef                 return;
884081ebf06SWludzik, Jozef             }
885081ebf06SWludzik, Jozef             if (ec)
886081ebf06SWludzik, Jozef             {
887081ebf06SWludzik, Jozef                 BMCWEB_LOG_ERROR << "respHandler DBus error " << ec;
888081ebf06SWludzik, Jozef                 messages::internalError(asyncResp->res);
889081ebf06SWludzik, Jozef                 return;
890081ebf06SWludzik, Jozef             }
891081ebf06SWludzik, Jozef 
892479e899dSKrzysztof Grobelny             telemetry::fillReportDefinition(asyncResp, id, properties);
89389474494SKrzysztof Grobelny             });
8947e860f15SJohn Edward Broadbent         });
895479e899dSKrzysztof Grobelny 
8967e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
8977e860f15SJohn Edward Broadbent                  "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/")
898ed398213SEd Tanous         .privileges(redfish::privileges::deleteMetricReportDefinitionCollection)
8997e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::delete_)(
900*dd1c4a9cSSzymon Dompke             std::bind_front(handleMetricReportDelete, std::ref(app)));
9014dbb8aeaSWludzik, Jozef }
902081ebf06SWludzik, Jozef } // namespace redfish
903