#pragma once #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 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); }); }