Skip to content
返回构建教程

日志搭建

第一天装结构化日志带级别、请求 ID 和关联上下文。

为什么

console.log 对 50 行脚本可,生产致命:不能按级别过滤、不能跨请求关联、不能搜需 SSH 进机。结构化日志(JSON 带级别、时间戳、request_id、user_id)把日志变可查数据——你能问'过去 1 小时用户 42 的每个错误'秒得答。请求 ID 是乘数:它把请求内每行日志系一起,用户报'3 点结账失败'变单次 grep 非 10k 行滚动。事后补痛苦因每调用点要改;第一天做是 20 行配置。

何时使用

紧跟 project-init,第一个功能前。约 20-30 分钟。仅无服务器的 CLI 工具可跳过。

如何做

1. 选结构化 logger:pino(Node,最快)、structlog(Python)、zap(Go)
   - 避免 winston/log4j——可配但慢且鼓励字符串模板

2. 定义日志级别及每级对应用含义
   - debug:仅 dev;info:请求生命周期;warn:降级但处理;error:需关注
   - prod 级别设 info,staging 设 debug——prod 永不 trace(量杀你)

3. 加请求 ID 中间件,每请求生 UUID 并每行记
   - Express:req.id = uuid();logger.child({ requestId: req.id })
   - 经 x-request-id 头传下游调用,trace 跨服务

4. 记结构化对象非插值字符串
   - logger.info({ userId, action: "checkout", durationMs }, "checkout completed")
   - 永不 logger.info(`User ${userId} checked out in ${ms}ms`)——不可搜

5. 日志发可搜 sink:Datadog、Loki、CloudWatch——非磁盘文件
   - dev 留本地文件回退;prod stdout → 容器日志驱动 → 聚合

示例

// logger.ts——pino 带请求 id 子 logger
import pino from "pino";
export const logger = pino({
  level: process.env.LOG_LEVEL ?? "info",
  formatters: { level: (label) => ({ level: label }) },
});

// middleware.ts——每请求子 logger
import { v4 as uuid } from "uuid";
export function requestLogger(req, res, next) {
  req.id = req.headers["x-request-id"] ?? uuid();
  req.log = logger.child({ requestId: req.id, userId: req.user?.id });
  req.log.info({ method: req.method, url: req.url }, "request start");
  res.on("finish", () => req.log.info({ status: res.statusCode }, "request end"));
  next();
}

// 路由用法——结构化、可搜
router.post("/checkout", async (req, res) => {
  const t0 = Date.now();
  await processCheckout(req.body);
  req.log.info({ action: "checkout", durationMs: Date.now() - t0 }, "checkout ok");
});

常见问题

  • ⚠info 级日志记密钥(密码、token、PII)发第三方聚合——合规事件。
  • ⚠dev 用 console.log,prod 用别 logger,prod 行为成意外。
  • ⚠无请求 ID,用户报'3 点失败'意味滚 10k 行碰运气找错。
  • ⚠热循环内(10k 行批每行)info 级记,量淹聚合。

最佳实践

  • ✓加脱敏格式器,日志离进程前剥已知密钥键(password、token、authorization)。
  • ✓用跨服务边界传播的关联 ID(HTTP 头、消息队列属性),多服务 trace 一查询。
  • ✓prod 采样 debug/trace(1000 请求取 1),偶得深 trace 无量成本。
  • ✓对错误率突增告警非单个错——单错正常;5 分钟 10 倍突增是事件。