| #pragma once |
| |
| #include "app.hpp" |
| #include "async_resp.hpp" |
| #include "grpc_statistics.h" |
| #include "http_request.hpp" |
| #include "privileges.hpp" |
| #include "query.hpp" |
| #include "registries/privilege_registry.hpp" |
| #include "routing.hpp" |
| |
| #include <nlohmann/json.hpp> |
| #include <sdbusplus/asio/property.hpp> |
| |
| #include <string> |
| |
| namespace redfish |
| { |
| |
| inline void |
| afterGetManagerStartTime(const std::shared_ptr<bmcweb::AsyncResp>& aResp, |
| const boost::system::error_code& ec, |
| uint64_t bmcwebResetTime) |
| { |
| if (ec) |
| { |
| // Not all servers will be running in systemd, so ignore the error. |
| return; |
| } |
| using std::chrono::steady_clock; |
| |
| std::chrono::duration<steady_clock::rep, std::micro> usReset{ |
| bmcwebResetTime}; |
| steady_clock::time_point resetTime{usReset}; |
| |
| steady_clock::time_point now = steady_clock::now(); |
| |
| steady_clock::duration runTime = now - resetTime; |
| |
| if (runTime < steady_clock::duration::zero()) |
| { |
| BMCWEB_LOG_CRITICAL << "Uptime was negative????"; |
| messages::internalError(aResp->res); |
| return; |
| } |
| |
| // Floor to the closest millisecond |
| using Milli = std::chrono::duration<steady_clock::rep, std::milli>; |
| Milli milli = std::chrono::floor<Milli>(runTime); |
| |
| using SecondsFloat = std::chrono::duration<double>; |
| SecondsFloat sec = std::chrono::duration_cast<SecondsFloat>(milli); |
| |
| aResp->res.jsonValue["ServiceRootUptimeSeconds"] = sec.count(); |
| } |
| |
| inline void |
| managerGetServiceRootUptime(const std::shared_ptr<bmcweb::AsyncResp>& aResp) |
| { |
| sdbusplus::asio::getProperty<uint64_t>( |
| *crow::connections::systemBus, "org.freedesktop.systemd1", |
| "/org/freedesktop/systemd1/unit/bmcweb_2eservice", |
| "org.freedesktop.systemd1.Unit", "ActiveEnterTimestampMonotonic", |
| std::bind_front(afterGetManagerStartTime, aResp)); |
| } |
| /** |
| * handleManagerDiagnosticData supports ManagerDiagnosticData. |
| * It retrieves BMC health information from various DBus resources and returns |
| * the information through the response. |
| */ |
| inline void handleManagerDiagnosticDataGet( |
| crow::App& app, const crow::Request& req, |
| const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) |
| { |
| if (!redfish::setUpRedfishRoute(app, req, asyncResp)) |
| { |
| return; |
| } |
| asyncResp->res.jsonValue["@odata.type"] = |
| "#ManagerDiagnosticData.v1_2_0.ManagerDiagnosticData"; |
| asyncResp->res.jsonValue["@odata.id"] = |
| "/redfish/v1/Managers/bmc/ManagerDiagnosticData"; |
| asyncResp->res.jsonValue["Id"] = "ManagerDiagnosticData"; |
| asyncResp->res.jsonValue["Name"] = "Manager Diagnostic Data"; |
| |
| #ifdef BMCWEB_ENABLE_REDFISH_OEM_GRPC_STATS |
| asyncResp->res.jsonValue["Oem"]["Google"]["@odata.type"] = |
| "#GoogleManagerDiagnosticData.v1_0_0.GoogleManagerDiagnosticData"; |
| asyncResp->res.jsonValue["Oem"]["Google"]["gRPCStatistics"]["@odata.id"] = |
| "/redfish/v1/Managers/bmc/ManagerDiagnosticData/Oem/Google/" |
| "GooglegRPCStatistics"; |
| #endif |
| managerGetServiceRootUptime(asyncResp); |
| } |
| |
| #ifdef BMCWEB_ENABLE_REDFISH_OEM_GRPC_STATS |
| |
| inline void handleManagerDiagnosticDataGooglegRPCStatsHead( |
| crow::App& app, const crow::Request& req, |
| const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) |
| { |
| if (!redfish::setUpRedfishRoute(app, req, asyncResp)) |
| { |
| return; |
| } |
| asyncResp->res.addHeader( |
| boost::beast::http::field::link, |
| "</redfish/v1/JsonSchemas/GoogleManagerDiagnosticData/" |
| "GooglegRPCStatistics.json>; rel=describedby"); |
| } |
| |
| inline void handleManagerDiagnosticDataGooglegRPCStatsGet( |
| crow::App& app, const crow::Request& req, |
| const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) |
| { |
| if (!redfish::setUpRedfishRoute(app, req, asyncResp)) |
| { |
| return; |
| } |
| |
| nlohmann::json& j = asyncResp->res.jsonValue; |
| j["@odata.id"] = |
| "/redfish/v1/Managers/bmc/ManagerDiagnosticData/Oem/Google/" |
| "GooglegRPCStatistics"; |
| j["@odata.type"] = |
| "#GooglegRPCStatistics.v1_0_0.GooglegRPCStatistics"; |
| j["Id"] = "GooglegRPCStatistics"; |
| j["Name"] = "Google gRPC Statistics"; |
| |
| grpc_redfish::gRPCStatisticsShared shared_stats; |
| grpc_redfish::gRPCStatistics stats = shared_stats.GetgRPCStatistics(); |
| |
| j["gRPCInitLatencyMs"] = stats.grpc_init_latency_ms.count(); |
| j["AuthenticationLatencyMs"] = stats.authn_latency_total_ms.count(); |
| j["QueueLatencyMs"] = stats.queue_latency_total_ms.count(); |
| j["RequestLatencyMs"] = stats.request_latency_total_ms.count(); |
| j["AuthorizationLatencyMs"] = stats.authz_latency_total_ms.count(); |
| j["ProcessingLatencyMs"] = stats.processing_latency_total_ms.count(); |
| j["ResponseLatencyMs"] = stats.response_latency_total_ms.count(); |
| |
| j["AuthorizedCount"] = stats.total_authorized_count; |
| j["AuthorizedFailCount"] = stats.total_authorized_fail_count; |
| j["AuthenticatedCount"] = stats.total_authenticated_count; |
| j["AuthenticatedFailCount"] = stats.total_authenticated_fail_count; |
| |
| nlohmann::json::array_t httpMethodCounts; |
| for (auto const& [http, count] : stats.request_count) |
| { |
| nlohmann::json::object_t countObj; |
| countObj["Method"] = static_cast<unsigned>(http); |
| countObj["Count"] = static_cast<unsigned>(count); |
| httpMethodCounts.emplace_back(std::move(countObj)); |
| } |
| nlohmann::json::array_t httpResponseCounts; |
| for (auto const& [response, count] : stats.http_response_count) |
| { |
| nlohmann::json::object_t countObj; |
| countObj["StatusCode"] = static_cast<unsigned>(response); |
| countObj["Count"] = static_cast<unsigned>(count); |
| httpResponseCounts.emplace_back(std::move(countObj)); |
| } |
| nlohmann::json::array_t gRPCStatusCounts; |
| for (auto const& [status, count] : stats.grpc_response_count) |
| { |
| nlohmann::json::object_t countObj; |
| countObj["StatusCode"] = static_cast<unsigned>(status); |
| countObj["Count"] = static_cast<unsigned>(count); |
| gRPCStatusCounts.emplace_back(std::move(countObj)); |
| } |
| j["HTTPMethods"] = std::move(httpMethodCounts); |
| j["HTTPResponseCodes"] = std::move(httpResponseCounts); |
| j["gRPCResponseCodes"] = std::move(gRPCStatusCounts); |
| } |
| #endif |
| |
| inline void requestRoutesManagerDiagnosticData(App& app) |
| { |
| BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/ManagerDiagnosticData") |
| .privileges(redfish::privileges::getManagerDiagnosticData) |
| .methods(boost::beast::http::verb::get)( |
| std::bind_front(handleManagerDiagnosticDataGet, std::ref(app))); |
| |
| #ifdef BMCWEB_ENABLE_REDFISH_OEM_GRPC_STATS |
| BMCWEB_ROUTE( |
| app, |
| "/redfish/v1/Managers/bmc/ManagerDiagnosticData/Oem/Google/" |
| "GooglegRPCStatistics") |
| .privileges(redfish::privileges::headManagerDiagnosticData) |
| .methods(boost::beast::http::verb::head)(std::bind_front( |
| handleManagerDiagnosticDataGooglegRPCStatsHead, std::ref(app))); |
| |
| BMCWEB_ROUTE( |
| app, |
| "/redfish/v1/Managers/bmc/ManagerDiagnosticData/Oem/Google/" |
| "GooglegRPCStatistics") |
| .privileges(redfish::privileges::getManagerDiagnosticData) |
| .methods(boost::beast::http::verb::get)(std::bind_front( |
| handleManagerDiagnosticDataGooglegRPCStatsGet, std::ref(app))); |
| #endif |
| } |
| |
| } // namespace redfish |