Spaces:
Running
Running
import winston from 'winston'; | |
import path from 'path'; | |
import { fileURLToPath } from 'url'; | |
import fs from 'fs'; | |
const __filename = fileURLToPath(import.meta.url); | |
const __dirname = path.dirname(__filename); | |
// 确保日志目录存在 | |
const logDir = path.join(__dirname, '../../logs'); | |
if (!fs.existsSync(logDir)) { | |
fs.mkdirSync(logDir, { recursive: true }); | |
} | |
// 自定义日志格式 | |
const logFormat = winston.format.combine( | |
winston.format.timestamp({ | |
format: 'YYYY-MM-DD HH:mm:ss' | |
}), | |
winston.format.errors({ stack: true }), | |
winston.format.printf(({ level, message, timestamp, stack }) => { | |
if (stack) { | |
return `${timestamp} [${level.toUpperCase()}]: ${message}\n${stack}`; | |
} | |
return `${timestamp} [${level.toUpperCase()}]: ${message}`; | |
}) | |
); | |
// 创建logger实例 | |
const logger = winston.createLogger({ | |
level: process.env.LOG_LEVEL || 'info', | |
format: logFormat, | |
transports: [ | |
// 控制台输出 | |
new winston.transports.Console({ | |
format: winston.format.combine( | |
winston.format.colorize(), | |
logFormat | |
) | |
}), | |
// 错误日志文件 | |
new winston.transports.File({ | |
filename: path.join(logDir, 'error.log'), | |
level: 'error', | |
maxsize: 5242880, // 5MB | |
maxFiles: 5 | |
}), | |
// 综合日志文件 | |
new winston.transports.File({ | |
filename: path.join(logDir, 'combined.log'), | |
maxsize: 5242880, // 5MB | |
maxFiles: 5 | |
}) | |
], | |
// 处理未捕获的异常 | |
exceptionHandlers: [ | |
new winston.transports.File({ | |
filename: path.join(logDir, 'exceptions.log') | |
}) | |
], | |
// 处理未处理的Promise拒绝 | |
rejectionHandlers: [ | |
new winston.transports.File({ | |
filename: path.join(logDir, 'rejections.log') | |
}) | |
] | |
}); | |
// 在生产环境中不输出到控制台 | |
if (process.env.NODE_ENV === 'production') { | |
logger.remove(logger.transports[0]); // 移除控制台传输 | |
} | |
// 添加请求日志中间件 | |
export const requestLogger = (req, res, next) => { | |
const start = Date.now(); | |
res.on('finish', () => { | |
const duration = Date.now() - start; | |
const logData = { | |
method: req.method, | |
url: req.url, | |
status: res.statusCode, | |
duration: `${duration}ms`, | |
ip: req.ip || req.connection.remoteAddress, | |
userAgent: req.get('User-Agent') | |
}; | |
if (res.statusCode >= 400) { | |
logger.warn(`HTTP ${res.statusCode} - ${JSON.stringify(logData)}`); | |
} else { | |
logger.info(`HTTP ${res.statusCode} - ${JSON.stringify(logData)}`); | |
} | |
}); | |
next(); | |
}; | |
export default logger; |