How to simplify logic or format code for grok filter?

Hello,

I want to find out if there's any way to simplify the below code:

filter {
      mutate {
        add_field => {
          "[@metadata][copyOfMessage]" => "%{[message]}"
        }
      }
      mutate {
        split => {
          "[@metadata][copyOfMessage]" => "|"
        }
      }
      if [@metadata][copyOfMessage][4] =~ /^\/test\// {
        grok {
          break_on_match => false
          match => { "message" => "%{DATA:timestamp_local}\|%{NUMBER:duration}\|%{WORD:requesttype}\|%{DATA:username}\|%{DATA:resource}\|%{NUMBER:statuscode}\|%{NUMBER:bytes}" }
        }
        grok {
          break_on_match => false
          match => { "resource" => "/%{DATA:dropFirstValue}/%{DATA:dropSecondValue}/%{DATA:repo}/%{GREEDYDATA:resource_path}" }
        }

        mutate {
          remove_field => ["dropFirstValue", "dropSecondValue"]
        }
      }
      elseif [@metadata][copyOfMessage][4] =~ /^\/list\// or [@metadata][copyOfMessage][4] =~ /^\/simple\// {
        grok {
          break_on_match => false
          match => { "message" => "%{DATA:timestamp_local}\|%{NUMBER:duration}\|%{WORD:requesttype}\|%{DATA:username}\|%{DATA:resource}\|%{NUMBER:statuscode}\|%{NUMBER:bytes}" }
        }
        grok {
          break_on_match => false
          match => { "resource" => "/%{DATA:dropFirstValue}/%{DATA:repo}/%{GREEDYDATA:resource_path}" }
        }

        mutate {
           remove_field => ["dropFirstValue"]
        }
      }
      else{
        grok {
            # Enable multiple matchers
          break_on_match => false

          match => { "message" => "%{DATA:timestamp_local}\|%{NUMBER:duration}\|%{WORD:requesttype}\|%{DATA:username}\|%{DATA:resource}\|%{NUMBER:statuscode}\|%{NUMBER:bytes}" }

            # Extract repo and path
          match => { "resource" => "/%{DATA:repo}/%{GREEDYDATA:resource_path}"}

        }
      }
      grok {
        break_on_match => false
        match => { "resource_path" => "(?<resource_name>[^/]+$)" }
      }
      grok {
        break_on_match => false
        match => { "resource_path" => "(?<resource_type>[^.]+$)" }
      }
}

The sample requests for the filter are:
20190615|4|method|userend|/test/value/user-info/1.1|500|2
20190615|4|method|userend|/simple/user/123/1.1|500|2
20190615|4|method|userend|/list/resolve/123/1.1|500|2

Use-Case:

  1. I want to drop the first couple of words from "/test/value/user-info/1.1" if it starts with /test/
  2. I want to drop the first word from "/simple/user/123/1.1" if it starts with /simple/
  3. I want to drop the first word from "/list/resolve/123/1.1" if it starts with /list/

Now the above code works fine for my use-cases but looks a little hard to maintain, given we might have to add more if-else conditions in the future. I want to find out if there's any simpler way of doing this?

I'm not sure if this is what you want to achieve, but

%{DATA:timestamp_local}\|%{NUMBER:duration}\|%{WORD:requesttype}\|%{DATA:username}\|(/test/.*?/|/simple/|/list/)?%{DATA:resource}\|%{NUMBER:statuscode}\|%{NUMBER:bytes}

would give you the resources "user-info/1.1", "user/123/1.1" and "resolve/123/1.1"

I apologize for the delay but i see grok parse failure when i try this

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.