logstash之grok过滤

本文详细介绍了如何在生产环境中处理复杂格式的nginx日志,利用Logstash进行日志解析,并自定义正则表达式以适配不同日志字段。重点包括日志格式定义、正则表达式的编写与验证过程,以及如何在Logstash配置文件中整合这些正则以实现高效日志处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

  前面我们的nginx日志编码使用的json,logstash直接输入预定义好的 JSON 数据,这样就可以省略掉 filter/grok 配置,但是在我们的生产环境中,日志格式往往使用的是普通的格式,因此就不得不使用logstash的filter/grok进行过滤,下面我们就来讲下如何配置。

配置

1.nginx日志格式
为了帮助我们有效的理解grok的正则表达式,因此在这我们将日志格式定义的复杂一些,基本是各个使用的字段都涉及到了,google上好多都是套用的默认格式,我费好大劲才弄明白。

log_format main '$time_local - $upstream_addr $server_addr:$server_port '
                '$request_method $uri $args '
                '- $remote_addr $server_protocol [$http_user_agent] [$http_cookie] $http_referer '
                '$host $status 0 0 $bytes_sent $request_length 0'
                '"$upstream_cache_status" $request_time $upstream_response_time';

对应的日志如下:

08/Jan/2016:08:27:43 +0800 - 10.10.6.212:8088 10.10.6.110:80 GET /vvv/test/stat/index proptype=11&level=2&srtype=2&city=dz&region=XJ&begindate=2016-01-08&enddate=2016-01-08&apiKey=c2c959b203d669a9a21861379cb4523c&test=2 - 10.10.6.10 HTTP/1.1 [Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.99 Safari/537.36] [JSESSIONID=kq3v6xi2b74j1a9yxvfvcq131] http://10.10.6.110/test www.test.com 200 0 0 485 209 0"-" 1.642 1.642

2.编写正则表达式
logstash中默认存在一部分正则表达式来让我们套用,在如下的文件中我们可以看到:

ls /usr/local/logstash/vendor/bundle/jruby/1.9/gems/logstash-patterns-core-2.0.2/patterns
aws  bacula  bro  exim  firewalls  grok-patterns  haproxy  java  junos  linux-syslog  mcollective  mcollective-patterns  mongodb  nagios  postgresql  rails  redis  ruby

其中最基本的定义是在grok-patterns中,但是某些正则不适合我们的nginx字段,此时就需要我们来自定义,然后grok通过patterns_dir来调用即可。
另外,我们可以通过http://grokconstructor.appspot.com/do/matchhttp://grokdebug.herokuapp.com/这两个站点来查看我们的正则是否正确。(ps:个人觉得第一个好用)

下面我们来通过分解日志中的各个字段来一一对应下正则:

nginx日志字段定义nginx访问字段正则表达式
$time_local08/Jan/2016:08:27:43 +0800%{HTTPDATE:timestamp}
---
$upstream_addr10.10.6.212:8088%{HOSTPORT:upstream}
serveraddr: server_port10.10.6.110:80%{HOSTPORT:request_server}
$request_methodGET%{WORD:request_method}
$uri/vvv/test/stat/index%{URIPATH:uri}
$argsproptype=11&level=2&srtype=2&city=dz&region=XJ&begindate=2016-01-08&enddate=2016-01-08&apiKey=c2c959b203d669a9a21861379cb4523c&test=2%{URIPARAM1:args}
---
$remote_addr10.10.6.10%{IP:clientip}
$server_protocolHTTP/1.1HTTP/%{NUMBER:httpversion}
[$http_user_agent][Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.99 Safari/537.36]\ [%{GREEDYDATA:agent}\ ]
[$http_cookie][JSESSIONID=kq3v6xi2b74j1a9yxvfvcq131]\ [%{GREEDYDATA:cookie}\ ]
$http_refererhttp://10.10.6.110/test(?:%{URI:referrer}|-)
$hostwww.test.com%{HOSTNAME:domain}
$status200%{NUMBER:status:int}
000
000
$bytes_sent485%{NUMBER:body_sent:int}
$request_length209%{NUMBER:request_length:int}
0”$upstream_cache_status”0”-“0\”-\”
$request_time1.642%{NUMBER:request_time:float}
$upstream_response_time1.642%{NUMBER:response_time:float}

