0、题记
本文建立在干货 | Logstash Grok数据结构化ETL实战上,并专注于在Grok中使用自定义正则表达式。

有时Logstash没有我们需要的模式。幸运的是,我们有正则表达式库:Oniguruma。

Oniguruma是一个灵活的正则表达式库。 它包含多种语言的不同正则表达式实现的特性。

Github地址:https://github.com/kkos/oniguruma

1、基础再认知
Logstash:一个服务器端数据处理管道,它同时从多个源中提取数据,对其进行转换,然后将其发送到Elasticsearch“存储”。

Grok:Logstash中的过滤器,用于将非结构化数据解析为结构化和可查询的数据。

正则表达式:定义搜索模式的字符序列。

如果已经运行了Logstash,则无需安装其他正则表达式库,因为“Grok位于正则表达式之上,因此任何正则表达式在grok中都有效” -

官方文档:https://www.elastic.co/guide/en/logstash/current/plugins-filters-grok.html

2、正则匹配模式分类解读
2.1 Grok
grok语法如下:

1%{SYNTAX:SEMANTIC}

Syntax: 默认的grok模式
Semantic: 是关键词。
这样写很枯燥,实践一把。

干货 | Logstash自定义正则表达式ETL实战_第1张图片
2.2 Oniguruma
oniguruma语法如下:

1(?the pattern here)

field_name:是关键词。
pattern :这里的模式是你放入正则表达式模式的地方。

2.3 Grok + Oniguruma
您可以将Grok和Oniguruma结合起来,如下所示:

1%{SYNTAX:SEMANTIC} (?the pattern here)

不好理解?不要担心,2.2和2.3的示例在下面的章节详细解读。

3、实践一把
3.1 样例数据
为了演示如何在Grok中使用Oniguruma,我们将使用下面的日志数据作为示例。

1production GET /v2/blacklist/ 200 24ms 5ba9e948801d34906b96e0c20 Panya/1.6.3 (com.sn.panya.host; build:1; iOS 10.3.3) Alamofire/4.66.0 {\"user_id\":\"5bd4c2f4569f470016bd8d55\",\"reason\":\"SPAMMER\"}

3.2 结构化日志数据
production == environment

GET == method

/v2/blacklist == url

200 == response_status

24ms == response_time

5bc6e716b5d6cb35fc9687c0 == user_id

Panya/1.6.3 (com.sn.panya.host; build:1; iOS 10.3.3) Alamofire/4.66.0 == user_agent

{\"user_id\":\"5bd4c2f4569f470016bd8d55\",\"reason\":\"SPAMMER\"} == req.body

3.3 非结构化转化为结构化目标
目标是找到一种模式来构建和解析非结构化日志数据。

为此,我们将使用Grok Debugger和RegExr。

Grok Debugger :https://grokdebug.herokuapp.com/

RegExr:https://regexr.com/

上面的模式产生了结果:

1{
2 "environment": [
3 [
4 "production"
5 ]
6 ],
7 "method": [
8 [
9 "GET"
10 ]
11 ],
12 "url": [
13 [
14 "/v2/blacklist/"
15 ]
16 ],
17 "response_status": [
18 [
19 "200"
20 ]
21 ],
22 "BASE10NUM": [
23 [
24 "200"
25 ]
26 ],
27 "response_time": [
28 [
29 "24ms"
30 ]
31 ],
32 "user_id": [
33 [
34 "5ba9e948801d34906b96e0c20"
35 ]
36 ]
37}

这并不完整。 user_agent和req.body没有映射。
要提取user_agent和req.body,我们需要仔细检查它的结构。

干货 | Logstash自定义正则表达式ETL实战_第2张图片
3.4 空白分隔符
1 GET /v2/blacklist/ 200 24ms 5ba9e948801d34906b96e0c20

由空格分隔,这很容易使用。

但是,对于user_agent,根据发送请求的硬件类型,可能存在动态数量的空格。

1Panya/1.6.3 (com.sn.panya.host; build:1; iOS 10.3.3) Alamofire/4.66.0

我们如何解释这种不断变化?

提示:看一下req.body的结构。

1{\”user_id\”:\”5bd4c2f4569f470016bd8d55\”,\”reason\”:\”SPAMMER\”}

我们可以看到req.body由大括号{}组成。

利用这些知识,我们可以构建一个自定义正则表达式模式,以查找第一个左括号内的所有内容,然后再抓取所有内容。

如下正则的含义是:匹配从开头到“{”的所有字符。

干货 | Logstash自定义正则表达式ETL实战

谷歌搜索“regex match everything until character” 找到解决问题的正则思路:
https://stackoverflow.com/questions/2013124/regex-matching-up-to-the-first-occurrence-of-a-character/2013150#2013150

后半部分组合后的正则如下:

1(?[^{]*) %{GREEDYDATA:body}

user_agent和req.body将被提取出来。

3.5 全部放在一起
将此应用于grok调试器中的自定义正则表达式模式,得到了我们想要的结果:

干货 | Logstash自定义正则表达式ETL实战_第3张图片
4、更新Logstash.conf验证
在您安装ELK堆栈的服务器上,导航到Logstash配置。

1sudo vi /etc/logstash/conf.d/logstash.conf

贴上正则部分内容:

1input {
2 file {
3 path => "/your_logs/.log"
4 }
5}
6filter{
7 grok {
8 match => { "message" => "%{WORD:environment} %{WORD:method} %{URIPATH:url} %{NUMBER:response_status} %{WORD:response_time} %{USERNAME:user_id} (?[^{]
) %{GREEDYDATA:body}"}
9 }
10}
11output {
12 elasticsearch {
13 hosts => [ "localhost:9200" ]
14 }
15}

保存更改后,重新启动Logstash并检查其状态以确保它仍然有效。

1sudo service logstash restart
2sudo service logstash status

最后,为了确保更改生效,请务必刷新Kibana中Logstash的Elasticsearch索引!

干货 | Logstash自定义正则表达式ETL实战_第4张图片
5、小结
Oniguruma + Grok 组合实现自定义解析规则。Logstash文本模式的灵活性和可定制性使其成为构建非结构化日志的理想选择(只要数据结构具有可预测性)。

尝试在Logstash中结合Oniguruma实现自定义解析,提升解析的细化粒度。