1 #pragma once 2 3 #include "node.hpp" 4 #include "utils/telemetry_utils.hpp" 5 #include "utils/time_utils.hpp" 6 7 #include <tuple> 8 #include <variant> 9 10 namespace redfish 11 { 12 13 namespace telemetry 14 { 15 16 using ReadingParameters = 17 std::vector<std::tuple<sdbusplus::message::object_path, std::string, 18 std::string, std::string>>; 19 20 inline void fillReportDefinition( 21 const std::shared_ptr<AsyncResp>& asyncResp, const std::string& id, 22 const std::vector< 23 std::pair<std::string, std::variant<std::string, bool, uint64_t, 24 ReadingParameters>>>& ret) 25 { 26 asyncResp->res.jsonValue["@odata.type"] = 27 "#MetricReportDefinition.v1_3_0.MetricReportDefinition"; 28 asyncResp->res.jsonValue["@odata.id"] = 29 telemetry::metricReportDefinitionUri + id; 30 asyncResp->res.jsonValue["Id"] = id; 31 asyncResp->res.jsonValue["Name"] = id; 32 asyncResp->res.jsonValue["MetricReport"]["@odata.id"] = 33 telemetry::metricReportUri + id; 34 asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; 35 asyncResp->res.jsonValue["ReportUpdates"] = "Overwrite"; 36 37 const bool* emitsReadingsUpdate = nullptr; 38 const bool* logToMetricReportsCollection = nullptr; 39 const ReadingParameters* readingParams = nullptr; 40 const std::string* reportingType = nullptr; 41 const uint64_t* interval = nullptr; 42 for (const auto& [key, var] : ret) 43 { 44 if (key == "EmitsReadingsUpdate") 45 { 46 emitsReadingsUpdate = std::get_if<bool>(&var); 47 } 48 else if (key == "LogToMetricReportsCollection") 49 { 50 logToMetricReportsCollection = std::get_if<bool>(&var); 51 } 52 else if (key == "ReadingParameters") 53 { 54 readingParams = std::get_if<ReadingParameters>(&var); 55 } 56 else if (key == "ReportingType") 57 { 58 reportingType = std::get_if<std::string>(&var); 59 } 60 else if (key == "Interval") 61 { 62 interval = std::get_if<uint64_t>(&var); 63 } 64 } 65 if (!emitsReadingsUpdate || !logToMetricReportsCollection || 66 !readingParams || !reportingType || !interval) 67 { 68 BMCWEB_LOG_ERROR << "Property type mismatch or property is missing"; 69 messages::internalError(asyncResp->res); 70 return; 71 } 72 73 std::vector<std::string> redfishReportActions; 74 redfishReportActions.reserve(2); 75 if (*emitsReadingsUpdate) 76 { 77 redfishReportActions.emplace_back("RedfishEvent"); 78 } 79 if (*logToMetricReportsCollection) 80 { 81 redfishReportActions.emplace_back("LogToMetricReportsCollection"); 82 } 83 84 nlohmann::json metrics = nlohmann::json::array(); 85 for (auto& [sensorPath, operationType, id, metadata] : *readingParams) 86 { 87 metrics.push_back({ 88 {"MetricId", id}, 89 {"MetricProperties", {metadata}}, 90 }); 91 } 92 asyncResp->res.jsonValue["Metrics"] = metrics; 93 asyncResp->res.jsonValue["MetricReportDefinitionType"] = *reportingType; 94 asyncResp->res.jsonValue["ReportActions"] = redfishReportActions; 95 asyncResp->res.jsonValue["Schedule"]["RecurrenceInterval"] = 96 time_utils::toDurationString(std::chrono::milliseconds(*interval)); 97 } 98 } // namespace telemetry 99 100 class MetricReportDefinitionCollection : public Node 101 { 102 public: 103 MetricReportDefinitionCollection(App& app) : 104 Node(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/") 105 { 106 entityPrivileges = { 107 {boost::beast::http::verb::get, {{"Login"}}}, 108 {boost::beast::http::verb::head, {{"Login"}}}, 109 {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 110 {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 111 {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 112 {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 113 } 114 115 private: 116 void doGet(crow::Response& res, const crow::Request&, 117 const std::vector<std::string>&) override 118 { 119 res.jsonValue["@odata.type"] = "#MetricReportDefinitionCollection." 120 "MetricReportDefinitionCollection"; 121 res.jsonValue["@odata.id"] = 122 "/redfish/v1/TelemetryService/MetricReportDefinitions"; 123 res.jsonValue["Name"] = "Metric Definition Collection"; 124 125 auto asyncResp = std::make_shared<AsyncResp>(res); 126 telemetry::getReportCollection(asyncResp, 127 telemetry::metricReportDefinitionUri); 128 } 129 }; 130 131 class MetricReportDefinition : public Node 132 { 133 public: 134 MetricReportDefinition(App& app) : 135 Node(app, "/redfish/v1/TelemetryService/MetricReportDefinitions/<str>/", 136 std::string()) 137 { 138 entityPrivileges = { 139 {boost::beast::http::verb::get, {{"Login"}}}, 140 {boost::beast::http::verb::head, {{"Login"}}}, 141 {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 142 {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 143 {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 144 {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 145 } 146 147 private: 148 void doGet(crow::Response& res, const crow::Request&, 149 const std::vector<std::string>& params) override 150 { 151 auto asyncResp = std::make_shared<AsyncResp>(res); 152 153 if (params.size() != 1) 154 { 155 messages::internalError(asyncResp->res); 156 return; 157 } 158 159 const std::string& id = params[0]; 160 crow::connections::systemBus->async_method_call( 161 [asyncResp, 162 id](const boost::system::error_code ec, 163 const std::vector<std::pair< 164 std::string, std::variant<std::string, bool, uint64_t, 165 telemetry::ReadingParameters>>>& 166 ret) { 167 if (ec.value() == EBADR || 168 ec == boost::system::errc::host_unreachable) 169 { 170 messages::resourceNotFound(asyncResp->res, 171 "MetricReportDefinition", id); 172 return; 173 } 174 if (ec) 175 { 176 BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; 177 messages::internalError(asyncResp->res); 178 return; 179 } 180 181 telemetry::fillReportDefinition(asyncResp, id, ret); 182 }, 183 telemetry::service, telemetry::getDbusReportPath(id), 184 "org.freedesktop.DBus.Properties", "GetAll", 185 telemetry::reportInterface); 186 } 187 }; 188 } // namespace redfish 189