Conditional grok


(Tak Mk) #1

Hi guys!

I have a log with two totally different patterns (yeah, I should split them up), and I want to parse them with grok.

Can I do something like "if the message has X word, use this grok pattern, else, use that pattern"?

Thanks a lot!


(Magnus Bäck) #2

You can either use regexp conditionals to choose between different filters (see the documentation for examples) or list multiple grok patterns that'll be applied in order with first-match-wins policy.


(Tak Mk) #3

I'm reading this documentation page (https://www.elastic.co/guide/en/logstash/current/plugins-filters-grok.html#plugins-filters-grok-match), but still don't know how to do it properly.
There's any other web with more information? If don't, can you put a simple example?


(Magnus Bäck) #4

In the grok documentation that you linked to, see the example preceded by "If you need to match multiple patterns against a single field, the value can be an array of patterns".

See https://www.elastic.co/guide/en/logstash/current/event-dependent-configuration.html#conditionals for more on conditionals.


(Tak Mk) #5

Thanks for the info!
I've tested if but it won't work (or I'm writing a wrong config file).

Here's my filter condition:

filter {
  if [type] == "apache_access" {
    grok {
        patterns_dir => "./patterns"
        match => { "message" => "%{COMBINEDAPACHELOG}" }
    }
  }
  else if [type] == "apache_error" {
    if [message] in "ModSecurity" {
      grok {
        patterns_dir => "./patterns"
        match => { "message" => "%{HTTPERRORDATE:date} \[%{HTTPMODULE:module}:%{LOGLEVEL:loglevel}\] \[pid %{POSINT:pid}\] \[client %{IP:IP}\] ModSecurity: %{GREEDYDATA:message}"}
        }
      } else {
        grok {
          patterns_dir => "./patterns"
          match => { "message" => "%{HTTPERRORDATE:date} \[%{HTTPMODULE:module}:%{LOGLEVEL:loglevel}\] \[pid %{POSINT:pid}\] %{WORD:errorid}: %{GREEDYDATA:message}"}
      }
    }
  }
  else if [type] == "apache_request" {
    grok {
    patterns_dir => "./patterns"
      match => { "message" => "\[%{HTTPDATE:date}\] %{IP:IP} %{WORDSPACE:cipher} %{WORDSPACE:encryption} \"%{WORD:action} %{WORDSPACE:message} %{WORDSPACE:http_protocol}\" %{GREEDYDATA}"}
    }
  }
}

I want to match if a line of a "apache_error" type log has "ModSecurity" on it, and parse it with one grok or another.

The grok is running well (I've tested it on http://grokconstructor.appspot.com/do/match website), but I'm getting a lot of [0] "_grokparsefailure".

Thanks a lot!


(Magnus Bäck) #6
if [message] in "ModSecurity" {

This is backwards, change to:

if "ModSecurity" in [message] {

(Magnus Bäck) #7

Also, I wouldn't assume anything about what the current directory is. I suggest you specify absolute paths to the pattern file directory.


(Tak Mk) #8

I'll try that, and change the patterns path. Thanks a lot for your help!

EDIT: It works, thanks! :smiley:


(system) #9