当前位置: 首页 > news >正文

Node.js 实战六:日志系统设计 —— 不只是 console.log,而是可追溯的行为记录链

开发时你写:

console.log('进来了');

上线后出 bug,产品问:

“这个用户为啥订单创建失败?”

你打开服务器一看,啥也没有。于是陷入盲猜、靠运气 debug 的地狱模式。

你需要日志。不是调试用的,而是生产可追溯的

本篇我们讲讲:

如何在 Node.js 项目中构建一个 结构清晰、功能全面、适合生产环境的日志系统

一、日志系统需要满足哪些核心能力?

能力

含义

分级分类

info、warn、error、debug,不同级别记录

可持久化

存磁盘、发远程、进数据库

可筛查

带时间、用户、路径、traceId 等信息

可格式化

JSON、文本、彩色 console

可扩展

接入监控系统,发送告警,支持日志聚合服务

二、日志库推荐:winston / pino

winston(功能全、文档好、插件多)

npm install winston
import winston from 'winston';const logger = winston.createLogger({level: 'info',format: winston.format.combine(winston.format.timestamp(),winston.format.json()),transports: [new winston.transports.Console(),              // 控制台new winston.transports.File({ filename: 'logs/error.log', level: 'error' }),new winston.transports.File({ filename: 'logs/combined.log' }),],
});

三、日志等级与使用规范

等级

用于记录

error

程序异常、业务错误

warn

潜在问题、预期外但非致命事件

info

请求成功、关键行为记录

debug

调试信息,开发/测试环境开启

使用建议:

logger.info('User login success', { userId: 123 });
logger.error('Create order failed', { error: e.message, reqId });

四、给每个请求打上 traceId(链路追踪)

为了把一串相关日志串起来:

  1. 在中间件中生成唯一 ID(如 uuid)

  2. 注入到 ctx/request 中,写入每条日志

const { v4: uuidv4 } = require('uuid');app.use(async (ctx, next) => {ctx.traceId = uuidv4();await next();
});

然后写日志时统一带上:

logger.info('Processing payment', { traceId: ctx.traceId });

这样你就能一眼查出“这一波请求发生了啥”。

五、日志落盘与分环境配置

推荐结构:

logs/
├── error.log
├── combined.log
├── access.log

开发环境只打印 console

生产环境写文件 + 控制台(可彩色输出)

if (process.env.NODE_ENV !== 'production') {logger.add(new winston.transports.Console({format: winston.format.simple()}));
}

六、接入远程日志系统(推荐方式)

目标系统

工具

阿里云 SLS

aliyun-sls-sdk

ElasticSearch

filebeat + logstash

Loki + Grafana

winston-loki 插件

日志告警(如钉钉)

winston-dingding 等 webhook 插件

建议:关键 error 日志可额外推送报警渠道

七、扩展:用户行为日志 / 操作记录系统设计

除了系统层级的 error/info/debug,你还应该记录 业务行为日志,例如:

  • 谁登录了系统?

  • 谁删除了某条数据?

  • 谁修改了用户权限?

  • 谁导出了哪些数据?

这些信息不仅有助于:

  • 审计追责

  • 用户行为分析

  • 风控与安全预警

  • 后台展示操作记录

建议做法:

  1. 定义一个 log_behavior 表,结构如:

CREATE TABLE log_behavior (id BIGINT PRIMARY KEY AUTO_INCREMENT,user_id BIGINT,action VARCHAR(64),target_type VARCHAR(64),target_id BIGINT,timestamp DATETIME,detail TEXT
);

2. 在关键业务逻辑中插入行为日志:

await behaviorLogger.log({userId: ctx.state.user.id,action: 'delete_user',targetType: 'user',targetId: deletedUser.id,detail: JSON.stringify({ reason: 'admin operation' }),
});

3. 可配合后台系统展示为“操作日志模块”。

八、日志系统落地注意事项清单 

建议做法

❯ 文件命名

按日期拆分,或按级别分文件(logs/error-20240512.log)

❯ 格式

JSON 格式日志利于机器读取(如 ELK)

❯ 打印内容

包含 userId、traceId、req.path、IP、UA 等上下文信息

❯ 保留期限

每日日志建议保留 7~30 天,可用定时清理脚本

❯ 安全性

过滤敏感字段,如密码、token,不应打印入日志

总结

日志不是“写给自己看的调试输出”,它是:

  • 问题追溯的核心线索

  • 用户行为的安全记录

  • 系统稳定的前置保障

  • 可观测性的最底层能力

稳定的项目,不是靠程序没出 bug,而是出了 bug 你“知道它在哪、为什么、什么时候发生的”。

构建一套规范、分级、可扩展的日志系统,是任何线上项目的“标配基建”。

相关文章:

  • 单目测距和双目测距 bev 3D车道线
  • 常见面试题:Webpack的构建流程简单说一下。
  • iOS 内存分区
  • 报错System.BadImageFormatException:“试图加载格式不正确的程序。 (异常来自 HRESULT:0x8007000B)”
  • 滑动窗口算法详解与C++实现
  • 蓝桥杯1140 最小质因子之和(Hard Version)
  • 深入理解位图(Bit - set):概念、实现与应用
  • 蓝桥杯19681 01背包
  • Web开发-JavaEE应用SpringBoot栈SnakeYaml反序列化链JARWAR构建打包
  • linux本地部署ollama+deepseek过程
  • 职场方法论总结(4)-如何正确地汇报
  • 使用Python制作Lorenz吸引子的轨道生成视频
  • 《云端共生体:Flutter与AR Cloud如何改写社交交互规则》
  • 数字电子技术基础(六十)——使用Digital软件绘制脉冲触发的触发器
  • C++:static成员
  • 你引入的lodash充分利用了吗?
  • 封装、继承、多态的理解
  • 基于区块链技术的供应链溯源系统:重塑信任与透明度
  • 改进模糊C均值时序聚类+编码器状态识别!IPOA-FCM-Transformer组合模型
  • ESMFold在线预测蛋白质结构
  • 山东发布高温橙警:预计19日至21日局地可达40℃
  • 人民网:激发博物馆创新活力,让“过去”拥有“未来”
  • 打造信息消费新场景、新体验,上海信息消费节开幕
  • 101岁陕西省军区原司令员冀廷璧逝世,曾参加百团大战
  • 广西百色“致富果”:高品质芒果直供香港,带动近五千户增收
  • 特朗普再提“接管”加沙,要将其变为“自由区”