以下是 Winston 在 Express 中的详细使用方式,以及如何配置按日分割日志文件的步骤:
1. 安装依赖
npm install winston winston-daily-rotate-file express
2. 基础配置:创建 Winston Logger
在项目中新建 logger.js 文件,配置日志系统和文件分割规则:
const winston = require('winston');
const { combine, timestamp, printf, colorize } = winston.format;
// 自定义日志格式
const logFormat = printf(({ level, message, timestamp }) => {
return `${timestamp} [${level}]: ${message}`;
});
// 创建 Logger 实例
const logger = winston.createLogger({
level: 'info', // 设置日志级别(error, warn, info, verbose, debug, silly)
format: combine(
timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), // 添加时间戳
logFormat // 应用自定义格式
),
transports: [
// 控制台输出(带颜色)
new winston.transports.Console({
format: combine(colorize(), logFormat)
}),
// 按日分割文件
new winston.transports.DailyRotateFile({
dirname: 'logs', // 日志目录
filename: 'app-%DATE%.log', // 文件名(%DATE% 自动替换为日期)
datePattern: 'YYYY-MM-DD', // 日期格式
zippedArchive: true, // 压缩旧日志
maxSize: '20m', // 单个文件最大大小
maxFiles: '30d' // 保留最近30天的日志
})
],
// 异常处理(可选)
exceptionHandlers: [
new winston.transports.File({ filename: 'logs/exceptions.log' })
],
// Promise拒绝处理(可选)
rejectionHandlers: [
new winston.transports.File({ filename: 'logs/rejections.log' })
]
});
module.exports = logger;
3. 在 Express 中集成 Winston
3.1 记录请求日志
在 app.js 中,添加中间件记录 HTTP 请求:
const express = require('express');
const logger = require('./logger'); // 导入配置好的 Logger
const app = express();
// 自定义请求日志中间件
app.use((req, res, next) => {
const start = Date.now();
res.on('finish', () => {
const duration = Date.now() - start;
logger.info(
`${req.method} ${req.originalUrl} - ${res.statusCode} (${duration}ms)`
);
});
next();
});
3.2 记录错误日志
在错误处理中间件中捕获异常:
// 错误处理中间件
app.use((err, req, res, next) => {
logger.error(`Error: ${err.message}`, { stack: err.stack });
res.status(500).send('Internal Server Error');
});
4. 使用示例
在路由或服务中直接调用 Logger:
// 示例路由
app.get('/api/data', (req, res) => {
try {
logger.debug('Fetching data from database...');
// 业务逻辑
res.json({ data: 'success' });
} catch (err) {
logger.error('Database error: %s', err.message);
res.status(500).send('Error');
}
});
5. 日志分割配置详解
dirname: 'logs'
日志文件存储在项目根目录的logs文件夹中。filename: 'app-%DATE%.log'
每日生成的文件名格式(如app-2023-10-01.log)。datePattern: 'YYYY-MM-DD'
按日分割,也支持按小时(YYYY-MM-DD-HH)。zippedArchive: true
旧日志自动压缩为.gz文件以节省空间。maxSize: '20m'
单个日志文件超过 20MB 时触发分割(即使未到日期)。maxFiles: '30d'
自动删除 30 天前的日志文件。
6. 日志文件结构
运行后生成的日志文件结构如下:
logs/
app-2023-10-01.log # 当日日志
app-2023-09-30.log.gz # 压缩的旧日志
exceptions.log # 异常日志
rejections.log # Promise拒绝日志
7. 高级配置(可选)
7.1 多级别日志分割
为不同级别(如 error 和 info)创建独立文件:
transports: [
new winston.transports.DailyRotateFile({
level: 'error', // 仅记录 error 级别
filename: 'error-%DATE%.log',
// 其他配置同上
}),
new winston.transports.DailyRotateFile({
level: 'info', // 仅记录 info 级别
filename: 'info-%DATE%.log',
// 其他配置同上
})
]
7.2 自定义日志格式
添加更多上下文信息(如请求 IP):
const logFormat = printf(({ level, message, timestamp, meta }) => {
return `${timestamp} [${level}] ${meta?.ip || '-'} - ${message}`;
});
// 在中间件中传递元数据
logger.info('Request received', { ip: req.ip });
8. 注意事项
- 日志级别管理
通过logger.level动态调整日志详细程度(生产环境建议设为info或warn)。 - 性能优化
高频日志(如每条请求)建议使用winston的批量写入或异步模式。 - 敏感信息过滤
避免在日志中记录密码、Token 等敏感数据。 - 日志清理策略
根据磁盘空间调整maxFiles或maxSize。
总结
通过 Winston 和 winston-daily-rotate-file,Express 项目可以实现灵活的日志管理,包括按日分割、多级别存储和自动化压缩清理。结合中间件集成,能够全面监控请求流程和异常状态,是生产环境日志系统的可靠选择。