Files
ECAP_Server/module/Local_Server/server/Performance_Monitor.h
T
2026-06-25 15:44:25 +08:00

90 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);
});
}