title: logstash过滤插件——grok #标题tags: grok #标签
date: 2020-05-14
categories: elastic stack # 分类
grok简单使用示例
示例日志如下:
$ cat /var/log/http.log
55.3.244.1 GET /index.html 15824 0.043
logstash配置如下:
input {
file {
path => "/var/log/http.log"
}
}
filter {
grok {
match => { "message" => "%{IP:client} %{WORD:method} %{URIPATHPARAM:request} %{NUMBER:bytes} %{NUMBER:duration}" }
}
}
output {
stdout {
codec => rubydebug
}
}
在经过grok过滤器后,日志中的消息应该会多出以下几个字段:
- client: 55.3.244.1
- method: GET
- request: /index.html
- bytes: 15824
- duration: 0.043
输出如下:
{
"path" => "/var/log/http.log",
"request" => "/index.html", # uri也匹配到了
"bytes" => "15824", # 字节数也匹配到了
"host" => "es2",
"duration" => "0.043", # 时长也匹配到了
"method" => "GET", # method也匹配到了
"@version" => "1",
"client" => "55.3.244.1", # 第一个ip匹配到了
"message" => "55.3.244.1 GET /index.html 15824 0.043",
"@timestamp" => 2020-05-13T14:39:34.533Z
}
而当我将grok字段注释掉后,则输出如下:
{
"@timestamp" => 2020-05-13T14:47:31.989Z,
"path" => "/var/log/http.log",
"message" => "55.3.244.1 GET /index.html 15824 0.043",
"host" => "es2",
"@version" => "1"
}
grok提供的常用patterns说明
grok提供100多个常用正则表达式可供使用,这100多个正则表达式定义在logstash/vendor/bundle/jruby/x.x/gems/logstash-patterns-core-xxx/patterns/grok-patterns文件中(同时也托管在Github上),想要灵活的匹配各种数据,那么必须查看该文件,大概了解grok提供了什么内置的正则表达式。调用它们的语法如下:%{SYNTAX:SEMANTIC}
- SYNTAX:表示内置的正则表达式名称
- SEMANTIC:表示在事件中创建该字段名来存储匹配到的值。
例如:输出的数据内容为“[debug] 127.0.0.1 - test log content”,我们想提取127.0.0.1这个IP地址,那么可以使用以下语法来匹配:%{IP:client},将获得“client: 127.0.0.1”的结果,该结果将成为Event的一个新的字段和字段值;如果你在捕获数据时想进行数据类型转换可以使用%{NUMBER:num:int}这种语法,默认情况下,所有的返回结果都是string类型,当前Logstash所支持的转换类型仅有“int”和“float”;
示例:
# 假设要提取的日志如下:
/index.html GET 114.114.12.166 15824 0.043
# 我要提取其uri、method、ip这三段,则grok对应的语法为:
filter {
grok {
match => {"message" => "%{URIPATHPARAM:request} %{WORD:method} %{IP:myip}"}
}
}
根据上面定义的语法,则捕获到的消息如下:
{
"message" => "/index.html GET 114.114.12.166 15824 0.043",
"host" => "es2",
"path" => "/var/log/http.log",
"@version" => "1",
"request" => "/index.html",
"@timestamp" => 2020-05-13T23:50:38.940Z,
"method" => "GET",
"myip" => "114.114.12.166"
}
# 比默认增加了myip、method、request这三个字段。
grok常用自带表达式
常见字段
USERNAME或USER
正则:
USERNAME [a-zA-Z0-9._-]+
USER %{USERNAME}
作用:
匹配用户名,由数字、大小写及特殊字符(._-)组成的字符串,比如:1234
、Bob
、Alex.Wong
等.
EMAILLOCALPART
正则:
EMAILLOCALPART [a-zA-Z][a-zA-Z0-9_.+-=:]+
作用:
电子邮件用户名部分,首位由大小写字母组成,其他位由数字、大小写及特殊字符(_.+-=:)组成的字符串。注意,国内的QQ纯数字邮箱账号是无法匹配的,需要修改正则。可以匹配:stone
、Gary_Lu
、abc-123
等字符。
EMAILADDRESS
正则:
EMAILADDRESS %{EMAILLOCALPART}@%{HOSTNAME}
作用:
匹配电子邮件(同样无法匹配以数字开头的邮箱,需要修改EMAILLOCALPART的正则即可)可以匹配:stone@abc.com
、Gary_Lu@gmail.com
、abc-123@163.com
等
INT
正则:
INT (?:[+-]?(?:[0-9]+))
作用:
整数,包括0和正负整数,比如:0
、-123
、43987
等。
BASE10NUM及NUMBER
正则
BASE10NUM (?<![0-9.+-])(?>[+-]?(?:(?:[0-9]+(?:\.[0-9]+)?)|(?:\.[0-9]+)))
NUMBER (?:%{BASE10NUM})
作用
十进制数字,包括整数和小数。比如:0
、-123
、43987
等。
BASE16NUM
正则
BASE16NUM (?<![0-9A-Fa-f])(?:[+-]?(?:0x)?(?:[0-9A-Fa-f]+))
作用
匹配十六进制数字,整数。比如:0x0045fa2d
、-0x3F8709
等。
BASE16FLOAT
正则
BASE16FLOAT \b(?<![0-9A-Fa-f.])(?:[+-]?(?:0x)?(?:(?:[0-9A-Fa-f]+(?:\.[0-9A-Fa-f]*)?)|(?:\.[0-9A-Fa-f]+)))\b
作用
十六进制数字,整数和小数
WORD
正则:
WORD \b\w+\b
作用
匹配字符串,包括数字和大小写字母。比如:String
、3529345
、ILoveYou
等。
NOTSPACE
正则
NOTSPACE \S+
作用
不带任何空格的字符串。
SPACE
正则
SPACE \s*
作用
空格字符串。
DATA
正则
DATA .*?
作用
. 表示除\n之外的任意字符,表示匹配前面的表达式任意次,例如,zo能匹配“z”,也能匹配“zo”以及“zoo”。*等价于o{0,},z后面匹配0~任意多个o。?匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配“do”或“does”中的“do”。?等价于{0,1}。
GREEDYDATA
正则
GREEDYDATA .*
作用
如果DATA无法匹配,可以尝试使用这个,或许会有意外之喜。
QUOTEDSTRING
正则
QUOTEDSTRING (?>(?<!\\)(?>"(?>\\.|[^\\"]+)+"|""|(?>'(?>\\.|[^\\']+)+')|''|(?>`(?>\\.|[^\\`]+)+`)|``))
作用
带引号的字符串。如:"This is an apple"
、'What is your name?'
等
UUID
正则
UUID [A-Fa-f0-9]{8}-(?:[A-Fa-f0-9]{4}-){3}[A-Fa-f0-9]{12}
作用
标准UUID。比如:550E8400-E29B-11D4-A716-446655440000
网络相关
MAC
正则
MAC (?:%{CISCOMAC}|%{WINDOWSMAC}|%{COMMONMAC})
作用
MAC地址,可以是Cisco设备里的MAC地址,也可以是通用或者Windows系统的MAC地址以及通用得mac地址格式。
CISCOMAC
正则
CISCOMAC (?:(?:[A-Fa-f0-9]{4}\.){2}[A-Fa-f0-9]{4})
作用
用于匹配cisco设备的mac地址。
WINDOWSMAC
正则
WINDOWSMAC (?:(?:[A-Fa-f0-9]{2}-){5}[A-Fa-f0-9]{2})
用途
用于匹配windows的mac地址。
COMMONMAC
正则
COMMONMAC (?:(?:[A-Fa-f0-9]{2}:){5}[A-Fa-f0-9]{2})
用途
用于匹配通用的mac地址。
IPV6、IPV4、IP
正则
IPV6 ((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?
IPV4 (?<![0-9])(?:(?:[0-1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5])[.](?:[0-1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5])[.](?:[0-1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5])[.](?:[0-1]?[0-9]{1,2}|2[0-4][0-9]|25[0-5]))(?![0-9])
IP (?:%{IPV6}|%{IPV4})
用途
IPV6用于匹配IPV6地址,IPV4用于匹配IPV4地址,IP则两者都匹配。
HOSTNAME
正则
HOSTNAME \b(?:[0-9A-Za-z][0-9A-Za-z-]{0,62})(?:\.(?:[0-9A-Za-z][0-9A-Za-z-]{0,62}))*(\.?|\b)
用途
用于匹配主机名称。
IPORHOST
正则
IPORHOST (?:%{IP}|%{HOSTNAME})
用途
用于匹配ip或主机名称。
HOSTPORT
HOSTPORT %{IPORHOST}:%{POSINT}
作用
用于匹配主机名(IP)+端口,比如:127.0.0.1:3306
、api.stozen.net:8000
等
路径相关
PATH
正则
PATH (?:%{UNIXPATH}|%{WINPATH})
用途
用于匹配路径,unix系统或windows系统里的路径都可以匹配。比如:/usr/local/nginx/sbin/nginx
、c:\windows\system32\clr.exe
等
UNIXPATH
正则
UNIXPATH (/([\w_%!$@:.,+~-]+|\\.)*)+
作用
匹配unix系统中的路径。
WINPATH
正则
WINPATH (?>[A-Za-z]+:|\\)(?:\\[^\\?*]*)+
用于匹配windows中的路径。
TTY
正则
TTY (?:/dev/(pts|tty([pq])?)(\w+)?/?(?:[0-9]+))
作用
URIPROTO
正则
URIPROTO [A-Za-z]([A-Za-z0-9+\-.]+)+
用途
URI协议,如:http
、ftp
等。
URIHOST
正则
URIHOST %{IPORHOST}(?::%{POSINT:port})?
用途
URI主机,比如:www.stozen.net
、10.0.0.1:22
等。
URIPATH
正则
URIPATH (?:/[A-Za-z0-9$.+!*'(){},~:;=@#%&_\-]*)+
用途
URI路径,比如://www.stozen.net/abc/
、/api.php
等。
URIPARAM
正则
URIPARAM \?[A-Za-z0-9$.+!*'|(){},~@#%&/=:;_?\-\[\]<>]*
URI里的GET参数,如:?a=1&b=2&c=3
。
URIPATHPARAM
正则
URIPATHPARAM %{URIPATH}(?:%{URIPARAM})?
作用
URI路径+GET参数,比如://www.stozen.net/abc/api.php?a=1&b=2&c=3
。
URI
正则
URI %{URIPROTO}://(?:%{USER}(?::[^@]*)?@)?(?:%{URIHOST})?(?:%{URIPATHPARAM})?
作用
完整的URI,如:http://www.stozen.net/abc/api.php?a=1&b=2&c=3
时间日期相关
MONTH
正则
MONTH \b(?:[Jj]an(?:uary|uar)?|[Ff]eb(?:ruary|z)?|[Aa]pr(?:il)?|[Mm]a(?:y|i)?|[Jj]un(?:e|i)?|[Jj]ul(?:y)?|[Aa]ug(?:ust)?|[Ss]ep(?:tember)?|[Oo](?:c|k)?t(?:ober)?|[Nn]ov(?:ember)?|[Dd]e(?:c|z)(?:ember)?)\b
作用
月份名称,如:Jan
、January
等。
MONTHNUM
正则
MONTHNUM (?:0?[1-9]|1[0-2])
用途
月份数字,比如:03
、9
、12
等。
对于MONTHNUM,还有一个差不多类似的MONTHNUM2,其正则如下:
MONTHNUM2 (?:0[1-9]|1[0-2])
MONTHDAY
正则:
MONTHDAY (?:(?:0[1-9])|(?:[12][0-9])|(?:3[01])|[1-9])
作用:
日期数字,如:03
、9
、31
等。
DAY
正则:
DAY (?:Mon(?:day)?|Tue(?:sday)?|Wed(?:nesday)?|Thu(?:rsday)?|Fri(?:day)?|Sat(?:urday)?|Sun(?:day)?)
作用:
星期几名称,如:Mon
、Monday
等。
YEAR
正则:
YEAR (?>\d\d){1,2}
作用:
年份数字。
HOUR
正则:
HOUR (?:2[0123]|[01]?[0-9])
作用:
小时数字。
MINUTE
正则:
MINUTE (?:[0-5][0-9])
作用:
分钟数字。
SECOND
正则:
SECOND (?:(?:[0-5]?[0-9]|60)(?:[:.,][0-9]+)?)
作用:
秒数字。
TIME
正则:
TIME (?!<[0-9])%{HOUR}:%{MINUTE}(?::%{SECOND})(?![0-9])
作用:
时间,如:00:01:23
。
DATE_US
正则:
DATE_US %{MONTHNUM}[/-]%{MONTHDAY}[/-]%{YEAR}
作用:
美国日期格式,如:10-15-1982
、10/15/1982
等。
DATE_EU
正则:
DATE_EU %{MONTHDAY}[./-]%{MONTHNUM}[./-]%{YEAR}
作用:
欧洲日期格式,如:15-10-1982
、15/10/1982
、15.10.1982
等。
ISO8601_TIMEZONE
正则:
ISO8601_TIMEZONE (?:Z|[+-]%{HOUR}(?::?%{MINUTE}))
作用:
ISO8601时间格式,如:+10:23
、-1023
等。
TIMESTAMP_ISO8601
正则:
TIMESTAMP_ISO8601 %{YEAR}-%{MONTHNUM}-%{MONTHDAY}[T ]%{HOUR}:?%{MINUTE}(?::?%{SECOND})?%{ISO8601_TIMEZONE}?
作用:
ISO8601时间戳格式,如:2016-07-03T00:34:06+08:00
。
DATE
正则:
DATE %{DATE_US}|%{DATE_EU}
作用:
日期,美国日期%{DATE_US}
或者欧洲日期%{DATE_EU}
。
DATESTAMP
正则:
DATESTAMP %{DATE}[- ]%{TIME}
作用:
完整日期+时间,如:07-03-2016 00:34:06
。
HTTPDATE
正则:
HTTPDATE %{MONTHDAY}/%{MONTH}/%{YEAR}:%{TIME} %{INT}
作用:
http默认日期格式,如:03/Jul/2016:00:36:53 +0800
。
Log相关
SYSLOGTIMESTAMP
正则:
SYSLOGTIMESTAMP %{MONTH} +%{MONTHDAY} %{TIME}
作用:
如:Jan 03 00:01:23
。
logLEVEL
正则:
LOGLEVEL ([Aa]lert|ALERT|[Tt]race|TRACE|[Dd]ebug|DEBUG|[Nn]otice|NOTICE|[Ii]nfo|INFO|[Ww]arn?(?:ing)?|WARN?(?:ING)?|[Ee]rr?(?:or)?|ERR?(?:OR)?|[Cc]rit?(?:ical)?|CRIT?(?:ICAL)?|[Ff]atal|FATAL|[Ss]evere|SEVERE|EMERG(?:ENCY)?|[Ee]merg(?:ency)?)
作用:日志等级,如:Alert
、alert
、ALERT
、Error
等。
创建自己的grok表达式
在业务中,可能logstash自带的正则表达式并不能很好的满足我们,如:用户身份证号、手机号信息等。所以,手动编写这些正则表达式也是不可能避免的。我这里编写了几个,如下:
表达式 | 正则表达式 | 说明 |
---|---|---|
DATE_CHS | %{YEAR}[./-]%{MONTHNUM}[./-]%{MONTHDAY} | 中国人习惯的日期格式 |
ZIPCODE_CHS | [1-9]\d{5} | 国内邮政编码 |
GAME_ACCOUNT | [a-zA-Z][a-zA-Z0-9_]{4,15} | 游戏账号,首字符为字母,4-15位字母、数字、下划线组成 |
NOSQUARE | [^[]]+ | 非方括号 |
调试grok正则语法工具
网上也看到过一些在线测试语法的工具,比如:grok debugger,但是体验并不好,个人更喜欢使用kibana带的grok语法调试工具,使用方法如下:
匹配nignx日志示例
示例1
日志数据如下:
10.252.201.136 - - [27/Apr/2020:00:00:01 +0800] "POST /api-stkp/callback HTTP/1.1 200 221" "//192.168.20.4:5601/app/kibana#/dev_tools/grokdebugger?_g=()" "Java/1.8.0_77"
定义的gork规则如下:
%{IP:client} - (%{WORD:remote_user}|-) \[%{HTTPDATE:http_date}\] \"%{WORD:method} %{URIPATHPARAM:url} %{NOTSPACE:http_version} %{NUMBER:status:int} %{NUMBER:body_bytes:int}\" "(%{URIPATHPARAM:http_refere}|-)" \"%{NOTSPACE:http_x_forwarded_for}\"
对数据进行结构化处理后如下:
{
"method": "POST",
"body_bytes": 221,
"http_version": "HTTP/1.1",
"url": "/api-stkp/callback",
"http_refere": "//192.168.20.4:5601/app/kibana#/dev_tools/grokdebugger?_g=()",
"http_date": "27/Apr/2020:00:00:01 +0800",
"http_x_forwarded_for": "Java/1.8.0_77",
"client": "10.252.201.136",
"status": 200
}
示例2
日志格式如下:
211.136.64.35 - zhangsan [27/Apr/2020:00:00:10 +0800] "GET /XCcorpinter/marketingAcr=19808970412&sign=0f0f839de3f016ffec9b64fd1185a15e&t%3FcBSign%3D18422020042700000949405153e5a87f HTTP/1.0" 200 31 "-" "Java/1.8.0_191"
定义grok规则如下:
%{IP:client} - (%{WORD:remote_user}|-) \[%{HTTPDATE:http_date}\] \"%{WORD:method} %{URIPATHPARAM:url} %{NOTSPACE:http_version}\" %{NUMBER:status:int} %{NUMBER:body_bytes:int} "(%{URIPATHPARAM:http_refere}|-)" \"%{NOTSPACE:http_x_forwarded_for}\"
对数据进行结构化处理后如下:
{
"method": "GET",
"body_bytes": 31,
"http_version": "HTTP/1.0",
"url": "/XCcorpinter/marketingAcr=19808970412&sign=0f0f839de3f016ffec9b64fd1185a15e&t%3FcBSign%3D18422020042700000949405153e5a87f",
"remote_user": "zhangsan",
"http_date": "27/Apr/2020:00:00:10 +0800",
"http_x_forwarded_for": "Java/1.8.0_191",
"client": "211.136.64.35",
"status": 200
}