日志格式标准:Syslog、JSON、CEF、自定义格式
说到日志,第一件事是什么?不是存哪里、存多久,而是——你拿到的日志到底是什么样子的。我见过太多团队上来就谈存储方案,结果日志格式乱七八糟,解析器写了一个又一个,最后数据根本对不上。所以今天咱们先把格式这事掰扯清楚。
日志格式,说白了就是你在日志文件里看到的那一行行文字(或二进制)的结构约定。没有标准,系统间互读就是灾难。我个人习惯是:选格式前先把这三件事想清楚——谁来消费?数据量多大?字段固定还是多变?
2.1 Syslog:最老牌的文本日志
Syslog 从 Unix 时代就存在了,现在你用 Linux 服务器,/var/log/syslog 或 /var/log/messages 用的就是它。格式很简洁:时间戳 + 主机名 + 进程/模块 + 消息正文。
但你要注意:Syslog 没有强制要求消息正文的结构。所以同样是 SSH 登录失败的日志,不同设备能写出八种样子:
# 传统 Syslog(RFC 3164)
Mar 29 10:15:30 webserver sshd[1234]: Failed password for root from 192.168.1.100 port 22
# 新版 Syslog(RFC 5424,带结构化数据)
<34>1 2025-03-29T10:15:30.123Z webserver sshd 1234 - [timeQualified reason="password"][origin ip="192.168.1.100"]
Failed password for root
RFC 5424 引入了结构化数据(SD-ELEMENT),可以塞进 key-value 对。嗯,这就是进步。但现实中很多老设备只支持 RFC 3164,你解析时必须兼容两种。
2.2 JSON:灵活的结构化日志
JSON 是我现在最常用的格式。为什么?因为它天然支持嵌套、数组、任意字段。你可以在一个日志事件里塞 host、user、request、response、error stack,可读性好,解析也简单。
{
"timestamp": "2025-03-29T10:15:30.123Z",
"level": "ERROR",
"logger": "com.example.OrderService",
"thread": "http-nio-8080-exec-3",
"message": "Payment timeout for order #12345",
"context": {
"orderId": 12345,
"userId": "u_998877",
"amount": 299.99,
"retryCount": 3,
"targetService": "payment-gateway"
}
}
你想想看,如果用 Syslog 写上面这条日志,消息正文就得拼成一长串,解析时还得用正则拆。但 JSON 直接拿来就能用,日志收集工具(Filebeat、Fluentd)原生支持,字段映射成本几乎为零。
但 JSON 也有坑——体积大。每条日志多了花括号、逗号、引号,数据量上涨 30%~50% 很正常。如果你的日志量每天几个 TB,那就得考虑压缩或换更紧凑的格式了。
2.3 CEF:安全设备的最爱
CEF(Common Event Format)是 ArcSight 定义的标准,现在几乎成了安全设备日志的默认语言。防火墙、IDS/IPS、VPN 网关都会输出 CEF。为什么呢?因为 CEF 在一条日志里同时保有了必选字段的固定位置和扩展字段的灵活性。
标准格式长这样:
CEF:版本|设备厂商|设备产品|设备版本|事件类型|事件名称|严重级别|扩展字段
# 实际例子:
CEF:0|PaloAlto|PAN-OS|10.1|traffic|allow|5|src=192.168.1.10 dst=10.0.0.1 dport=443
proto=tcp app=ssl bytes=2048
看懂了吗?前面 7 个竖线分隔的字段是固定位置,后面的扩展字段用 key=value 格式。这样既保证了解析器能快速拿到设备名、事件类型、严重级别,又不限制你想加什么额外信息。
但我得说一句,CEF 的缺点也很明显——字段名没有统一字典。A 厂商用 src,B 厂商用 sourceAddress,归一化时你得写映射表。还有,有些设备厂商在扩展字段里塞了很多自定义的“=”或空格需要转义,解析时一不留神就踩坑。
raw=user=admin&pass=***。解析器直接把它拆成了两个字段,导致后面的字段错位。后来我加了一个判断:如果 value 以双引号开头,就把它当整体直到下一个未转义的双引号。
2.4 自定义格式:什么时候用?怎么用?
上面三种都不满足你,那就只有自己造轮子了。但——你确定吗?我见过很多团队因为“不想写复杂的解析规则”就自创格式,结果后期维护成本远高于预期。
什么时候可以考虑自定义:
- 你的业务场景非常特殊,标准格式无法表达核心字段
- 数据量极大(比如百万条/秒),必须用极简的分隔符格式来压缩体积
- 传递的是二进制协议,文本格式不再适用
举个例子,我曾经在 IoT 平台做过一个协议:设备ID|时间戳|槽位号|传感器类型:值|...|校验码,没有花括号没有引号,一条日志只有几十字节。解析器也简单,直接用 split('|') 就能拿到所有字段。
但自定义格式必须有版本号和文档。版本号可以放在第一个字段,方便未来升级。文档要写清楚每个字段的顺序、类型、取值范围、转义规则。否则过了半年换个人来维护,你连猜带蒙都看不懂。
2.5 格式对比与选择决策
下面这个表格我经常用在方案评审会上,帮你快速定位该用哪种:
| 特性 | Syslog | JSON | CEF | 自定义(举例) |
|---|---|---|---|---|
| 解析复杂度 | 低(但消息体需要正则) | 低(标准解析器) | 中(字段需映射字典) | 高(自己写解析器) |
| 灵活度 | 低(消息体非结构化) | 高(嵌套/可变字段) | 中(扩展字段但无约束) | 极高(可完全定制) |
| 数据体积 | 小(纯文本) | 大(元数据多) | 中(分隔符+key=value) | 极小(二进制或极简分隔符) |
| 设备支持 | 几乎所有网络/安全设备 | 应用层、微服务 | 安全设备(SIEM 生态) | 仅自定义系统 |
| 跨系统互操作性 | 高(通用标准) | 高(Web 生态通用) | 中(安全圈通用) | 低(绑定自家系统) |
你看,没有银弹。选格式实际上是在灵活度、体积、解析成本三者之间找平衡。下面的 SVG 图更直观地展示了这个决策过程: