JavaScript 应用中的日志记录:实践中的最佳实践
日志记录不仅仅是向控制台写入消息。在生产环境中,配置良好的日志记录成为监控、调试和审计的主要工具。没有它,你就是在盲目工作。在本文中,我们将探讨 Node.js 上 JavaScript 应用程序的日志记录最佳实践,从库的选择到日志轮转的配置。所有代码示例均可直接使用。
1. 为什么 console.log 不好?
在开发阶段,我们都使用 console.log。它快速且方便。但在生产环境中,这种方法很危险:
- 没有日志级别。 你无法将错误与信息消息区分开来。
- 同步阻塞。 标准的
console.log在高请求量下可能会减慢应用程序。 - 缺乏结构。 没有额外的辅助工具,JSON 日志无法被解析。
- 没有轮转。 日志文件会无限增长,直到填满磁盘。
相反,请使用专业的库。Node.js 中最流行的两个是 Winston 和 Pino。
2. 库的选择:Winston vs Pino
这两个库解决同一个问题,但有不同的侧重点。
Winston — 通用且灵活
Winston 是日志记录领域的“瑞士军刀”。它支持多种传输方式(文件、控制台、HTTP、数据库),并且易于配置。
const winston = require('winston');
const logger = winston.createLogger({ level: 'info', format: winston.format.json(), transports: [ new winston.transports.File({ filename: 'error.log', level: 'error' }), new winston.transports.File({ filename: 'combined.log' }), ],});
// 在开发环境中添加控制台输出if (process.env.NODE_ENV !== 'production') { logger.add(new winston.transports.Console({ format: winston.format.simple(), }));}
logger.info('服务器已在端口 3000 上启动');logger.error('数据库连接错误', { db: 'postgres' });Pino — 速度至上
Pino 被定位为 Node.js 最快的日志记录器。由于使用了 sonic-boom(异步写入),它比 Winston 快 5-6 倍。非常适合高负载项目。
const pino = require('pino');
const logger = pino({ level: process.env.LOG_LEVEL || 'info', transport: { target: 'pino/file', options: { destination: './app.log' }, },});
logger.info({ user: 'admin' }, '用户已登录系统');logger.error({ err: new Error('Timeout') }, '请求超时');建议: 对于高负载的微服务和 API,选择 Pino。对于需要多种传输方式的复杂配置,选择 Winston。
3. 日志级别:不要把所有内容都写入 info
使用标准级别范围(按重要性递增):
trace/debug— 仅用于开发。详细的调试信息。info— 应用程序正常运行:启动、成功请求、业务事件。warn— 潜在问题:慢请求、内存不足、已弃用的方法。error— 异常、故障、崩溃。应始终放在单独的文件或监控系统中。fatal— 严重错误,应用程序无法继续运行。
配置环境变量 LOG_LEVEL,以便无需重启代码即可更改过滤级别:
// 使用 Winston 的示例const logger = winston.createLogger({ level: process.env.LOG_LEVEL || 'info', // ...});
// 在