2、日志格式规范:让每一条日志都成为线索

日志格式这事,说大不大,说小不小。我见过太多团队,日志写得随心所欲,检索的时候恨不得把键盘砸了。说白了,日志格式就是你和未来自己之间的约定——你希望三个月后的你,能一眼看懂今天写的日志吗?

核心观点:日志格式不是给机器看的,是给人看的。格式统一了,检索才有意义。

2.1 通用日志格式:五个字段,一个都不能少

我个人习惯,任何日志至少包含五个字段:时间戳、级别、线程、类名、消息。这五个字段就像身份证上的信息,缺了哪个都不好查。

字段 含义 示例 为什么重要
时间戳 日志产生的时间 2025-03-21 14:30:00.123 定位问题发生的时间点,排查性能瓶颈必备
级别 日志的严重程度 ERROR / WARN / INFO 快速过滤关键信息,别让INFO淹没了ERROR
线程 执行日志的线程名 http-nio-8080-exec-3 多线程环境下追踪请求链路,谁干了什么一目了然
类名 产生日志的类 com.example.OrderService 快速定位代码位置,不用翻源码猜
消息 具体的日志内容 订单创建成功,订单号:ORD123456 核心信息,必须包含关键业务标识

举个例子,一个标准的日志行长这样:

2025-03-21 14:30:00.123 [http-nio-8080-exec-3] ERROR com.example.OrderService - 订单创建失败,订单号:ORD123456,原因:库存不足

嗯,这里要注意:时间戳一定要带毫秒。我在项目中遇到过,排查一个性能问题,日志只精确到秒,结果同一秒内几十个请求混在一起,根本分不清先后顺序。加了毫秒之后,问题瞬间清晰了。

小技巧:时间戳统一用 ISO 8601 格式(yyyy-MM-dd HH:mm:ss.SSS),跨系统、跨语言解析都方便。别用自定义格式,比如 2025/03/21 14:30:00,解析起来麻烦。

2.2 自定义日志格式:按需扩展,别过度设计

通用格式够用吗?说实话,大部分场景够了。但有些时候,你需要加点料。比如微服务架构下,你得知道这条日志来自哪个服务实例;再比如处理用户请求时,你得能串联起整个调用链。

我建议,自定义字段遵循一个原则:不加则已,加必有因。每加一个字段,都要问自己:这个字段在检索时真的会用吗?

常见的自定义字段包括:

  • 请求ID(traceId):串联一次请求的所有日志,微服务排障利器
  • 用户ID(userId):快速定位某个用户的操作记录
  • 服务名(serviceName):分布式环境下区分日志来源
  • 环境标识(env):区分开发、测试、生产环境

举个例子,加上自定义字段后的日志:

2025-03-21 14:30:00.123 [http-nio-8080-exec-3] ERROR com.example.OrderService - [traceId=a1b2c3d4] [userId=10086] [env=prod] 订单创建失败,订单号:ORD123456,原因:库存不足

你看,多了几个字段,检索的时候就能按 traceId 把所有相关日志串起来。我曾经排查过一个线上问题,没有 traceId,只能靠时间戳和关键词硬猜,花了整整一个下午。后来加了 traceId,类似问题十分钟搞定。

避坑指南:自定义字段不要塞太多。我曾经见过一个团队,日志里塞了十几个自定义字段,结果日志行长得像裹脚布,不仅影响写入性能,检索时也眼花缭乱。记住:字段越多,维护成本越高。

2.3 日志字段设计原则:少即是多,稳即是快

设计日志字段,说白了就是做减法。我总结了四条原则,你可以直接拿来用。

  1. 唯一性原则:每条日志必须能唯一标识一个业务实体。比如订单号、用户ID、请求ID,至少有一个。
  2. 可检索原则:字段值要方便检索。避免用长文本、JSON 嵌套、特殊字符。比如消息里不要写 订单创建失败,原因:{"code":1001,"msg":"库存不足"},直接写 订单创建失败,原因:库存不足 更友好。
  3. 稳定性原则:字段名和字段类型一旦确定,不要轻易改。改了之后,历史日志的检索就断了。我见过一个项目,日志字段从 userId 改成 user_id,结果历史数据全废了。
  4. 最小化原则:只记录必要信息。别把整个请求体、响应体都塞进日志。日志量太大,存储和检索都是成本。

一句话总结:日志字段设计,就像收拾行李箱——能带上的才带,带不上的就别硬塞。

2.4 日志格式规范知识体系

下面这张图,把日志格式规范的核心内容串起来了。你可以把它当作一个检查清单,每次设计日志格式时对照一下。

日志格式规范知识体系 日志格式规范 通用日志格式 自定义日志格式 字段设计原则 时间戳 级别 线程 类名 消息 traceId userId serviceName env 唯一性原则 可检索原则 稳定性原则 最小化原则 核心要点 • 通用格式五字段:时间戳、级别、线程、类名、消息 • 自定义字段按需添加,不加则已,加必有因 • 字段设计四原则:唯一性、可检索、稳定性、最小化

2.5 实战建议:从今天开始改

如果你现在的日志格式还很混乱,别慌。我建议你分三步走:

  • 第一步:统一通用格式。先把时间戳、级别、线程、类名、消息这五个字段对齐。这是底线,不能妥协。
  • 第二步:按需加自定义字段。先加 traceId 和 userId,这两个最常用。其他字段等确实需要了再加。
  • 第三步:写一份日志规范文档。把格式、字段定义、示例都写清楚,团队所有人都按这个来。我见过太多团队,口头约定一套,写出来又是另一套。

最后说一句:日志格式规范这件事,越早做越好。等日志量上去了再改,成本高得吓人。你想想看,是现在花半天时间统一格式划算,还是以后花一周时间重构日志系统划算?