一、背景
我们的应用程序通常每天都会产生非常多的日志,这些日志大多都是一个字符串的格式,那么我们如果想从中提取一些有用的信息(比如
:请求的时间、日志的级别等),那么应该如果实现呢?
二、解决思路
针对以上的问题,我们可以通过正则表达式
来匹配我们的日志内容,从而达到提取到有用的数据。而 logstash
的grok
正好可以帮助我们做到这种事。
三、前置知识
grok
插件为我们提供了大概120
种可用的模式。可以简单理解,grok
提供好了120种定义好的可用这则。- 比如:
INT
对应的正则(?:[+-]?(?:[0-9]+))
表示 正负数字。 grok
提供好的可用模式。 https://github.com/logstash-plugins/logstash-patterns-core/tree/master/patterns
- 比如:
grok语法的格式
%{SYNTAX:SEMANTIC}
SYNTAX
表示需要匹配文本的格式。比如: 文本内容:123
可以被INT
匹配到。SEMANTIC
表示 SYNTAX 匹配到文本后,将内容保存到那个字段中。比如:%{INT:age} 则匹配到后的age字段有值。
自定义
grok
模式(custom patterns)- 语法格式:
(?<field_name>the pattern here)
- 比如: (?<userName>[a-zA-Z]{3,5}) 用户名只能是 3到5位的字母
- 语法格式:
grok调试网站
- 可以在此网站调试我们的grok表达式是否编写正确 http://grokdebug.herokuapp.com/
grok解析失败和超时会增加如下标签
解析失败
,会在生成数据中的tags
中介增加_grokparsefailure
标签解析超时
,会在生成数据中的tags
中增加_groktimeout
标签
四、实现步骤
1、准备测试数据
[9708] 2021-05-13 11:14:51.873 [http-nio-8080-exec-1] INFO org.springframework.web.servlet.DispatcherServlet#initServletBean:547 -Completed initialization in 1 ms
[9708] 2021-05-13 11:14:51.910 [http-nio-8080-exec-1] ERROR com.huan.study.LogController#showLog:32 -请求:[/showLog]发生了异常
java.lang.ArithmeticException: / by zero
at com.huan.study.LogController.showLog(LogController.java:30)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
2、编写grok
表达式
(?m)^\[%{INT:pid}\]%{SPACE}%{TIMESTAMP_ISO8601:createTime}%{SPACE}\[%{DATA:threadName}\]%{SPACE}%{LOGLEVEL:LEVEL}%{SPACE}%{JAVACLASS:javaClass}#(?<methodName>[a-zA-Z_]+):%{INT:linenumber}%{SPACE}-%{GREEDYDATA:msg}
注意⚠️:
1、如果要匹配多行文本,比如java中的异常堆栈,则在表达式前需要加上(?m)
。
2、使用\
可以进行转义。
3、其中的(?<methodName>[a-zA-Z_]+)
methodName 为我们自定义的正则。
3、编写 logstash pipeline文件
input {
file {
id => "mutate-id"
path => ["/Users/huan/soft/elastic-stack/logstash/logstash/pipeline.conf/filter-grok/*.log"]
start_position => "beginning"
sincedb_path => "/Users/huan/soft/elastic-stack/logstash/logstash/pipeline.conf/filter-grok/sincedb.db"
codec => multiline {
pattern => "^\[+"
negate => "true"
what => "previous"
charset => "UTF-8"
auto_flush_interval => 2
}
}
}
filter {
grok {
match => {
"message" => "(?m)^\[%{INT:pid}\]%{SPACE}%{TIMESTAMP_ISO8601:createTime}%{SPACE}\[%{DATA:threadName}\]%{SPACE}%{LOGLEVEL:LEVEL}%{SPACE}%{JAVACLASS:javaClass}#(?<methodName>[a-zA-Z_]+):%{INT:linenumber}%{SPACE}-%{GREEDYDATA:msg}"
}
}
}
output {
stdout {
codec => rubydebug {
}
}
}
4、查看运行结果
五、代码地址
六、参考网址
1、https://github.com/logstash-plugins/logstash-patterns-core/tree/master/patterns
2、http://grokdebug.herokuapp.com/
3、https://www.elastic.co/guide/en/logstash/current/plugins-filters-grok.html