Files
ECAP_Server/module/Local_Server/server/Performance_Monitor.h
T
2026-06-16 11:18:22 +08:00

86 lines
3.3 KiB
C++

#pragma once
#include <drogon/drogon.h>
#include <chrono>
#include <cstddef>
#include <iostream>
#include <string>
#include <utility>
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<int>(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<double>(threshold_ms)) return;
std::cout << "[slow http request] method=" << request->methodString()
<< ", path=" << request->path()
<< ", status=" << static_cast<int>(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<double, std::milli>(
std::chrono::steady_clock::now() - start_).count();
if (elapsed_ms < static_cast<double>(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<std::chrono::steady_clock::time_point>(
kHttpRequestStart);
if (start == std::chrono::steady_clock::time_point{}) return;
const auto elapsed_ms =
std::chrono::duration<double, std::milli>(
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);
});
}