内容简介:Grok是Logstash最重要的插件, 可以将非结构化日志数据解析为结构化和可查询的内容.此工具非常适用于syslog日志, apache和其他Web服务器日志, mysql日志, 以及通常为人类而非计算机使用而编写的任何日志格式.SYNTAX是文本要匹配的”patterns”(翻译为”模式”, 但我觉得翻译成”类型”更恰当)
Grok是Logstash最重要的插件, 可以将非结构化日志数据解析为结构化和可查询的内容.
此 工具 非常适用于syslog日志, apache和其他Web服务器日志, mysql日志, 以及通常为人类而非计算机使用而编写的任何日志格式.
grok的语法
%{SYNTAX:SEMANTIC}
SYNTAX是文本要匹配的”patterns”(翻译为”模式”, 但我觉得翻译成”类型”更恰当)
SEMANTIC是匹配到的文标识(字段), 默认是以字符串的方式保存
翻译成中文就是
%{模式:字段}
假设有以下日志片断
55.3.244.1 GET /index.html 15824 0.043
通过分析, 第一段可能是一个IP, 第二段可能是一个HTTP的请求方法, 第三段可能是请求的页面, 等等, 所以grok的过滤表达式可以写为
%{IP:client} %{WORD:method} %{URIPATHPARAM:request} %{NUMBER:bytes} %{NUMBER:duration}
经过grok过滤器处理以后, 该日志片断将被解析成以下字段
client: 55.3.244.1 method: GET request: /index.html bytes: 15824 duration: 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 { #something here. }
Logstash默认提供约120种常见文本”模式”( 参考这里 ), 例如: NUMBER, IP, USERNAME, EMAILADDRESS, INT, UUID, MAC, PATH, TIMESTAMP, DATE, WORD, HOSTNAME, 等
我一直好奇, 为什么要把SYNTAX翻译成”模式”, 而不翻译成”类型”(因为一些常见的”模式”都是一种”类型”啊), 那是因为, “模式”并不仅仅是一种”类型”, 更有可能是多个”类型”的组合 , 例如以下都是”模式”的定义
USERNAME [a-zA-Z0-9._-]+ USER %{USERNAME} EMAILLOCALPART [a-zA-Z][a-zA-Z0-9_.+-=:]+ EMAILADDRESS %{EMAILLOCALPART}@%{HOSTNAME} INT (?:[+-]?(?:[0-9]+)) NUMBER (?:%{BASE10NUM}) 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}) HOSTNAME \b(?:[0-9A-Za-z][0-9A-Za-z-]{0,62})(?:\.(?:[0-9A-Za-z][0-9A-Za-z-]{0,62}))*(\.?|\b) IPORHOST (?:%{IP}|%{HOSTNAME}) HOSTPORT %{IPORHOST}:%{POSINT} PATH (?:%{UNIXPATH}|%{WINPATH}) UNIXPATH (/([\w_%!$@:.,+~-]+|\\.)*)+ TTY (?:/dev/(pts|tty([pq])?)(\w+)?/?(?:[0-9]+)) WINPATH (?>[A-Za-z]+:|\\)(?:\\[^\\?*]*)+ URIPROTO [A-Za-z]([A-Za-z0-9+\-.]+)+ URIHOST %{IPORHOST}(?::%{POSINT:port})? URIPATH (?:/[A-Za-z0-9$.+!*'(){},~:;=@#%&_\-]*)+ URIPARAM \?[A-Za-z0-9$.+!*'|(){},~@#%&/=:;_?\-\[\]<>]* URIPATHPARAM %{URIPATH}(?:%{URIPARAM})? URI %{URIPROTO}://(?:%{USER}(?::[^@]*)?@)?(?:%{URIHOST})?(?:%{URIPATHPARAM})? # Shortcuts QS %{QUOTEDSTRING} SYSLOGPROG %{PROG:program}(?:\[%{POSINT:pid}\])? SYSLOGHOST %{IPORHOST} SYSLOGFACILITY <%{NONNEGINT:facility}.%{NONNEGINT:priority}> # Log formats SYSLOGBASE %{SYSLOGTIMESTAMP:timestamp} (?:%{SYSLOGFACILITY} )?%{SYSLOGHOST:logsource} %{SYSLOGPROG}: # HTTPD Log formats HTTPD_COMMONLOG %{IPORHOST:clientip} %{HTTPDUSER:ident} %{HTTPDUSER:auth} \[%{HTTPDATE:timestamp}\] "(?:%{WORD:verb} %{NOTSPACE:request}(?: HTTP/%{NUMBER:httpversion})?|%{DATA:rawrequest})" %{NUMBER:response} (?:%{NUMBER:bytes}|-) HTTPD_COMBINEDLOG %{HTTPD_COMMONLOG} %{QS:referrer} %{QS:agent} # HTTPD Error logs HTTPD20_ERRORLOG \[%{HTTPDERROR_DATE:timestamp}\] \[%{LOGLEVEL:loglevel}\] (?:\[client %{IPORHOST:clientip}\] ){0,1}%{GREEDYDATA:message} HTTPD24_ERRORLOG \[%{HTTPDERROR_DATE:timestamp}\] \[%{WORD:module}:%{LOGLEVEL:loglevel}\] \[pid %{POSINT:pid}(:tid %{NUMBER:tid})?\]( \(%{POSINT:proxy_errorcode}\)%{DATA:proxy_message}:)?( \[client %{IPORHOST:clientip}:%{POSINT:clientport}\])?( %{DATA:errorcode}:)? %{GREEDYDATA:message} HTTPD_ERRORLOG %{HTTPD20_ERRORLOG}|%{HTTPD24_ERRORLOG}
示例: Grok添加自定义模式
这里我们自定义一个10-11位文本的模式”POSTFIX_QUEUEID”
$ cat ./patterns/postfix POSTFIX_QUEUEID [0-9A-F]{10,11}
接下来我们来解析以下日志
Jan 1 06:25:43 mailserver14 postfix/cleanup[21403]: BEF25A72965: message-id=<20130101142543.5828399CCAF@mailserver14.example.com>
Grok的写法为
filter { grok { patterns_dir => ["./patterns"] match => { "message" => "%{SYSLOGBASE} %{POSTFIX_QUEUEID:queue_id}: %{GREEDYDATA:syslog_message}" } } }
经过grok过滤器处理以后, 该日志片断将被解析成以下字段
timestamp: Jan 1 06:25:43 logsource: mailserver14 program: postfix/cleanup pid: 21403 queue_id: BEF25A72965 syslog_message: message-id=<20130101142543.5828399CCAF@mailserver14.example.com>
请注意: SYSLOGBASE是一个包括了多种”模式”的模式, 因此里面的字段是固定的, 例如logsource, program, pid
示例: Grok自带方法
Grok过滤器自带了一些配置选项, 下面随机演示一个
filter { grok { match => { "message" => "%{IPORHOST:remote_ip} - %{DATA:user_name} \[%{HTTPDATE:access_time}\] \"%{WORD:http_method} %{DATA:url} HTTP/%{NUMBER:http_version}\" %{NUMBER:response_code} %{NUMBER:body_sent_bytes} \"%{DATA:referrer}\" \"%{DATA:agent}\"" } remove_field => "message" } }
remove_field这个方法, 顾名思义, 是将整个日志条目移除. 为什么要移除? 因为 在上面已经通过match方法获得了remote_ip/access_time/http_method/http_version/response_code等字段信息, 整条日志已经没有意义了, 所以这里可以remove之.
其它的一些Grok过滤器自带的配置选项, 可以参考官网的 这篇文章 .
其它有用内容
1, Grok Debugger 这个网站, 除了可以帮你测试写出的模式是否可以正确解析日志以外, 还提供了一些Grok其它的”模式”. 例如, Grok自带的”模式”里, 有Apache的”模式”, 却没有nginx的”模式”, 其实nginx的”模式”可以在 这里 找到.
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。