玩转多行事件
1.介绍说明
缺省情况下,Logstash认为一行文本就是一个事件对象的范围,这也符合大多数实际情形。但是,同样有很多情形是一个事件是由多行文本构成的,比如Java应用的日志中会出现异常堆栈信息。如此以来,Logstash就需要能够分辨一个文本行是否为一个多行事件的组成部分。注意,以上讨论的有一个大的前提基础:Logstash从文本中分析事件对象的过程中,文本行是最基本的处理单位。
Logstash提供了multiline codec
与multiline filter
两个插件来处理多行事件问题,也就是说使用者可以在input阶段结合codec,或者在filter阶段直接使用filter来处理。Logstash的推荐实践是尽量将该项处理前置。原因有二,第一:前置该处理将有助于尽早定型事件对象;第二:由于该插件中将会维护相邻行状态,所以如果置于filter阶段将会限制filter的线程数量只能为1。
multiline codec
与multiline filter
的配置选项是一致的,以input中的codec为例,配置如下:
input {
stdin {
codec => multiline {
pattern => "pattern, a regexp"
what => "previous" or "next"
negate => true or false
}
}
}
这其中有三个选项参数:
- pattern
- what
- negate
最重要的是前两个:pattern
与what
,这二者结合起来共同影响了解码(过滤)的执行操作逻辑。从大意上讲,pattern
是用来匹配文本行的正则表达式(这其中也可以直接使用grok pattern
),解码(过滤)器会依据匹配结果来判断当前文本行是否是一个多行事件的组成部分。而what
可以设置的两个字符串值:previous
和next
,分别表示“向前”和“向后”的意思。那么结合pattern
的匹配结果来讲,“向前”的含义就是说当前被匹配成功的行与上一行合为同一个多行事件的一部分,“向后”的含义就是说当前被匹配成功的行与下一行合为同一个多行事件的一部分。
默认情况下,pattern
匹配成功则认为当前行是多行事件的组成部分,否则就会完成本次多行事件的扫描,向pipeline的下游传递得出的事件对象。negate
选项的作用在于设置是否对pattern
匹配结果取反,其默认值是false
,意思就是不起作用。如果设置为true
会将pattern
匹配结果取反,进而将多行事件扫描过程中的行匹配逻辑反置(pattern
匹配失败则认为当前行是多行事件的组成部分)。
2.示例
2.1 分析Java堆栈追踪日志
处理内容如下:
Exception in thread "main" java.lang.NullPointerException
at com.example.myproject.Book.getTitle(Book.java:16)
at com.example.myproject.Author.getBookTitles(Author.java:25)
at com.example.myproject.Bootstrap.main(Bootstrap.java:14)
针对以上数据,以行开头处是否有空白字符为匹配规则:
input {
stdin {
codec => multiline {
pattern => "^\s"
what => "previous"
}
}
}
2.2 分析以时间开头的多行日志
处理内容如下:
[2015-08-24 11:49:14,389][INFO ][env] [Letha] using [1] data paths, mounts [[/
(/dev/disk1)]], net usable_space [34.5gb], net total_space [118.9gb], types [hfs]
针对以上数据,以行开头处内容中是否有时间信息为匹配规则:
input {
file {
path => "/var/log/someapp.log"
codec => multiline {
# Grok pattern names are valid! :)
pattern => "^%{TIMESTAMP_ISO8601} "
negate => true
what => previous
}
}
}
2.3 分析带有折行符号的文本数据
处理内容如下,
printf ("%10.10ld \t %10.10ld \t %s\
%f", w, x, y, z );
像诸如C语言等多种编程语言中,都会以行尾的\
表示“此行未完,接下行”的意思。处理这样大的输出,可以使用以下配置:
input {
stdin {
codec => multiline {
pattern => "\\$"
what => "next"
}
}
}