#pragma once #include #include #include #include #include #include #include class Access_Logger { public: static void log(const drogon::HttpRequestPtr &request, const drogon::HttpResponsePtr &response, const double elapsed_ms) { std::cout << "[http access] method=" << request->methodString() << ", path=" << request->path() << ", status=" << static_cast(response->statusCode()) << ", cost_ms=" << elapsed_ms << std::endl; } }; class Slow_Request_Monitor { public: static void log_if_slow(const drogon::HttpRequestPtr &request, const drogon::HttpResponsePtr &response, const double elapsed_ms, const std::size_t threshold_ms) { if (elapsed_ms < static_cast(threshold_ms)) return; std::cout << "[slow http request] method=" << request->methodString() << ", path=" << request->path() << ", status=" << static_cast(response->statusCode()) << ", cost_ms=" << elapsed_ms << ", threshold_ms=" << threshold_ms << std::endl; } }; class Scope_Timer { public: Scope_Timer(std::string_view name, const std::size_t threshold_ms) : name_(std::move(name)), threshold_ms_(threshold_ms), start_(std::chrono::steady_clock::now()) {} ~Scope_Timer() { const auto elapsed_ms = std::chrono::duration( std::chrono::steady_clock::now() - start_) .count(); if (elapsed_ms < static_cast(threshold_ms_)) return; std::cout << "[slow scope] name=" << name_ << ", cost_ms=" << elapsed_ms << ", threshold_ms=" << threshold_ms_ << std::endl; } private: std::string name_; std::size_t threshold_ms_; std::chrono::steady_clock::time_point start_; }; inline constexpr const char *kHttpRequestStart = "ecap.http_request_start"; inline void register_http_performance_monitor(const bool access_log, const std::size_t slow_request_threshold_ms) { drogon::app().registerSyncAdvice( [](const drogon::HttpRequestPtr &request) -> drogon::HttpResponsePtr { request->attributes()->insert(kHttpRequestStart, std::chrono::steady_clock::now()); return {}; }); drogon::app().registerPreSendingAdvice( [access_log, slow_request_threshold_ms](const drogon::HttpRequestPtr &request, const drogon::HttpResponsePtr &response) { const auto &start = request->attributes()->get( kHttpRequestStart); if (start == std::chrono::steady_clock::time_point{}) return; const auto elapsed_ms = std::chrono::duration( std::chrono::steady_clock::now() - start) .count(); if (access_log) Access_Logger::log(request, response, elapsed_ms); Slow_Request_Monitor::log_if_slow(request, response, elapsed_ms, slow_request_threshold_ms); }); }