如何修改Grok过滤规则以同时提取level与requestId字段?
问题与解决方案
问题背景
测试日志语句:
2023-03-07T19:09:26.661856688Z stdout F {"test1":"one","level":"info","message":"Query Params","requestId":"66x66x7b7951a5d9c609359146b3f435","test2":"two"}
当前使用的Grok模式:
%{TIMESTAMP_ISO8601:[container][log][timestamp]} (?:%{WORD:[container][log][stream]}) (?:%{WORD:[container][log][designator]}) {(%{GREEDYDATA:data_before},)?("level":%{DATA:SEVERITY})?(,%{GREEDYDATA:data_after_severity},)?("requestId":%{DATA:requestId})?(,%{GREEDYDATA:data_after_id})}
目标是提取日志体中的level和requestId字段,但当前仅成功提取requestId,level被包含在data_before字段中无法单独获取,返回结果:
{ "[container][log][timestamp]": "2023-03-07T19:09:26.661856688Z", "requestId": "\"66x66x7b7951a5d9c609359146b3f435\"", "[container][log][stream]": "stdout", "data_before": "\"test1\":\"one\",\"level\":\"info\",\"message\":\"Query Params\"", "[container][log][designator]": "F", "data_after_id": "\"test2\":\"two\"" }
问题根源
GREEDYDATA属于贪婪匹配规则,会尽可能抓取最多的字符。你的模式中data_before直接匹配到了requestId之前的所有内容,包含level字段,导致后续匹配level的规则完全无法触发。
解决方案
方案1:Grok提取JSON体 + JSON过滤器(推荐)
这种方式更稳定,适配JSON格式日志的通用场景:
- 先用Grok提取日志元数据和完整JSON体:
%{TIMESTAMP_ISO8601:[container][log][timestamp]} %{WORD:[container][log][stream]} %{WORD:[container][log][designator]} %{DATA:log_body}
- 搭配
json过滤器解析log_body字段,可自动解析出JSON中的所有字段,包括level和requestId,无需编写复杂的Grok规则。
方案2:纯Grok精准匹配
如果必须仅使用Grok,可针对目标字段做精准匹配,跳过无关内容:
%{TIMESTAMP_ISO8601:[container][log][timestamp]} %{WORD:[container][log][stream]} %{WORD:[container][log][designator]} %{DATA}?"level":"%{DATA:SEVERITY}"%{DATA}?"requestId":"%{DATA:requestId}"%{DATA}
该模式会忽略level和requestId前后的任意内容,直接提取对应字段的值。
验证结果
使用方案1处理后,最终可得到:
SEVERITY: "info"requestId: "66x66x7b7951a5d9c609359146b3f435"
同时完整保留容器日志的元数据字段。
内容的提问来源于stack exchange,提问作者Reid
相关产品推荐
相关产品推荐

