2. 日志标准与格式:syslog、JSON、CEF、W3C 解析

日志格式这个东西,刚入门的人往往觉得枯燥。说实话,我之前也这么想。直到有一次排查线上故障,因为日志格式不统一,我硬是花了三个小时才把不同系统的日志拼凑出完整链路。嗯,从那以后,我再看日志格式,就跟看地图似的——不把图例搞清楚,走哪都是弯道。

这一章,我会把工业界最常见的四种日志格式掰开揉碎了讲。每种格式我都在实际项目里踩过坑、填过坑。你学完就能知道:什么时候该用 syslog,什么时候上 JSON,什么时候非 CEF 不可。

核心要点: 格式不是装饰,是协议。你选的格式决定了你能查多深的线索。
常见日志格式知识结构 日志格式选型 syslog JSON CEF W3C 传统设备、网络日志 RFC 3164 / 5424 文本流,可读性中 现代应用、API 日志 自定义字段,嵌套结构 可读性高,解析快 安全设备(IPS/IDS) ArcSight 标准 字段固定,易于关联 Web 服务器日志 IIS / Apache / Nginx 注:实际生产环境中常常多种格式混用,建议统一归一化后再做巡检分析。

2.1 syslog:经典中的经典

syslog 是日志格式里的老兵了。从 Unix 时代就存在,RFC 3164 定义了最早版本,后来 RFC 5424 做了结构化扩展。我最早接触运维时,交换机、路由器、防火墙,清一色 syslog。

它的基本结构很简单:时间戳 + 主机名 + 进程名 + 消息内容。但简单也意味着灵活,灵活有时候就成了混乱的来源。

<134>2025-01-15T08:12:30Z my-firewall %ASA-6-302013: Built inbound TCP connection 12345 from 10.0.1.100/443 to 192.168.1.50/52341

上面这条是 Cisco ASA 防火墙的典型 syslog。前面的 <134> 是优先级值,计算方式是 facility × 8 + severity。我刚开始看到这个数字一头雾水,后来才搞清楚——<134> 意味着 facility=16 (local0),severity=6 (informational)。

小技巧: 在巡检脚本里,我习惯用 facility 来区分日志来源,local0-local7 留给不同业务系统。这样写过滤规则特别干净。

2.2 JSON:现代日志的标配

你想想看,现在哪个微服务框架不吐 JSON 日志?说白了,JSON 就是给程序读的,结构清晰,字段随意扩展,解析效率也高。

{
    "timestamp": "2025-01-15T08:12:30.123Z",
    "level": "WARN",
    "service": "user-svc",
    "trace_id": "ab12cd34",
    "user_id": "u-88721",
    "action": "login_failed",
    "detail": {
        "reason": "invalid_password",
        "attempt": 3,
        "ip": "203.0.113.42"
    }
}

我做审计日志巡检时,JSON 格式的处理最顺手。因为字段是自描述的,不需要额外查手册。但注意——JSON 日志一定要控制嵌套深度。超过三层,查询性能就开始打折了。我在项目里见过有人嵌套了六层,结果 ELK 直接崩了。

避坑提醒: 我曾经在一个金融项目里,日志 JSON 里包含了完整的请求体,导致单条日志超过 2MB。存储和网络都扛不住。记住:日志不是存储,别把原始数据全塞进去。

2.3 CEF:安全分析的通用语言

CEF(Common Event Format)是 ArcSight 定义的格式,现在基本成了安全设备的普通话。像 IPS、IDS、WAF、DLP 这些设备,输出 CEF 格式是最标准的做法。

它的结构是:前缀 + 扩展字段。前缀部分固定包含 Device Vendor、Device Product、Device Version、Signature ID、Severity 等。扩展字段用 key=value 形式,字段名都是标准化的。

CEF:0|PaloAlto|PAN-OS|10.1.0|THREAT|Traffic|5|src=10.0.1.100 dst=192.168.1.50 spt=443 dpt=52341 proto=tcp act=block cn1=12345 msg=Malicious traffic detected

你看这条,前缀部分:CEF 版本 0,厂商 PaloAlto,产品 PAN-OS,版本 10.1.0,签名 ID THREAT,事件名 Traffic,严重度 5。后面全是扩展字段。我特别喜欢 CEF 的一点是:字段名是跨厂商统一的。src、dst、spt、dpt 在所有设备里含义都一样。

格式 主要场景 可读性 解析复杂度 字段扩展性
syslog 网络设备、Unix 系统 中等 低 差
JSON 应用、API、微服务 高 低 优
CEF 安全设备(IPS/IDS/WAF) 中等 中 良
W3C Web 服务器(IIS/Nginx) 中等 低 中

2.4 W3C:Web 服务器的规范日志

W3C 格式是 IIS 的默认日志格式,也是很多 Web 服务器支持的格式。它的特点是用 # 开头的指令定义字段顺序,数据行按那个顺序排列。

#Fields: date time cs-method cs-uri-stem sc-status cs(User-Agent)
2025-01-15 08:12:30 GET /api/v2/orders 200 Mozilla/5.0
2025-01-15 08:12:31 POST /api/v2/login 401 PostmanRuntime/7.36.0

W3C 的好处是字段可以在头部自定义。你只要修改 #Fields 那一行,后面的数据就自动对齐。但我遇到过一个问题:有些运维人员改了字段顺序忘了同步下游解析器,导致日志解析全是乱码。这个坑在团队协作里特别常见。

我的做法: 在每个 Web 服务器集群的 W3C 配置里,我会定义一个固定的字段模板,并且版本控制。下游解析脚本直接读取头部 #Fields 做动态映射,这样前后端解耦,改字段也不影响解析。

2.5 格式归一化:巡检自动化的第一步

你可能会问:这么多格式,我怎么统一处理?说实话,我在做巡检自动化时,并不会直接处理原始日志。我会先做一个归一化层,把 syslog、JSON、CEF、W3C 全部转成统一的中间格式。

归一化层要处理三个差异:

  • 时间戳格式差异——有的用 ISO 8601,有的用本地时间,有的用 epoch
  • 字段命名差异——同样是源 IP,syslog 里可能是 src,CEF 里是 src,JSON 里是 source_ip
  • 严重度标识差异——syslog 用 0-7,CEF 用 0-10,JSON 用字符串
{
    "normalized": {
        "timestamp": "2025-01-15T08:12:30.000Z",
        "src_ip": "10.0.1.100",
        "dst_ip": "192.168.1.50",
        "src_port": 443,
        "dst_port": 52341,
        "protocol": "tcp",
        "severity": "medium",
        "raw_format": "syslog",
        "raw_message": "<134>2025-01-15T08:12:30Z my-firewall %ASA-6-302013: ..."
    }
}

归一化后的结构,就是后面几章要做自动化巡检的基础。没有这个标准层,你写的规则会非常脆弱——换一个设备厂商,规则就得重写。

经验之谈: 归一化层别做太多“智能推断”。我见过有人试图自动识别所有格式,最后搞出了几十条正则,性能和准确性都不行。建议做白名单匹配:先判断格式类型,再用专用解析器。四个格式写四个解析器,比一个万能解析器靠谱得多。