无法使用 Logstash 中的 grok 从包含 JSON 和非 JSON 数据的日志行中提取字段
Unable to extract fields form log line containing a mix of JSON and non-JSON data using grok in Logstash
我是 运行 几个 Spring 在 Docker 容器中启动应用程序。因为我不想记录到文件,所以我改为记录到控制台,然后使用 logspout to forward the logs to Logstash. I am using logstash-logback-encoder 以 JSON 格式记录来自应用程序的所有日志。
除此之外,还有一些日志(控制台输出)由 docker 容器在启动 Spring 启动应用程序之前生成。这些不是 JSON 格式。
对于这两者,Logspout 在发送到 Logstash 之前附加元数据(容器名称、容器 ID 等)。以下是我的两种格式的示例日志。
- 直接来自容器(无 JSON)
<14>1 2016-12-01T12:58:20Z 903c18d47759 com-test-myapp 31635
- - Setting active profile to test
- 应用程序日志(JSON 格式)
<14>1 2016-12-01T13:08:13Z 903c18d47759 com-test-myapp 31635
- - {"@timestamp":"2016-12-01T13:08:13.651+00:00","@version":1,"message":"Some
log message goes
here","logger_name":"com.test.myapp.MyClass","thread_name":"http-nio-8080-exec-1","level":"DEBUG","level_value":10000,"HOSTNAME":"903c18d47759"}
下面是我的 Logstash grok 配置。
input {
tcp {
port => 5000
type => "logspout-syslog-tcp"
}
}
filter {
if [type] == "logspout-syslog-tcp" {
grok {
match => {
"message" => [
"<%{NUMBER:syslogPriority}>1 %{TIMESTAMP_ISO8601:eventTimestamp} %{BASE16NUM:containerId} %{DATA:containerName} %{NUMBER:containerPort} - - %{DATA:jsonLog}",
"<%{NUMBER:syslogPriority}>1 %{TIMESTAMP_ISO8601:eventTimestamp} %{BASE16NUM:containerId} %{DATA:containerName} %{NUMBER:containerPort} - - %{DATA:regularLog}"
]
}
}
json {
source => "jsonLog"
target => "parsedJson"
remove_field=>["jsonLog"]
}
mutate {
add_field => {
"level" => "%{[parsedJson][level]}"
"thread" => "%{[parsedJson][thread_name]}"
"logger" => "%{[parsedJson][logger_name]}"
"message" => ["%{[parsedJson][message]}"]
}
}
}
}
output {
elasticsearch { hosts => ["localhost:9200"] }
stdout { codec => rubydebug }
}
基于此,我希望 JSON 中的每个字段都可用作 Elasticsearch/Kibana 中的过滤器。但我无法获得这些领域的价值。它在 Kibana 中显示如下:
我不确定我在这里遗漏了什么。我应该如何从 JSON 中提取字段?此外,grok 过滤器对于处理 JSON 和非 JSON 日志是否正确?
谢谢,
阿诺普
问题出在 %{DATA:jsonLog}
部分。 DATA 模式 .*?
不是贪婪的(请参阅 here),因此它不会获取任何内容,也不会创建 jsonLog
字段。您需要改用 GREEDYDATA
模式。
请参阅 http://grokconstructor.appspot.com/do/match#result 来测试您的模式。
我是 运行 几个 Spring 在 Docker 容器中启动应用程序。因为我不想记录到文件,所以我改为记录到控制台,然后使用 logspout to forward the logs to Logstash. I am using logstash-logback-encoder 以 JSON 格式记录来自应用程序的所有日志。
除此之外,还有一些日志(控制台输出)由 docker 容器在启动 Spring 启动应用程序之前生成。这些不是 JSON 格式。
对于这两者,Logspout 在发送到 Logstash 之前附加元数据(容器名称、容器 ID 等)。以下是我的两种格式的示例日志。
- 直接来自容器(无 JSON)
<14>1 2016-12-01T12:58:20Z 903c18d47759 com-test-myapp 31635 - - Setting active profile to test
- 应用程序日志(JSON 格式)
<14>1 2016-12-01T13:08:13Z 903c18d47759 com-test-myapp 31635 - - {"@timestamp":"2016-12-01T13:08:13.651+00:00","@version":1,"message":"Some log message goes here","logger_name":"com.test.myapp.MyClass","thread_name":"http-nio-8080-exec-1","level":"DEBUG","level_value":10000,"HOSTNAME":"903c18d47759"}
下面是我的 Logstash grok 配置。
input {
tcp {
port => 5000
type => "logspout-syslog-tcp"
}
}
filter {
if [type] == "logspout-syslog-tcp" {
grok {
match => {
"message" => [
"<%{NUMBER:syslogPriority}>1 %{TIMESTAMP_ISO8601:eventTimestamp} %{BASE16NUM:containerId} %{DATA:containerName} %{NUMBER:containerPort} - - %{DATA:jsonLog}",
"<%{NUMBER:syslogPriority}>1 %{TIMESTAMP_ISO8601:eventTimestamp} %{BASE16NUM:containerId} %{DATA:containerName} %{NUMBER:containerPort} - - %{DATA:regularLog}"
]
}
}
json {
source => "jsonLog"
target => "parsedJson"
remove_field=>["jsonLog"]
}
mutate {
add_field => {
"level" => "%{[parsedJson][level]}"
"thread" => "%{[parsedJson][thread_name]}"
"logger" => "%{[parsedJson][logger_name]}"
"message" => ["%{[parsedJson][message]}"]
}
}
}
}
output {
elasticsearch { hosts => ["localhost:9200"] }
stdout { codec => rubydebug }
}
基于此,我希望 JSON 中的每个字段都可用作 Elasticsearch/Kibana 中的过滤器。但我无法获得这些领域的价值。它在 Kibana 中显示如下:
我不确定我在这里遗漏了什么。我应该如何从 JSON 中提取字段?此外,grok 过滤器对于处理 JSON 和非 JSON 日志是否正确?
谢谢, 阿诺普
问题出在 %{DATA:jsonLog}
部分。 DATA 模式 .*?
不是贪婪的(请参阅 here),因此它不会获取任何内容,也不会创建 jsonLog
字段。您需要改用 GREEDYDATA
模式。
请参阅 http://grokconstructor.appspot.com/do/match#result 来测试您的模式。