JavaScript 应用中的日志记录:Node.js 最佳实践
日志记录不仅仅是向控制台写入消息。在现代 Node.js 应用中,它是调试、监控和审计的关键工具。正确配置的日志记录可以快速发现错误、分析用户行为并确保服务稳定性。本文将介绍 JavaScript (Node.js) 中日志记录的最佳实践,从库的选择到集中式日志收集的配置。
1. 选择日志记录库
内置的 console.log 仅适用于开发环境。对于生产环境,需要使用专门的库,它们提供日志级别、格式化、文件轮转以及与外部系统的集成。
我们来看三个流行的选项:
- Winston — 最流行的库。灵活,支持多种传输方式(文件、控制台、HTTP、数据库)。适合复杂系统。
- Pino — 超快速日志记录器。推荐用于性能关键的高负载应用。
- Bunyan — 以 JSON 格式生成日志。便于机器处理。
Winston 配置示例:
const winston = require('winston');
const logger = winston.createLogger({ level: 'info', format: winston.format.json(), defaultMeta: { service: 'user-service' }, 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('服务已启动');logger.error('数据库连接错误', { db: 'main' });2. 使用日志级别
日志级别有助于按重要性过滤消息。标准层级(从最不关键到最关键):
- debug — 详细的调试信息(仅用于开发)。
- info — 标准事件(请求已处理,用户已授权)。
- warn — 潜在问题(内存不足,请求缓慢)。
- error — 严重错误(模块崩溃,异常)。
规则: 在生产环境中使用 info 或更高级别。debug 应被禁用,以避免填满磁盘并降低性能。
动态更改级别的示例:
const logger = require('./logger');
if (process.env.LOG_LEVEL) { logger.level = process.env.LOG_LEVEL;}
logger.debug('此消息不会出现在生产环境中');logger.info('用户已登录');logger.error('无法保存数据');3. 结构化日志 (JSON)
文本日志难以解析。现代实践是使用 JSON 格式的结构化日志。这可以轻松与分析系统(ELK, Splunk, Grafana Loki)集成。
每个日志应包含的内容:
- timestamp — 事件的精确时间(ISO 8601)。
- level — 日志级别。
- message — 人类可读的描述。
- context — 附加数据(请求 ID、用户名、错误代码)。
使用 Pino 的示例:
const pino = require('pino');
const logger = pino({ level: 'info', timestamp: pino.stdTimeFunctions.isoTime, formatters: { level(label) { return