Logstash Grok 概览(OverviewOfLogstashGrok)

  • 25th Oct 2018
  • 5 min read
  • Tags: 
  • Logstash
  • Updated on 8th Feb 2025

背景

Grok 插件让 Logstash 在处理一定格式的日志文件的时候有了一定程度“正则表达”的功能。 特别适用于解析一些非结构化的数据,并从中提取真正相关的信息至一些结构化 field 中。

主要的使用场景在 syslog、apache 与其他的 webserver 具有这样特点的日志:这些日志都具有易人读但不易机读的特点。

Logstash 默认有很多 patterns,你可以在 https://github.com/logstash-plugins/logstash-patterns-core/tree/master/patterns 找到。当然你也可以添加你自己的 pattern,这点我们稍后就会讲到。

测试你的 Grok pattern

Debug 是人类进步的阶梯,想起来当时被正则表达式支配的恐惧了么?那时我们有一些工具来测试我们的正则表达式是否足够“强壮”,grok 的作者也提供了两个网站,允许你通过这个来测试你的 grok 表达式,就跟你在测试正表达式的时候一样。分别是 http://grokdebug.herokuapp.com http://grokconstructor.appspot.com/

Grok 的一些基本设定

语法

Grok 使用如下的语法进行匹配操作。

%{SYNTAX:SEMANTIC}

其中 SYNTAX是你想匹配的表达式的名称,SEMANTIC 则是存储匹配后的文本的变量名,比如:

# 待匹配的文本为 192.168.1.1 2016-04-26T19:55:15Z # 一个完整的匹配式 %{IPV4:ip} %{TIMESTAMP_ISO8601:time} # pattern 为 IPV4 (?<![0-9])(?:(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2}))(?![0-9]) TIMESTAMP_ISO8601 %{YEAR}-%{MONTHNUM}-%{MONTHDAY}[T ]%{HOUR}:?%{MINUTE}(?::?%{SECOND})?%{ISO8601_TIMEZONE}?

那么 IPV4TIMESTAMP_ISO8601就是 SYNTAXiptime 就是 SEMANTIC。

一个实际的例子

一个 logstash 的配置文件,内容如下:

input { file { path => "/var/log/http.log" } } filter { grok { match => { "message" => "%{IP:client} %{WORD:method} %{URIPATHPARAM:request} %{NUMBER:bytes} %{NUMBER:duration}" } } }

运行后,这条 message 将会在 grok 过滤之后上报一条 event,内容如下:

client: 55.3.244.1 method: GET request: /index.html bytes: 15824 duration: 0.043

正则表达式库

Grok 使用了 oniguruma 的正则表达式,所以所有在该文档中出现的匹配语法都可以使用。

自定义 pattern

Grok 自带了一些常用的匹配规则,比如:IPV4、IPV6、YEAR等,但是当我们想要写一些自己的规则的时候,grok 也提供了支持,这里主要有两种方式:

第一种方式添加自定义 pattern

直接使用下面的 pattern 结构:

(?<field_name>the pattern here)

其中 field_name 可以理解为上文的 SEMANTIC,后面则跟的是实际的匹配表达式,比如这样:

(?<queue_id>[0-9A-F]{10,11})

第二种方式添加自定义 pattern

第二种方式就如同我们一开始使用的一样,在指定的 pattern 文件夹,添加即可比如:

# 在 ./pattern/postfix 添加 POSTFIX_QUEUEID [0-9A-F]{10,11}

在实际匹配的时候写入

%{POSTFIX_QUEUEID:queue_id}

使用的效果与第一种方式完全一致。

Logstash 的配置文件中可以指定 自定义 pattern 的位置,比如:

filter { grok { patterns_dir => ["./patterns"] match => { "message" => "%{SYSLOGBASE} %{POSTFIX_QUEUEID:queue_id}: %{GREEDYDATA:syslog_message}" } } }

就是读取当前目录下的 patterns 文件。

Grok 插件的一些配置项

如果需要定制化 Grok 插件的一些匹配配置

