hn-hlw-service/utils/performance-monitor.js
2026-07-27 11:28:33 +08:00

168 lines
4.0 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const logger = require("./logger");
/**
* 性能监控工具
*/
class PerformanceMonitor {
constructor() {
this.requestCount = 0;
this.activeRequests = 0;
this.maxActiveRequests = 0;
this.errorCount = 0;
this.startTime = Date.now();
this.responseTimeHistory = [];
this.errorHistory = [];
}
/**
* 记录请求开始
*/
requestStart(req) {
this.requestCount++;
this.activeRequests++;
if (this.activeRequests > this.maxActiveRequests) {
this.maxActiveRequests = this.activeRequests;
}
// 记录请求开始时间
req.startTime = Date.now();
// 如果并发请求过多,记录警告
if (this.activeRequests > 100) {
logger.warn(`高并发警告: 当前活跃请求数 ${this.activeRequests}`);
}
}
/**
* 记录请求结束
*/
requestEnd(req, res) {
this.activeRequests--;
if (req.startTime) {
const responseTime = Date.now() - req.startTime;
this.responseTimeHistory.push(responseTime);
// 只保留最近1000条记录
if (this.responseTimeHistory.length > 1000) {
this.responseTimeHistory.shift();
}
// 如果响应时间过长,记录警告
if (responseTime > 10000) { // 10秒
logger.warn(`响应时间过长: ${responseTime}ms, URL: ${req.url}`);
}
}
}
/**
* 记录错误
*/
recordError(error, req) {
this.errorCount++;
this.errorHistory.push({
timestamp: Date.now(),
error: error.message,
url: req ? req.url : 'unknown',
method: req ? req.method : 'unknown'
});
// 只保留最近100条错误记录
if (this.errorHistory.length > 100) {
this.errorHistory.shift();
}
}
/**
* 获取性能统计
*/
getStats() {
const uptime = Date.now() - this.startTime;
const avgResponseTime = this.responseTimeHistory.length > 0
? this.responseTimeHistory.reduce((a, b) => a + b, 0) / this.responseTimeHistory.length
: 0;
return {
uptime: Math.floor(uptime / 1000), // 秒
totalRequests: this.requestCount,
activeRequests: this.activeRequests,
maxActiveRequests: this.maxActiveRequests,
errorCount: this.errorCount,
errorRate: this.requestCount > 0 ? (this.errorCount / this.requestCount * 100).toFixed(2) : 0,
avgResponseTime: Math.floor(avgResponseTime),
requestsPerSecond: this.requestCount > 0 ? (this.requestCount / (uptime / 1000)).toFixed(2) : 0,
recentErrors: this.errorHistory.slice(-5) // 最近5个错误
};
}
/**
* 重置统计
*/
reset() {
this.requestCount = 0;
this.activeRequests = 0;
this.maxActiveRequests = 0;
this.errorCount = 0;
this.startTime = Date.now();
this.responseTimeHistory = [];
this.errorHistory = [];
}
/**
* 定期报告性能状态
*/
startPeriodicReport(intervalMs = 60000) { // 默认每分钟报告一次
setInterval(() => {
const stats = this.getStats();
logger.info("性能统计:", stats);
// 如果错误率过高,发出警告
if (stats.errorRate > 5) {
logger.warn(`错误率过高: ${stats.errorRate}%`);
}
// 如果平均响应时间过长,发出警告
if (stats.avgResponseTime > 5000) {
logger.warn(`平均响应时间过长: ${stats.avgResponseTime}ms`);
}
}, intervalMs);
}
}
// 创建全局监控实例
const monitor = new PerformanceMonitor();
/**
* Express中间件监控请求
*/
function monitoringMiddleware(req, res, next) {
monitor.requestStart(req);
// 监听响应结束事件
res.on('finish', () => {
monitor.requestEnd(req, res);
});
// 监听响应关闭事件(客户端断开连接)
res.on('close', () => {
monitor.requestEnd(req, res);
});
next();
}
/**
* 错误监控中间件
*/
function errorMonitoringMiddleware(err, req, res, next) {
monitor.recordError(err, req);
next(err);
}
module.exports = {
PerformanceMonitor,
monitor,
monitoringMiddleware,
errorMonitoringMiddleware
};