Logstash:拆分后基于if的Drop On事件

时间:2017-02-17 15:47:21

标签: logging elasticsearch docker logstash kibana

情况:

我的输入日志如下所示:

{
"key1":"value1"
"key2":"value2"
"events":
[{
"Level":"Information",
"Code":"100"
},
{
"Level":"Information",
"SomeKey":"SomeValue"
},
{
"Level":"Error",
"Message":"Something went wrong"
}
]}

我想:

  1. 拆分事件数组以创建单个对象,其中所有外层字段仍然填充(key1和key2)。

  2. 分割后选择性地删除日志。我只想保留“信息级”日志,如果它们包含“代码”属性。

  3. 我的logstash配置看起来像

    filter {
     split {
      field => "[events]"
      }
    }
    
     filter {
        if ![events][Code]
        { drop {} }
     }
    
     output {
       elasticsearch {}
     }
    

    问题:

    Logstash似乎在执行第二个过滤器之前不会分隔事件。

    换句话说,如果日志中的任何事件没有“代码”字段,则会删除整个日志,包括我必须保留的“错误”级别信息。

    我已经待了大约一整天了,这让我很紧张。我会手动尝试创建自己的插件,但我从未使用任何Ruby。

    我很确定这无关紧要,但我在Docker中运行ELK堆栈。我确信配置文件正确加载并且它们被Logstash使用。

1 个答案:

答案 0 :(得分:0)

这实际上似乎是某种logstash错误。这是一个错误的演示:

配置文件:

input {
    stdin { codec => "json" }
}
filter {
    split { field => "events" }
    if ([events] == "" or [events][Code] == "") { 
        drop {} 
    }
}  
output {
    stdout { codec => "rubydebug" }
}

命令行:

echo '{"key1":"value1","key2":"value2","events":[{"Level":"Information","Code":"100"},{"Level":"Information","SomeKey":"SomeValue"},{"Level":"Error","Message":"Something went wrong"}]}' | bin/logstash -f test.conf

结果:

Exception in thread "[main]>worker7" java.lang.NumberFormatException: For input string: "Code"
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.lang.Integer.parseInt(Integer.java:580)
    at java.lang.Integer.parseInt(Integer.java:615)
    at org.logstash.Accessors.fetch(Accessors.java:130)
    at org.logstash.Accessors.get(Accessors.java:20)
    at org.logstash.Event.getUnconvertedField(Event.java:160)
    at org.logstash.ext.JrubyEventExtLibrary$RubyEvent.ruby_get_field(JrubyEventExtLibrary.java:113)
    at org.logstash.ext.JrubyEventExtLibrary$RubyEvent$INVOKER$i$1$0$ruby_get_field.call(JrubyEventExtLibrary$RubyEvent$INVOKER$i$1$0$ruby_get_field.gen)

所以基本上它仍然认为事件是一个数组,它试图通过“代码”

对其进行索引

这似乎解决了这个问题:

    mutate {
            add_field => ["code", "%{[events][Code]}"]
    }
    if ([code] == "%{[events][Code]}") {
            drop {}
    }
    mutate {
            remove_field => ["code"]
    }