All files / services requestLogger.ts

0% Statements 0/38
0% Branches 0/1
0% Functions 0/1
0% Lines 0/38

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57                                                                                                                 
import { Context, Next } from 'koa';
import { logService, LogLevel, RequestLog } from './log.service';
 
// 请求日志中间件
export async function requestLogger(ctx: Context, next: Next): Promise<void> {
  const startTime = Date.now();
  const requestId = `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
 
  // 请求开始前记录
  const requestLog: Partial<RequestLog> = {
    requestId,
    method: ctx.method,
    path: ctx.path,
    query: ctx.querystring,
    headers: ctx.headers as Record<string, string>,
    ip: ctx.ip,
    userAgent: ctx.get('user-agent') || '',
  };
 
  try {
    await next();
 
    // 请求完成后记录响应信息
    requestLog.status = ctx.status;
    requestLog.responseTime = Date.now() - startTime;
    requestLog.responseSize = parseInt(ctx.get('Content-Length') || '0', 10);
 
    // 根据状态码确定日志级别
    if (ctx.status >= 500) {
      requestLog.level = LogLevel.ERROR;
      requestLog.error = `Server error: ${ctx.status}`;
    } else if (ctx.status >= 400) {
      requestLog.level = LogLevel.WARN;
      requestLog.error = `Client error: ${ctx.status}`;
    } else {
      requestLog.level = LogLevel.INFO;
    }
 
    logService.logRequest(requestLog as RequestLog);
  } catch (err: unknown) {
    const error = err as Error & { status?: number; code?: number };
 
    // 记录错误请求
    requestLog.status = error.status || 500;
    requestLog.responseTime = Date.now() - startTime;
    requestLog.level = LogLevel.ERROR;
    requestLog.error = error.message;
 
    logService.logRequest(requestLog as RequestLog);
 
    // 重新抛出错误,让 errorHandler 中间件处理
    throw err;
  }
}
 
// 导出日志服务实例,供其他地方使用
export { logService, LogLevel };