CatPtain's picture
Upload 85 files
28e1dba verified
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;