Как обработать многострочную запись журнала с помощью фильтра logstash?

Справочная информация:

у меня есть пользовательский сгенерированный файл журнала, который имеет следующий шаблон:

[2014-03-02 17:34:20] - 127.0.0.1|ERROR| E:xampphtdocstest.php|123|subject|The error message goes here ; array (
  'create' => 
  array (
    'key1' => 'value1',
    'key2' => 'value2',
    'key3' => 'value3'
  ),
)
[2014-03-02 17:34:20] - 127.0.0.1|DEBUG| flush_multi_line

вторая запись [2014-03-02 17:34:20] - 127.0.0.1|DEBUG| flush_multi_line является фиктивной строкой, просто чтобы logstash знал, что событие multi line закончилось, эта строка удаляется позже.

мой конфигурационный файл следующий:

input {
  stdin{}
}

filter{
  multiline{
      pattern => "^["
      what => "previous"
      negate=> true
  }
  grok{
    match => ['message',"[.+] - %{IP:ip}|%{LOGLEVEL:loglevel}"]
  }

  if [loglevel] == "DEBUG"{ # the event flush  line
    drop{}
  }else if [loglevel] == "ERROR"  { # the first line of multievent
    grok{
      match => ['message',".+|.+| %{PATH:file}|%{NUMBER:line}|%{WORD:tag}|%{GREEDYDATA:content}"] 
    }
  }else{ # its a new line (from the multi line event)
    mutate{
      replace => ["content", "%{content} %{message}"] # Supposing each new line will override the message field
    }
  }  
}

output {
  stdout{ debug=>true }
}

вывод контент - это : The error message goes here ; array (

проблема:

моя проблема в том, что я хочу сохранить остальные поля многострочное содержимое:

The error message goes here ; array (
  'create' => 
  array (
    'key1' => 'value1',
    'key2' => 'value2',
    'key3' => 'value3'
  ),
)

поэтому я могу удалить поле сообщения позже.

на @ поле содержит все многострочное событие, поэтому я попробовал мутировать фильтр С заменить функция на этом, но я просто не могу заставить ее работать : (.

Я не понимаю, как работает многострочный фильтр, если бы кто-то мог пролить свет на это, это было бы действительно оцененный.

спасибо,

Абду.

4 ответов


Я просмотрел исходный код и узнал, что:

  • на многострочный фильтр отменить все события считается продолжением ожидающего события, затем добавьте эту строку в исходное поле сообщения, то есть любые фильтры, которые после многострочного фильтра не будут применяться в этом случае
  • единственное событие, которое когда-либо пройдет фильтр, считается новым ( то, что начинаются с [ в моем случае )

вот рабочий код :

input {
   stdin{}
}  

filter{
      if "|ERROR|" in [message]{ #if this is the 1st message in many lines message
      grok{
        match => ['message',"\[.+\] - %{IP:ip}\|%{LOGLEVEL:loglevel}\| %{PATH:file}\|%{NUMBER:line}\|%{WORD:tag}\|%{GREEDYDATA:content}"]
      }

      mutate {
        replace => [ "message", "%{content}" ] #replace the message field with the content field ( so it auto append later in it )
        remove_field => ["content"] # we no longer need this field
      }
    }

    multiline{ #Nothing will pass this filter unless it is a new event ( new [2014-03-02 1.... )
        pattern => "^\["
        what => "previous"
        negate=> true
    }

    if "|DEBUG| flush_multi_line" in [message]{
      drop{} # We don't need the dummy line so drop it
    }
}

output {
  stdout{ debug=>true }
}

спасибо,

Абду


grok и многострочная обработка упоминаются в этой проблеме https://logstash.jira.com/browse/LOGSTASH-509

просто добавить "(?м)" перед вашим Грок regex и вы не нужны мутации. Пример из выпуска:

pattern => "(?m)<%{POSINT:syslog_pri}>(?:%{SPACE})%{GREEDYDATA:message_remainder}"

многострочный фильтр добавит "\n " к сообщению. Например:

"[2014-03-02 17:34:20] - 127.0.0.1|ERROR| E:\xampp\htdocs\test.php|123|subject|The error message goes here ; array (\n  'create' => \n  array (\n    'key1' => 'value1',\n    'key2' => 'value2',\n    'key3' => 'value3'\n  ),\n)"

однако фильтр grok не может анализировать "\n". Поэтому вам нужно заменить \n на другой символ, говорит пустое пространство.

mutate {
    gsub => ['message', "\n", " "]
}

затем шаблон grok может анализировать сообщение. Например:

 "content" => "The error message goes here ; array (   'create' =>    array (     'key1' => 'value1',     'key2' => 'value2',     'key3' => 'value3'   ), )"

проблема не просто в упорядочении фильтров. Заказ очень важен для журнала stash. Вам не нужна другая строка, чтобы указать, что вы закончили вывод многострочной строки журнала. Просто убедитесь, что многострочный фильтр появляется первым перед grok (см. ниже)

P. s. Мне удалось проанализировать многострочную строку журнала, где xml был добавлен в конец строки журнала, и он охватывал несколько строк, и все же я получил хороший чистый объект xml в мою эквивалентную переменную контента (с именем xmlrequest ниже.) Прежде чем говорить о регистрации xml в журналах... Я знаю... это не идеально... но это для другой дискуссии :)):

filter { 
multiline{
        pattern => "^\["
        what => "previous"
        negate=> true
    }

mutate {
    gsub => ['message', "\n", " "]
}

mutate {
    gsub => ['message', "\r", " "]
}

grok{
        match => ['message',"\[%{WORD:ONE}\] \[%{WORD:TWO}\] \[%{WORD:THREE}\] %{GREEDYDATA:xmlrequest}"]
    }

xml {
source => xmlrequest
remove_field => xmlrequest
target => "request"
  }
}