Logstash 处理日志中可有可无的可选字段?

Logstash grok 处理可选字段:用括号加问号 (模式)? 把字段段标记为可选;或用多个模式备选。本文给出具体写法和示例。

最佳实践
Logstash 处理日志中可有可无的可选字段?封面

核心语法:在 grok 模式中把可选部分用圆括号包起来再加问号——(可选段)?。正则的 ? 让整个分组"出现 0 次或 1 次",字段不存在时该字段留空,整条日志仍能正常匹配。

示例:可选字段

日志有两种格式(有的带用户 ID,有的不带):

2024-01-15 10:30:00 INFO User logged in
2024-01-15 10:30:01 INFO User 42 logged in

grok 模式:

filter {
  grok {
    match => { "message" => "%{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:level} User( %{NUMBER:user_id})? logged in" }
  }
}

( %{NUMBER:user_id})? 表示"空格+数字"这一段是可选的:匹配到时提取 user_id 字段,没匹配到时整个事件照常解析、user_id 字段不存在。

多个可选段

match => { "message" => "%{IP:ip}( - %{WORD:user})? \"%{WORD:method} %{URIPATH:path}\" %{NUMBER:status}( %{NUMBER:duration})?" }

后续处理时判断字段是否存在

if [user_id] {
  mutate { convert => { "user_id" => "integer" } }
}

备选方案:多模式匹配

格式差异大时,与其堆叠可选段不如写多个模式:

grok {
  match => { "message" => [
    "%{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:level} User %{NUMBER:user_id} %{GREEDYDATA:msg}",
    "%{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:level} User %{GREEDYDATA:msg}"
  ] }
}

观测云对照

观测云 Pipeline 的 grok 函数同样支持正则可选分组语法,且提供在线调试:粘贴两种格式的样本日志即可验证模式,比"改配置-重启-看效果"的循环快得多。

常见问题(FAQ)

Q:可选段没匹配时字段是什么值?
A:字段不会出现在事件中(不是 null,是不存在)。用 if [field] 条件判断。

Q:可选段用非贪婪匹配 (??) 有必要吗?
A:一般不需要。(...)? 已足够;?? 是非贪婪量词,用于不同的场景。

Q:给可选字段设默认值?
A:if ![user_id] { mutate { add_field => { "user_id" => "anonymous" } } }

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台