「 简记往来」第二十篇:日志系统设计——没有日志,出了问题只能靠猜
一、没有日志的代价
有一次,用户反馈“批量记礼功能用不了”。
我登录服务器,查了代码、查了数据库、查了网络……折腾了一个小时,才发现是MongoDB连接超时。
如果有日志,这个问题30秒就能定位。
没有日志,出了问题只能靠猜。
二、Node.js日志的基本原则
Node.js日志管理通常遵循**“应用层 + 系统层 + 运维层”三层结合的策略**。
核心原则:
- 使用结构化日志:采用JSON格式,便于检索和分析
- 分级记录:ERROR / WARN / INFO / DEBUG
- 包含上下文:requestId、userId、timestamp等
- 异步写入:不阻塞事件循环
三、日志库选型
Node.js生态推荐三个日志库:
| 库 | 特点 | 适用场景 |
|---|---|---|
| Winston | 功能最全、支持多传输 | 需要多种输出方式 |
| Pino | 性能最好、JSON原生 | 高并发场景 |
| Bunyan | 轻量、结构化 | 简单应用 |
简记往来使用Winston:
constwinston=require('winston');constlogger=winston.createLogger({level:process.env.LOG_LEVEL||'info',format:winston.format.combine(winston.format.timestamp(),winston.format.json()),transports:[newwinston.transports.File({filename:'logs/error.log',level:'error'}),newwinston.transports.File({filename:'logs/combined.log'})]});if(process.env.NODE_ENV!=='production'){logger.add(newwinston.transports.Console({format:winston.format.simple()}));}四、日志分级
| 级别 | 用途 | 示例 |
|---|---|---|
| ERROR | 系统错误,需要立即处理 | 数据库连接失败 |
| WARN | 异常但可恢复 | 请求参数不完整,使用默认值 |
| INFO | 关键业务操作 | 用户登录、创建账本 |
| DEBUG | 调试信息 | 查询参数、中间件执行 |
生产环境建议将日志级别控制在WARN/ERROR,按需开启INFO/DEBUG。
五、日志格式规范
每条日志应包含:
{"timestamp":"2026-06-30T10:00:00.000Z","level":"INFO","service":"jianji-backend","requestId":"req_xxx","userId":"user_xxx","message":"用户登录成功","duration":125}requestId是贯穿整个请求链路的唯一标识,方便追踪问题。
六、日志存储与轮转
日志文件需要定期轮转,防止磁盘占满:
constDailyRotateFile=require('winston-daily-rotate-file');consttransport=newDailyRotateFile({filename:'logs/application-%DATE%.log',datePattern:'YYYY-MM-DD',maxSize:'20m',maxFiles:'14d'});七、总结
日志系统是运维的“眼睛”。
- 用Winston/Pino记录结构化日志
- 按ERROR/WARN/INFO/DEBUG分级
- 包含requestId、userId、timestamp等上下文
- 定期轮转,防止磁盘占满
没有日志,出了问题只能靠猜。有了日志,一切都有迹可循。
下一篇,我们来聊聊数据备份与恢复策略——数据丢了怎么办?
评论区聊聊:你的日志系统是怎么设计的?