/** * 响应时间统计中间件 * 记录请求响应时间并进行日志记录 */ import LoggerProvider from '../../../app/providers/LoggerProvider.js' const logger = LoggerProvider.getLogger('request') // 静态资源扩展名列表 const staticExts = [".css", ".js", ".png", ".jpg", ".jpeg", ".gif", ".ico", ".svg", ".map", ".woff", ".woff2", ".ttf", ".eot"] /** * 判断是否为静态资源 */ function isStaticResource(path) { return staticExts.some(ext => path.endsWith(ext)) } /** * 格式化请求日志 */ function formatRequestLog(ctx, ms) { const user = ctx.state?.user || null const ip = ctx.ip || ctx.request.ip || ctx.headers["x-forwarded-for"] || ctx.req.connection.remoteAddress return { timestamp: new Date().toISOString(), method: ctx.method, path: ctx.path, url: ctx.url, userAgent: ctx.headers['user-agent'], user: user ? { id: user.id, username: user.username } : null, ip, params: { query: ctx.query, body: ctx.request.body }, status: ctx.status, responseTime: `${ms}ms`, contentLength: ctx.length || 0 } } /** * 响应时间记录中间件 */ export default async function responseTime(ctx, next) { // 跳过静态资源 if (isStaticResource(ctx.path)) { await next() return } const start = Date.now() try { await next() } finally { const ms = Date.now() - start // 设置响应头 ctx.set("X-Response-Time", `${ms}ms`) // 页面请求简单记录 if (!ctx.path.includes("/api")) { if (ms > 500) { logger.warn(`Slow page request: ${ctx.path} | ${ms}ms`) } return } // API 请求详细记录 const logLevel = ms > 1000 ? 'warn' : ms > 500 ? 'info' : 'debug' const slowFlag = ms > 500 ? '🐌' : '⚡' logger[logLevel](`${slowFlag} API Request:`, formatRequestLog(ctx, ms)) // 如果是慢请求,额外记录 if (ms > 1000) { logger.error(`Very slow API request detected: ${ctx.method} ${ctx.path} took ${ms}ms`) } } }