Logstash grok过滤器 - 动态命名字段

时间:2014-07-07 07:41:58

标签: logstash

我有以下格式的日志行,想要提取字段:

[field1: content1] [field2: content2] [field3: content3] ...

我既不知道字段名称,也不知道字段数。

我尝试使用反向引用和sprintf格式,但没有得到任何结果:

match => [ "message", "(?:\[(\w+): %{DATA:\k<-1>}\])+" ] # not working
match => [ "message", "(?:\[%{WORD:fieldname}: %{DATA:%{fieldname}}\])+" ] # not working

这似乎仅适用于一个领域而不是更多领域:

match => [ "message", "(?:\[%{WORD:field}: %{DATA:content}\] ?)+" ]
add_field => { "%{field}" => "%{content}" }

kv过滤器也不合适,因为字段的内容可能包含空格。

是否有任何插件/策略可以解决此问题?

3 个答案:

答案 0 :(得分:8)

Logstash Ruby插件可以帮到你。 :)

以下是配置:

input {
    stdin {}
}

filter {
    ruby {
        code => "
            fieldArray = event['message'].split('] [')
            for field in fieldArray
                field = field.delete '['
                field = field.delete ']'
                result = field.split(': ')
                event[result[0]] = result[1]
            end
        "
    }
}

output {
    stdout {
        codec => rubydebug
    }
}

使用您的日志:

[field1: content1] [field2: content2] [field3: content3]

这是输出:

{
   "message" => "[field1: content1] [field2: content2] [field3: content3]",
  "@version" => "1",
"@timestamp" => "2014-07-07T08:49:28.543Z",
      "host" => "abc",
    "field1" => "content1",
    "field2" => "content2",
    "field3" => "content3"
}

我尝试了4个字段,它也有效。

请注意,ruby代码中的event是logstash事件。您可以使用它来获取所有事件字段,例如message, @timestamp等。

享受它!!!

答案 1 :(得分:5)

我找到了使用正则表达式的另一种方式:

ruby {
    code => "
        fields = event['message'].scan(/(?<=\[)\w+: .*?(?=\](?: |$))/)
        for field in fields
            field = field.split(': ')
            event[field[0]] = field[1]
        end
    "
}

答案 2 :(得分:0)

我知道这是一个旧帖子,但我今天刚看到它,所以我想我会提供一个替代方法。请注意,作为一项规则,我几乎总是使用 ruby​​ 过滤器,如前两个答案中的任何一个所建议的。不过,我想我会提供这个作为替代方案。

如果有固定数量的字段或最大数量的字段(即可能少于三个字段,但永远不会超过三个字段),这可以通过组合{{1 }} 和 grok 过滤器,以及。

mutate

对于那些可能不熟悉正则表达式的人,# Test message is: `[fieldname: value]` # Store values in [@metadata] so we don't have to explicitly delete them. grok { match => { "[message]" => [ "\[%{DATA:[@metadata][_field_name_01]}:\s+%{DATA:[@metadata][_field_value_01]}\]( \[%{DATA:[@metadata][_field_name_02]}:\s+%{DATA:[@metadata][_field_value_02]}\])?( \[%{DATA:[@metadata][_field_name_03]}:\s+%{DATA:[@metadata][_field_value_03]}\])?" ] } } # Rename the fieldname, value combinations. I.e., if the following data is in the message: # # [foo: bar] # # It will be saved in the elasticsearch output as: # # {"foo":"bar"} # mutate { rename => { "[@metadata][_field_value_01]" => "[%{[@metadata][_field_name_01]}]" "[@metadata][_field_value_02]" => "[%{[@metadata][_field_name_02]}]" "[@metadata][_field_value_03]" => "[%{[@metadata][_field_name_03]}]" } tag_on_failure => [] } 中的捕获是可选的正则表达式匹配,这意味着如果没有匹配,则表达式不会失败。 ()? 过滤器中的 tag_on_failure => [] 选项可确保在重命名之一失败时不会将错误附加到 mutate,因为没有要捕获的数据,因此没有要重命名的字段。