配置项名称匹配项类型是否必须
break_on_matchbooleanno
keep_empty_capturebooleanno
matchhashno
named_captures_onlybooleanno
overwritearrayno
pattern_definitionshashno
patterns_dirarrayno
patterns_files_globstringno
tag_on_failurearrayno
tag_on_timeoutstringno
timeout_millisnumberno

named_captures_only

默认值: true 意义:当该值为 true 时,只会从数据中捕获有 SEMANTIC 的信息,其他的匹配项不存储。

overwrite

默认值:[] 意义:这个属性允许你在输出匹配结果之前,重写该匹配结果中的一项或多项,比如:

# 原始数据 734742416494845952,Android,"In trade, military and EVERYTHING else, it will be AMERICA FIRST! This will quickly lead to our ultimate goal: MAKE AMERICA GREAT AGAIN!",2016-05-23T13:46:57Z # 配置文件 filter { grok { patterns_dir => ["/root/custom-patterns.txt"] match => { "message" => "%{ID:id},%{DEVICE:device},%{MESSAGE_BODY:message},%{TIMESTAMP_ISO8601:timestamp}" } } } # 结果1 没有overwrite选项 "message": [ "734742416494845952,Android,"In trade, military and EVERYTHING else, it will be AMERICA FIRST! This will quickly lead to our ultimate goal: MAKE AMERICA GREAT AGAIN!",2016-05-23T13:46:57Z" , ""In trade, military and EVERYTHING else, it will be AMERICA FIRST! This will quickly lead to our ultimate goal: MAKE AMERICA GREAT AGAIN!"" ], "host": "localhost", "@timestamp": "2018-10-21T01:09:04.089Z", "device": "Android", "id": "734742416494845952", "timestamp": "2016-05-23T13:46:57Z", "path": "/root/trump-test.csv", "@version": "1" # 结果2 设置overwrite选项 overwrite => ["message"] "message": "In trade, military and EVERYTHING else, it will be AMERICA FIRST! This will quickly lead to our ultimate goal: MAKE AMERICA GREAT AGAIN!", "host": "localhost", "@timestamp": "2018-10-21T01:09:04.089Z", "device": "Android", "id": "734742416494845952", "timestamp": "2016-05-23T13:46:57Z", "path": "/root/trump-test.csv", "@version": "1"

可以看到,原来的 message 属性存储的是原始的输入信息,增加了 overwrite 选项后,则由匹配到的 message 信息将其替换。

pattern_definitions

默认值:空 意义:可以再该项中,以键值对的方式输入 grok 表达式,也就是把patterns_dir 文件内的 pattern 写在这个属性里,比如:

pattern_definitions => { "ID" => "\d+(?=,)" "DEVICE" => "[a-zA-Z]+(?=,)" "MESSAGE_BODY" => ".+(?=,2)" }

timeout_millis

默认值:30000 意义:在执行了所定义的时间后,终止正则匹配,设置为0则没有超时时间。

add_tag

默认值:[] 意义:在匹配成功后,增加一个或多个 tag 字段

add_field

默认值:{} 意义:在匹配成功后,增加一个或多个 field、value对,例如:

# 输入 依然是上文中使用的例子 # Logstash 配置文件如下 filter { grok { pattern_definitions => { "ID" => "\d+(?=,)" "DEVICE" => "[a-zA-Z]+(?=,)" "MESSAGE_BODY" => ".+(?=,2)" } #patterns_dir => ["/root/custom-patterns.txt"] match => { "message" => "%{ID:id},%{DEVICE:device},%{MESSAGE_BODY:message},%{TIMESTAMP_ISO8601:timestamp}" } overwrite => ["message"] add_tag => [ "test_%{id}"] add_field => { "test_%{timestamp}" => "test" } remove_field => ["device"] } } # 结果如下 "host": "localhost", "timestamp": "2016-05-23T13:46:57Z", "id": "734742416494845952", "tags": [ "test_734742416494845952" ], "@version": "1", "@timestamp": "2018-10-21T01:47:31.552Z", "message": "In trade, military and EVERYTHING else, it will be AMERICA FIRST! This will quickly lead to our ultimate goal: MAKE AMERICA GREAT AGAIN!", "path": "/root/trump-test.csv", "test_2016-05-23T13:46:57Z": "test"

参考

grok manual