我有这样的日志:
2020-09-02 14:29:22,854 [http-something] [ERROR] JavaClass(JavaLine) - [6652942]: Error message with no stack trace
2020-09-02 14:29:08,976 [http-something] [INFO] JavaClass(JavaLine) - [6791732]: Some message
2020-09-02 14:29:09,116 [http-something] [ERROR] JavaClass(JavaLine) - [6791732]: Error message with stack trace
JavaException: This is not going well
at JavaClass
at JavaClass
at JavaClass
at JavaClass
at JavaClass
Caused by: JavaClass: This is a problem
at JavaClass
at JavaClass
at JavaClass
at JavaClass
... 48 more
我使用这个过滤器在Kibana:上有一个更可读的日志
filter {
# INFO and ERROR
grok {
tag_on_failure => ["_stackTraceFailure"]
match => { "message" => "%{TIMESTAMP_ISO8601:timestamp}%{SPACE}([%{DATA:thread}])?%{SPACE}[%{LOGLEVEL:log_level}]%{SPACE}%{GREEDYDATA}%{SPACE}-%{SPACE}%{GREEDYDATA:action}" }
overwrite => [ "message" ]
}
# JAVA ERROR
if ("_stackTraceFailure" in [tags]) {
grok {
tag_on_failure => ["_grokParseFailure"]
match => { "message" => "%{TIMESTAMP_ISO8601:timestamp}%{SPACE}([%{DATA:thread}])?%{SPACE}[%{LOGLEVEL:log_level}]%{SPACE}%{GREEDYDATA}%{SPACE}-%{SPACE}%{DATA:issue}(r|n)+(?m)%{GREEDYDATA:stack-trace}" }
overwrite => [ "message" ]
remove_tag => "_stackTraceFailure"
}
}
}
问题是,第一个模式匹配所有内容,将所有堆栈跟踪(如果有(放在action标记中,导致第二个模式永远无法使用。我知道这个问题是由GREEDYDATA引起的,但我对regex不是很熟练,也没有找到解决方案来做我想做的事情。
我不想交换模式的位置,因为INFO和ERROR(没有堆栈跟踪(更常见,所以我需要一种方法来在多行日志的情况下使第一个失败,或者如果有某种堆栈跟踪,任何会使第一个失效的方法。从我目前所做的事情开始,我能做些什么呢?
您需要在grok之前使用条件词。您可以使用条件来过滤整个消息,并使用两个不同的grok
过滤器,或者您可以保持第一个grok
过滤器不变,并使用条件来仅解析action
字段,我建议使用第二个选项。
在这两种情况下,您都需要根据只存在于多行消息中的内容进行条件筛选,在这种情况下可能是"at JavaClass"
字符串。
所以你需要这样的东西:
if "at JavaClass" not in [message] {
grok { your first grok }
} else {
grok { your second grok }
}
如果你想保留你的第一个grok,并使用第二个grok只解析动作字段,它会是这样的。
if "at JavaClass" in [action] {
grok {
tag_on_failure => ["_grokParseFailure"]
match => { "action" => "%{DATA:issue}(r|n)+(?m)%{GREEDYDATA:stack-trace}" }
}
}
你没有说明你是如何收集日志的,如果你使用的是输入中编码为multiline
的filebeat或logstash,你也可以根据标签进行过滤,因为你的日志会有一个名为multiline
的标签。