JavaScript 应用程序中的日志记录:最佳实践
日志记录不仅仅是把事件写入文件。在现代 Node.js 应用程序中,它是一个强大的监控、调试和审计工具。没有高质量的日志记录,在生产服务器上查找崩溃原因就像猜谜游戏。在本文中,我们将介绍 JavaScript (Node.js) 中的最佳日志记录实践,帮助您构建可靠且可维护的系统。
为什么标准 console.log 是不良实践
许多初学者开发者使用 console.log 进行调试。然而,在生产环境中,这会导致问题:
- 缺少级别:您无法区分信息性消息和关键错误。
- 没有结构:控制台输出只是难以解析的字符串。
- 阻塞式 I/O:同步写入可能会减慢应用程序。
- 缺少轮转:日志文件将无限增长。
相反,请使用专门的库,例如 winston 或 pino。它们提供灵活的传输配置(输出到文件、控制台、外部服务)和异步写入。
选择日志记录库:winston vs pino
在 Node.js 领域有两个明显的领导者。让我们看看它们的特点:
Winston
最流行的库。支持多种传输(文件、HTTP、MongoDB、Elasticsearch)和自定义格式。非常适合单体应用程序。
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' }), new winston.transports.Console({ format: winston.format.simple() }) ]});
logger.info('服务器在端口 3000 上启动');logger.error('数据库连接错误', { db: 'mongo', code: 500 });Pino
超快库,比 winston 快 5-10 倍。非常适合高负载系统和微服务。默认输出 JSON。
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(new Error('Timeout'), '请求错误');建议:对于大多数项目,选择 winston 因其灵活性。如果性能至关重要,请使用 pino。
日志记录级别:如何不被消息淹没
正确使用级别是良好日志记录的基础。在 Node.js 中,采用以下层次结构(从最不关键到最关键):
- trace / silly — 最详细的调试信息(通常在生产环境中关闭)。
- debug — 供开发者使用的调试消息。
- info — 确认正常运行(请求、服务启动)。
- warn — 异常情况,但应用程序继续运行(例如,超出请求限制)。
- error — 需要关注的错误(请求失败、外部服务故障)。
- fatal — 关键错误,应用程序无法继续运行。
通过环境变量配置日志记录级别:
const LOG_LEVEL = process.env.LOG_LEVEL || 'info';const logger = winston.createLogger({ level: LOG_LEVEL });在开发环境中设置为 debug,在生产环境中设置为 info。