How to handle non-matching Logstash grok filters
Asked Answered
A

4

54

I am wondering what the best approach to take with my Logstash Grok filters. I have some filters that are for specific log entries, and won't apply to all entries. The ones that don't apply always generate _grokparsefailure tags. For example, I have one grok filter that's for every log entry and it works fine. Then I have another filter that's for error messages with tracebacks. The traceback filter throws a grokparsefailure for every single log entry that doesn't have a traceback.

I'd prefer to have it just pass the rule if there isn't a match instead of adding the parsefailure tag. I use the parsefailure tag to find things that aren't parsing properly, not things that simply didn't match a particular filter. Maybe it's just the nomenclature "parse failure" that gets me. To me that means there's something wrong with the filter (e.g. badly formatted), not that it didn't match.

So the question is, how should I handle this?

  • Make the filter pattern optional using ?

  • (ab)use the tag_on_failure option by setting it to nothing []

  • make the filter conditional using something like "if traceback in message"

  • something else I'm not considering?

Thanks in advance.

EDIT

I took the path of adding a conditional around the filter:

    if [message] =~ /took\s\d+/ {
        grok {
            patterns_dir => "/etc/logstash/patterns"
            match => ["message", "took\s+(?<servicetime>[\d\.]+)"]
            add_tag => [ "stats", "servicetime" ]
        }
    }

Still interested in feedback though. What is considered "best practice" here?

Ave answered 30/12, 2013 at 23:57 Comment(0)
F
38

When possible, I'd go with a conditional wrapper just like the one you're using. Feel free to post that as an answer!

If your application produces only a few different line formats, you can use multiple match patterns with the grok filter. By default, the filter will process up to the first successful match:

grok {
    patterns_dir => "./patterns"
    match => {
        "message" => [ 
              "%{BASE_PATTERN} %{EXTRA_PATTERN}",
              "%{BASE_PATTERN}",
              "%{SOME_OTHER_PATTERN}"
        ]
    }
}

If your logic is less straightforward (maybe you need to check the same condition more than once), the grep filter can be useful to add a tag. Something like this:

grep {
    drop => false #grep normally drops non-matching events
    match => ["message", "/took\s\d+/"]
    add_tag => "has_traceback"
}


...

if "has_traceback" in [tags] {
    ...
}
Frigg answered 2/1, 2014 at 20:31 Comment(6)
This is in violation of the DRY principle. It can't be that you first have to match a message to see if you should match a message. Especially since it's not a heuristic; the message has to match if the condition is met, otherwise the grok fails.Yankee
I see your point, but also notice you offer no alternative solution. With a few more months of experience, I know that an empty tag_on_failure may work for some use cases... but I also know the behavior on parse failures is barely documented and subject to change in the future.Frigg
match => [ "message", "a", "message", "b", "message", "c" ] results in an error.Billi
oh, it's match => { "message" => [ "Duration: %{NUMBER:duration}", "Speed: %{NUMBER:speed}" ] }Billi
just an update on your link to the logstash docs about conditionals: elastic.co/guide/en/logstash/current/…Merritt
Thanks to @StefanK. for having found the correct syntax.Wellstacked
M
25

You can also add tag_on_failure => [] to your grok stanza like so:

grok {
    match => ["context", "\"tags\":\[%{DATA:apptags}\]"]
    tag_on_failure => [ ]
}

grok will still fail, but will do so without adding to the tags array.

Marrowfat answered 25/8, 2014 at 18:1 Comment(2)
I think this is the most standard way to do it.Martine
Great this way you can create fail tags that are understandable also by people who don't know anything about grokAmputee
M
9

This is the most efficient way of doing this. Ignore the filter

filter {

        grok {
            match => [ "message", "something"]
    }

    if "_grokparsefailure" in [tags] {
            drop { }
        }
}
Munger answered 18/4, 2017 at 22:23 Comment(0)
Q
4

You can also do this

remove_tag => [ "_grokparsefailure" ]

whenever you have a match.

Quadrilateral answered 23/4, 2014 at 23:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.