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