Files
xiaocai/server/src/middleware/logger.ts
wangxiaogang 7f6da1fa10 fix: 恢复使用服务器本地时间,不硬编码时区
- logger.ts: 使用 new Date() 服务器本地时间
- logs.ts: 统计使用服务器本地时间
- 时区显示由客户端处理
2026-06-08 15:37:21 +08:00

86 lines
2.8 KiB
TypeScript
Raw 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.
import { Request, Response, NextFunction } from 'express'
import fs from 'fs'
import path from 'path'
// 日志目录
const LOG_DIR = path.resolve(process.env.LOG_DIR || './logs')
if (!fs.existsSync(LOG_DIR)) {
fs.mkdirSync(LOG_DIR, { recursive: true })
}
/** 获取当前日期字符串 YYYY-MM-DD服务器本地时间 */
function getDateStr(): string {
const d = new Date()
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
}
/** 格式化时间 HH:mm:ss.SSS服务器本地时间 */
function formatTime(date: Date): string {
return `${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}:${String(date.getSeconds()).padStart(2, '0')}.${String(date.getMilliseconds()).padStart(3, '0')}`
}
/** 写入日志文件 */
function writeLog(level: string, message: string, meta?: Record<string, any>) {
const dateStr = getDateStr()
const logFile = path.join(LOG_DIR, `${dateStr}.log`)
const now = new Date()
const time = formatTime(now)
const timestamp = now.toISOString() // 记录 UTC 时间戳,前端可按用户时区显示
const metaStr = meta ? ` ${JSON.stringify(meta)}` : ''
const line = `[${time}] [${timestamp}] ${level} ${message}${metaStr}\n`
fs.appendFile(logFile, line, (err) => {
if (err) console.error('[Logger] Write error:', err)
})
}
/** 请求日志中间件 */
export function requestLogger(req: Request, res: Response, next: NextFunction) {
const startTime = Date.now()
const { method, url, ip } = req
// 响应结束时记录日志(此时 authMiddleware 已执行userId 可用)
res.on('finish', () => {
const duration = Date.now() - startTime
const { statusCode } = res
// 延迟获取 userId确保 authMiddleware 已执行
const userId = (req as any).userId
const meta = {
method,
url,
status: statusCode,
duration: `${duration}ms`,
ip: ip || req.headers['x-forwarded-for'] || 'unknown',
userId: userId || null,
userAgent: req.headers['user-agent']?.slice(0, 100) || ''
}
if (statusCode >= 400) {
writeLog('ERROR', `${method} ${url} ${statusCode} ${duration}ms`, meta)
} else if (duration > 1000) {
writeLog('WARN', `Slow request: ${method} ${url} ${duration}ms`, meta)
} else {
writeLog('INFO', `${method} ${url} ${statusCode} ${duration}ms`, meta)
}
})
next()
}
/** 错误日志 */
export function logError(message: string, error: Error | any, meta?: Record<string, any>) {
writeLog('ERROR', message, {
...meta,
error: error?.message || String(error),
stack: error?.stack?.slice(0, 500) || ''
})
}
/** 业务日志 */
export function logInfo(message: string, meta?: Record<string, any>) {
writeLog('INFO', message, meta)
}
export default { requestLogger, logError, logInfo }