ok,我们nginx日志的所有字段都已经定义完毕,我们可以到http://grokconstructor.appspot.com/do/match看下是否有问题:

注意要点:
(1)上图中URIPARAM1 [A-Za-z0-9$.+!‘|(){},~@#%&/=:;_?-[]]是我们自定义的个一个正则,由%{URIPARAM1:args}调用,
它和默认正则库/usr/local/logstash/vendor/bundle/jruby/1.9/gems/logstash-patterns-core-2.0.2/patterns/grok-patterns中的URIPARAM \?[A-Za-z0-9$.+!‘|(){},~@#%&/=:;_?-[]<>]是不一样的,可以看到默认的URIPARAM是以?开头,我们自定义的URIPARAM1而不是,也可通过https://github.com/elastic/logstash/blob/v1.4.2/patterns/grok-patterns查看(这个规则是更新的,可能由于版本的问题和你使用的不一样),正是由于这点差别导致我们在使用默认正则会出现“Longest prefix that matches”的提示,“after matche”会显示日志中未匹配的剩余内容,如下图:

也就是说我们的匹配是异常的,一旦有这样的提示,就说明我们的正则有问题。

(2) httpuseragent http_cookie字段使用http://grokdebug.herokuapp.com/patterns#中“nginx-access”生成的规则“%{QS:agent}”以及类似“%{QS:cookie}”也会出现“Longest prefix that matches”提示,因此这两个正则是不正确的,我就使用了%{GREEDYDATA:agent}和%{GREEDYDATA:cookie},在/usr/local/logstash/vendor/bundle/jruby/1.9/gems/logstash-patterns-core-2.0.2/patterns/grok-patterns或https://github.com/elastic/logstash/blob/v1.4.2/patterns/grok-patterns我们可以查到“GREEDYDATA .*”,匹配的所有字符,注意和“QS %{QUOTEDSTRING}”的区别。
(3)?:%{URI:referrer}|-)正则表示如果$referer字段为空,则用-表示,若不为空则显示referer的内容,经测试如果直接设置成%{URI:referrer},过滤时当referer为空时,导致grokfailure,因此需要注意此字段的正则表达式。

某些字段为“-”,可能导致grokfailure,此时我们可以通过(?:%{XX:XX}|-)的方式进行匹配,即为空时显示“-”。

(4)可能你想知道所有的正则是如何定义的,我们可以查看https://github.com/kkos/oniguruma/blob/master/doc/RE

3.logstash调用
(1)在logstash中定义正则目录并定义规则

mkdir -p /usr/local/logstash/patterns
vim /usr/local/logstash/patterns/nginx
URIPARAM1 [A-Za-z0-9$.+!*'|(){},~@#%&/=:;_?\-\[\]]*
NGINXACCESS %{HTTPDATE:timestamp} - %{HOSTPORT:upstream} %{HOSTPORT:request_server} %{WORD:request_method} %{URIPATH:uri} %{URIPARAM1:args} - %{IP:clientip} HTTP/%{NUMBER:httpversion} \[%{GREEDYDATA:agent}\] \[%{GREEDYDATA:cookie}\] %{URI:referer} %{HOSTNAME:host} %{NUMBER:status:int} 0 0 %{NUMBER:body_sent:int} %{NUMBER:request_length:int} 0\"-\" %{NUMBER:request_time:float} %{NUMBER:response_time:float}

其中URIPARAM1是我们自定义的部分,而NGINXACCESS也是我们自定的正则,其中又调用了URIPARAM1。

注意:若以上的日志如下

08/Jan/2016:08:27:43 +0800 - 10.10.6.212:8088 10.10.6.110:80 GET /vvv/test/stat/index proptype=11&level=2&srtype=2&city=dz&region=XJ&begindate=2016-01-08&enddate=2016-01-08&apiKey=c2c959b203d669a9a21861379cb4523c&test=2 - 10.10.6.10 HTTP/1.1 [Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.99 Safari/537.36] [JSESSIONID=kq3v6xi2b74j1a9yxvfvcq131] www.test.cn www.test.com 200 0 0 485 209 0"-" 1.642 1.642

其中referrer字段为”www.test.cn”,以上匹配可能出现问题,因为我们这个字段的匹配规则为”(?:%{URI:referrer}|-)”,其中”URI”规则为”%{URIPROTO}://(?:%{USER}(?::[^@]*)?@)?(?:%{URIHOST})?(?:%{URIPATHPARAM})?”,因此我们需要在/usr/local/logstash/patterns/nginx中添加REFER如下:

URIPARAM1 [A-Za-z0-9$.+!*'|(){},~@#%&/=:;_?\-\[\]]*
REFER (?:%{HOSTNAME}|%{URI})

NGINXACCESS %{HTTPDATE:timestamp} - (?:%{HOSTPORT:upstream}|-) %{HOSTPORT:request_server} %{WORD:request_method} %{URIPATH:uri} %{URIPARAM1:args} - %{IP:clientip} HTTP/%{NUMBER:httpversion} \[%{GREEDYDATA:agent}\] \[%{GREEDYDATA:cookie}\] (?:%{REFER:referrer}|-) %{HOSTNAME:domain} %{NUMBER:status:int} 0 0 %{NUMBER:body_sent:int} %{NUMBER:request_length:int} 0\"(?:%{WORD:cache_status}|-)\"

至此可以匹配了。
(2)配置文件logstash.conf

input {
        file {
                path => "/data/nginx/logs/api.creprice.log"
                type => "nginx-access"
                start_position => "beginning"
                sincedb_path => "/usr/local/logstash/sincedb"
        }
}
filter {
        if [type] == "nginx-access" {
                grok {
                        patterns_dir => "/usr/local/logstash/patterns"
                        match => {
                                "message" => "%{NGINXACCESS}"
                        }
                }
                date {
                        match => [ "timestamp" , "dd/MMM/YYYY:HH:mm:ss Z" ]
                        }
        }
}
output {
        if [type] == "nginx-access" {
                elasticsearch {
                        hosts => ["10.10.10.16:9200"]
                        manage_template => true
                        index => "logstash-nginx-access-%{+YYYY-MM}"
                }
        }

}

其中:patterns_dir定义的是我们自定义的正则存放目录

(3)重启logstash,查看kibana,我们的字段就显示出来了,如果我们的字段前面是?,请刷新下我们的“Setting”——“indices”——“Index Patterns”——“logstash-nginx-access-%{+YYYY-MM}”即可。

总结

通过上面对正则的了解,即使是在复杂的日志,我们只要对应规则也可以一一解开,下面的工作就是让我们应用到生产环境吧。

Grok过滤器是Logstash中一种用于解析和匹配日志消息的工具。它使用正则表达式来匹配文本模式,并将匹配的值存储在新字段中。然而,当模式不匹配时,Grok过滤器可能会遇到性能问题。为了解决这个问题,可以考虑改用基于分隔符的Dissect过滤器,它比基于正则表达式的过滤器更容易编写和使用。不幸的是,目前还没有针对此的应用程序。要使用Grok过滤器,可以在配置文件中指定字段名称和匹配模式,如: ``` filter { grok { match => [ "message", "%{USERNAME:user}" ] } } ``` 这将从"message"字段中提取匹配的用户名,并将其存储在新的"user"字段中。另一方面,如果想在Logstash中改变应用程序的日志记录模式,可能会增加直接日志读取的困难。在这种情况下,可以考虑使用Logstash的Dissect过滤器,并进行相应的配置。一个可能的配置示例如下: ``` filter { dissect { mapping => { "message" => ... } } mutate { strip => [ "log", "class" ] } } ``` 这个配置将使用Dissect过滤器根据指定的映射将日志消息拆分成多个字段,并通过mutate过滤器删除不需要的字段,例如"log"和"class"。综上所述,Grok过滤器是Logstash中用于解析和匹配日志消息的一种工具,而Dissect过滤器则是一种更简单易用的基于分隔符的过滤器。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Logstash:如何使用 Logstash Grok 过滤器提取模式](https://blog.youkuaiyun.com/UbuntuTouch/article/details/107512971)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值