feat(log): 增强日志系统功能与追踪能力
- 新增模块级别日志控制和采样配置 - 为操作日志添加requestId字段支持全链路追踪 - 优化请求日志中间件,增强结构化记录能力 - 实现日志降级机制,数据库不可用时写入文件 - 添加相关数据库迁移脚本和模型索引
This commit is contained in:
@@ -1,29 +1,53 @@
|
||||
/**
|
||||
* HTTP 请求日志中间件
|
||||
* 为每个请求生成唯一 ID,记录请求/响应信息
|
||||
* 支持:
|
||||
* - 唯一请求ID生成(UUID格式,避免碰撞)
|
||||
* - 全链路请求追踪
|
||||
* - 请求/响应信息结构化记录
|
||||
*/
|
||||
|
||||
const logger = require('../utils/logger');
|
||||
const crypto = require('crypto');
|
||||
|
||||
/**
|
||||
* 生成唯一请求ID
|
||||
* 使用UUID格式确保全局唯一性
|
||||
* @returns {string} 请求ID
|
||||
*/
|
||||
const generateRequestId = () => {
|
||||
if (crypto.randomUUID) {
|
||||
return crypto.randomUUID();
|
||||
}
|
||||
return `${Date.now().toString(36)}-${crypto.randomBytes(16).toString('hex')}`;
|
||||
};
|
||||
|
||||
/**
|
||||
* 请求日志中间件
|
||||
* 记录每个 HTTP 请求的方法、URL、状态码、耗时、用户ID 等信息
|
||||
* 为每个请求生成唯一ID,记录请求/响应信息
|
||||
* 支持全链路追踪:requestId贯穿请求生命周期
|
||||
*/
|
||||
const requestLogger = (req, res, next) => {
|
||||
const requestId = crypto.randomBytes(4).toString('hex');
|
||||
const requestId = generateRequestId();
|
||||
const startTime = Date.now();
|
||||
|
||||
req.requestId = requestId;
|
||||
|
||||
const reqLogger = logger.withRequestId(requestId, 'HTTP');
|
||||
|
||||
reqLogger.debug('请求开始', {
|
||||
method: req.method,
|
||||
url: req.originalUrl,
|
||||
ip: req.ip || req.connection.remoteAddress,
|
||||
userAgent: req.get('User-Agent'),
|
||||
userId: req.user?.userId || null,
|
||||
});
|
||||
|
||||
res.on('finish', () => {
|
||||
const duration = Date.now() - startTime;
|
||||
const level = res.statusCode >= 500 ? 'error'
|
||||
: res.statusCode >= 400 ? 'warn' : 'debug';
|
||||
|
||||
logger[level](`${req.method} ${req.originalUrl}`, {
|
||||
module: 'HTTP',
|
||||
requestId,
|
||||
const logData = {
|
||||
method: req.method,
|
||||
url: req.originalUrl,
|
||||
statusCode: res.statusCode,
|
||||
@@ -31,6 +55,21 @@ const requestLogger = (req, res, next) => {
|
||||
ip: req.ip || req.connection.remoteAddress,
|
||||
userAgent: req.get('User-Agent'),
|
||||
userId: req.user?.userId || null,
|
||||
contentLength: res.get('Content-Length') || 0,
|
||||
};
|
||||
|
||||
if (res.statusCode >= 400) {
|
||||
logData.errorMessage = res.locals.errorMessage || null;
|
||||
logData.errorStack = res.locals.errorStack || null;
|
||||
}
|
||||
|
||||
reqLogger[level](`${req.method} ${req.originalUrl}`, logData);
|
||||
});
|
||||
|
||||
res.on('error', (error) => {
|
||||
reqLogger.error('响应错误', {
|
||||
error: error.message,
|
||||
stack: error.stack,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user