xref: /openbmc/bmcweb/redfish-core/include/utils/telemetry_utils.hpp (revision 504af5a0568171b72caf13234cc81380b261fa21)
1 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: Copyright OpenBMC Authors
3 #pragma once
4 
5 #include "generated/enums/metric_report_definition.hpp"
6 #include "http/utility.hpp"
7 #include "logging.hpp"
8 #include "utility.hpp"
9 
10 #include <boost/container/flat_set.hpp>
11 #include <boost/system/result.hpp>
12 #include <boost/url/parse.hpp>
13 #include <boost/url/url_view.hpp>
14 #include <nlohmann/json.hpp>
15 #include <sdbusplus/message/native_types.hpp>
16 
17 #include <cstddef>
18 #include <functional>
19 #include <optional>
20 #include <span>
21 #include <string>
22 #include <string_view>
23 #include <utility>
24 
25 namespace redfish
26 {
27 
28 namespace telemetry
29 {
30 constexpr const char* service = "xyz.openbmc_project.Telemetry";
31 constexpr const char* reportInterface = "xyz.openbmc_project.Telemetry.Report";
32 
getDbusReportPath(std::string_view id)33 inline std::string getDbusReportPath(std::string_view id)
34 {
35     sdbusplus::message::object_path reportsPath(
36         "/xyz/openbmc_project/Telemetry/Reports/TelemetryService");
37     return {reportsPath / id};
38 }
39 
getDbusTriggerPath(std::string_view id)40 inline std::string getDbusTriggerPath(std::string_view id)
41 {
42     sdbusplus::message::object_path triggersPath(
43         "/xyz/openbmc_project/Telemetry/Triggers/TelemetryService");
44     return {triggersPath / id};
45 }
46 
getTriggerIdFromDbusPath(const std::string & dbusPath)47 inline std::optional<std::string> getTriggerIdFromDbusPath(
48     const std::string& dbusPath)
49 {
50     sdbusplus::message::object_path converted(dbusPath);
51 
52     if (converted.parent_path() !=
53         "/xyz/openbmc_project/Telemetry/Triggers/TelemetryService")
54     {
55         return std::nullopt;
56     }
57 
58     const std::string& id = converted.filename();
59     if (id.empty())
60     {
61         return std::nullopt;
62     }
63     return id;
64 }
65 
66 struct IncorrectMetricUri
67 {
68     std::string uri;
69     size_t index;
70 };
71 
getChassisSensorNode(std::span<const std::string> uris,boost::container::flat_set<std::pair<std::string,std::string>> & matched)72 inline std::optional<IncorrectMetricUri> getChassisSensorNode(
73     std::span<const std::string> uris,
74     boost::container::flat_set<std::pair<std::string, std::string>>& matched)
75 {
76     size_t uriIdx = 0;
77     for (const std::string& uri : uris)
78     {
79         boost::system::result<boost::urls::url_view> parsed =
80             boost::urls::parse_relative_ref(uri);
81 
82         if (!parsed)
83         {
84             BMCWEB_LOG_ERROR("Failed to get chassis and sensor Node "
85                              "from {}",
86                              uri);
87             return std::make_optional<IncorrectMetricUri>({uri, uriIdx});
88         }
89 
90         std::string chassis;
91         std::string node;
92 
93         if (crow::utility::readUrlSegments(*parsed, "redfish", "v1", "Chassis",
94                                            std::ref(chassis), std::ref(node)))
95         {
96             matched.emplace(std::move(chassis), std::move(node));
97             uriIdx++;
98             continue;
99         }
100 
101         // Those 2 segments cannot be validated here, as we don't know which
102         // sensors exist at the moment of parsing.
103         std::string ignoredSenorId;
104 
105         if (crow::utility::readUrlSegments(*parsed, "redfish", "v1", "Chassis",
106                                            std::ref(chassis), "Sensors",
107                                            std::ref(ignoredSenorId)))
108         {
109             matched.emplace(std::move(chassis), "Sensors");
110             uriIdx++;
111             continue;
112         }
113 
114         BMCWEB_LOG_ERROR("Failed to get chassis and sensor Node "
115                          "from {}",
116                          uri);
117         return std::make_optional<IncorrectMetricUri>({uri, uriIdx});
118     }
119     return std::nullopt;
120 }
121 
122 inline metric_report_definition::CalculationAlgorithmEnum
toRedfishCollectionFunction(std::string_view dbusValue)123     toRedfishCollectionFunction(std::string_view dbusValue)
124 {
125     if (dbusValue ==
126         "xyz.openbmc_project.Telemetry.Report.OperationType.Maximum")
127     {
128         return metric_report_definition::CalculationAlgorithmEnum::Maximum;
129     }
130     if (dbusValue ==
131         "xyz.openbmc_project.Telemetry.Report.OperationType.Minimum")
132     {
133         return metric_report_definition::CalculationAlgorithmEnum::Minimum;
134     }
135     if (dbusValue ==
136         "xyz.openbmc_project.Telemetry.Report.OperationType.Average")
137     {
138         return metric_report_definition::CalculationAlgorithmEnum::Average;
139     }
140     if (dbusValue ==
141         "xyz.openbmc_project.Telemetry.Report.OperationType.Summation")
142     {
143         return metric_report_definition::CalculationAlgorithmEnum::Summation;
144     }
145     return metric_report_definition::CalculationAlgorithmEnum::Invalid;
146 }
147 
toDbusCollectionFunction(std::string_view redfishValue)148 inline std::string toDbusCollectionFunction(std::string_view redfishValue)
149 {
150     if (redfishValue == "Maximum")
151     {
152         return "xyz.openbmc_project.Telemetry.Report.OperationType.Maximum";
153     }
154     if (redfishValue == "Minimum")
155     {
156         return "xyz.openbmc_project.Telemetry.Report.OperationType.Minimum";
157     }
158     if (redfishValue == "Average")
159     {
160         return "xyz.openbmc_project.Telemetry.Report.OperationType.Average";
161     }
162     if (redfishValue == "Summation")
163     {
164         return "xyz.openbmc_project.Telemetry.Report.OperationType.Summation";
165     }
166     return "";
167 }
168 
toRedfishCollectionFunctions(std::span<const std::string> dbusEnums)169 inline std::optional<nlohmann::json::array_t> toRedfishCollectionFunctions(
170     std::span<const std::string> dbusEnums)
171 {
172     nlohmann::json::array_t redfishEnums;
173     redfishEnums.reserve(dbusEnums.size());
174 
175     for (const auto& dbusValue : dbusEnums)
176     {
177         metric_report_definition::CalculationAlgorithmEnum redfishValue =
178             toRedfishCollectionFunction(dbusValue);
179 
180         if (redfishValue ==
181             metric_report_definition::CalculationAlgorithmEnum::Invalid)
182         {
183             return std::nullopt;
184         }
185 
186         redfishEnums.emplace_back(redfishValue);
187     }
188     return redfishEnums;
189 }
190 
191 } // namespace telemetry
192 } // namespace redfish
193