3. 日志格式标准:常见日志格式与关键字段解析
日志格式这事儿,看着简单,但坑特别多。我见过不少团队,日志倒是打了,结果格式乱七八糟,排查问题时根本没法用。说白了,日志格式就是你和系统之间的「共同语言」,语言不通,啥都查不出来。
今天咱们就聊聊三种最常见的日志格式:JSON、纯文本、Syslog。我会把每种格式的特点、适用场景、关键字段都掰开揉碎了讲清楚。
3.1 三种主流日志格式对比
先给个总览,让你心里有个谱:
| 格式类型 | 可读性 | 机器解析 | 存储开销 | 典型场景 |
|---|---|---|---|---|
| JSON | 中等 | ★★★★★ | 较大 | 微服务、云原生、ELK |
| 纯文本 | ★★★★★ | ★★☆☆☆ | 较小 | 传统应用、开发调试 |
| Syslog | 中等 | ★★★★☆ | 中等 | 网络设备、Linux系统 |
我的建议:新项目优先选 JSON 格式。虽然多占点磁盘,但换来的是自动解析和结构化查询,排查效率翻倍。我接手过一个遗留系统,全是纯文本日志,每次查问题都得写一堆正则,那叫一个痛苦。
3.2 JSON 格式日志
JSON 格式现在基本是业界标准了。每个日志条目都是一个结构化的 JSON 对象,字段名和值清清楚楚。
一个标准的 JSON 日志长这样:
{
"timestamp": "2025-03-15T14:23:45.123+08:00",
"level": "ERROR",
"thread": "http-nio-8080-exec-3",
"logger": "com.example.order.OrderService",
"message": "订单创建失败:库存不足",
"context": {
"orderId": "ORD20250315001",
"userId": "U12345",
"sku": "SKU-8888"
},
"stackTrace": "com.example.exception.InventoryException: 库存不足\n\tat ..."
}
关键字段解析:
- timestamp:时间戳,必须带时区。我习惯用 ISO 8601 格式,跨时区排查时不会乱。
- level:日志级别,ERROR/WARN/INFO/DEBUG。别乱用,ERROR 就是系统出错了,别把业务异常也打 ERROR。
- thread:线程 ID 或线程名。高并发场景下,靠这个字段能把同一请求的日志串起来。
- logger:类名或包名。定位问题出在哪个模块,全靠它。
- message:日志正文。别写废话,要写「做了什么 + 结果 + 关键参数」。
- context:上下文信息。这个太重要了,能把请求链路串起来。
小技巧:JSON 日志里一定要加 traceId 或 requestId。我曾经排查一个分布式事务问题,就是因为每个服务都打了 traceId,才能在 10 万条日志里快速定位到完整的调用链。
3.3 纯文本日志
纯文本日志虽然老,但依然广泛存在。它的核心问题在于:格式不统一,解析全靠猜。
常见的纯文本格式:
2025-03-15 14:23:45.123 ERROR [http-nio-8080-exec-3] com.example.order.OrderService - 订单创建失败:库存不足
字段顺序一般是:时间戳 → 级别 → 线程 → 类名 → 消息。但不同团队、不同框架的格式差异很大。
纯文本日志的痛点:
- 字段分隔符不统一,有的用空格,有的用中划线
- 多行消息(比如堆栈)很难处理
- 没有上下文信息,排查问题得靠猜
避坑指南:我曾经接手过一个项目,纯文本日志里时间戳格式是 "03/15/2025 14:23:45",月份和日期写反了。结果日志分析工具解析出来的时间全是错的,排查问题时序完全乱套。所以,时间戳格式一定要统一,最好用 ISO 8601。
3.4 Syslog 格式
Syslog 是 Unix/Linux 世界的标准日志协议。它的格式有 RFC 3164(老版)和 RFC 5424(新版)两种。
RFC 5424 格式示例:
<14>1 2025-03-15T14:23:45.123Z myhost.example.com myapp 12345 - - 订单创建失败:库存不足
字段含义:
- <14>:优先级,由设施代码和严重级别计算得出
- 1:版本号
- 时间戳:精确到毫秒,带时区
- 主机名:产生日志的机器
- 应用名:进程名称
- 进程ID:PID
- 消息ID:可选,用于标识消息类型
Syslog 的优势在于标准化程度高,网络设备、防火墙、Linux 系统都在用。但缺点也很明显:字段固定,扩展性差,想加自定义字段比较麻烦。
3.5 关键字段深度解析
不管用哪种格式,有几个字段是必须认真对待的:
时间戳
时间戳是日志的灵魂。我见过太多因为时间戳问题导致的排查灾难:
- 没有时区信息,跨地域排查时差8小时
- 精度不够,毫秒级并发事件分不清先后
- 时钟不同步,不同机器的时间差几分钟
最佳实践:时间戳统一用 UTC 时间,精度到毫秒,格式用 ISO 8601。所有服务器必须配置 NTP 同步,时钟偏差超过 1 秒就要告警。
线程 ID / 线程名
Java 应用里,线程名通常包含线程池信息,比如 "http-nio-8080-exec-3"。通过线程名,你能知道:
- 请求来自哪个连接器
- 线程池的哪个线程在处理
- 是否存在线程阻塞或死锁
类名 / Logger 名
类名直接告诉你问题出在哪个模块。我习惯用包名作为 logger 名,这样在日志分析工具里可以按模块过滤。
3.6 日志格式知识体系
下面这张图总结了日志格式的核心知识结构,你可以对照着梳理自己的日志体系:
3.7 如何选择日志格式
选哪种格式,取决于你的场景:
- 微服务架构:必须用 JSON,配合 ELK/Loki 等工具,自动解析、全文检索
- 传统单体应用:纯文本够用,但建议逐步迁移到 JSON
- 网络设备/系统日志:Syslog 是标准,别乱改
- 开发调试:纯文本可读性好,但上线前要转成结构化格式
我的经验:不管选哪种格式,一定要在项目初期就定好规范。我见过太多项目,日志格式改来改去,最后历史日志全废了。定好规范后,用代码模板或注解强制统一,别靠自觉。
嗯,日志格式这块就聊到这儿。记住一句话:日志是给机器读的,不是给人读的。结构化、标准化,才能让日志真正成为排查问题的利器。