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<bmcweb::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(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 79 const crow::Request&, const std::vector<std::string>&) override 80 { 81 asyncResp->res.jsonValue["@odata.type"] = 82 "#MetricReportCollection.MetricReportCollection"; 83 asyncResp->res.jsonValue["@odata.id"] = 84 "/redfish/v1/TelemetryService/MetricReports"; 85 asyncResp->res.jsonValue["Name"] = "Metric Report Collection"; 86 87 telemetry::getReportCollection(asyncResp, telemetry::metricReportUri); 88 } 89 }; 90 91 class MetricReport : public Node 92 { 93 public: 94 MetricReport(App& app) : 95 Node(app, "/redfish/v1/TelemetryService/MetricReports/<str>/", 96 std::string()) 97 { 98 entityPrivileges = { 99 {boost::beast::http::verb::get, {{"Login"}}}, 100 {boost::beast::http::verb::head, {{"Login"}}}, 101 {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 102 {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 103 {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 104 {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 105 } 106 107 private: 108 void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 109 const crow::Request&, 110 const std::vector<std::string>& params) override 111 { 112 113 if (params.size() != 1) 114 { 115 messages::internalError(asyncResp->res); 116 return; 117 } 118 119 const std::string& id = params[0]; 120 const std::string reportPath = telemetry::getDbusReportPath(id); 121 crow::connections::systemBus->async_method_call( 122 [asyncResp, id, reportPath](const boost::system::error_code& ec) { 123 if (ec.value() == EBADR || 124 ec == boost::system::errc::host_unreachable) 125 { 126 messages::resourceNotFound(asyncResp->res, "MetricReport", 127 id); 128 return; 129 } 130 if (ec) 131 { 132 BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; 133 messages::internalError(asyncResp->res); 134 return; 135 } 136 137 crow::connections::systemBus->async_method_call( 138 [asyncResp, id]( 139 const boost::system::error_code ec, 140 const std::variant<telemetry::TimestampReadings>& ret) { 141 if (ec) 142 { 143 BMCWEB_LOG_ERROR << "respHandler DBus error " << ec; 144 messages::internalError(asyncResp->res); 145 return; 146 } 147 148 telemetry::fillReport(asyncResp, id, ret); 149 }, 150 telemetry::service, reportPath, 151 "org.freedesktop.DBus.Properties", "Get", 152 telemetry::reportInterface, "Readings"); 153 }, 154 telemetry::service, reportPath, telemetry::reportInterface, 155 "Update"); 156 } 157 }; 158 } // namespace redfish 159