複数行にまたがるログのパースについて

inputの中身について

まずinputの指定です。

ここにあります「Another example is to merge lines not starting with a date up to the previous line..」のところが今回のパターンと近しいのでイメージしやすいと思います。

日付の文字列で始まってなかったら、前の行データ(previous)にくっつけていくというサンプルです。

少し上の説明文を見ると、こう書いてあります。

The negate can be true or false (defaults to false ). If true , a message not matching the pattern will constitute a match of the multiline filter and the what will be applied. (vice-versa is also true)

negateをtrueにしたとき、メッセージがパターンにマッチしなかったら、whatの内容が適用される。
今回negateはtrueになっているため、日付文字列が入った [ で始まらなかったら、前の行に追加する、 と書けるので、inputはこんな感じにしました。
nextではなくpreviousにしています。


input {
  file {
    path => "Z:/z.log"
    start_position => "beginning"
    codec => multiline {
      pattern => "^\["
      negate => true
      what => "previous"
    }
  }
}

grokの書き方について

おそらく、multilineがうまく設定されていると、logstashのoutputにstdoutを指定しますと、どのようなデータがmessageに入っているかを確認できるかと思います。

改行コードにもよりますが、今回はCRLF(\r\n)で以下のようなテストデータを作りました。

[2019/04/15 11:19:32] ID=1790 DEV=tokyo.region.04
dir

logstashのgrokでは、改行コードも含めてpatternを書きました。

filter {
  grok {
    match => { "message" => "\[%{YEAR:year}/%{MONTHNUM:month}/%{MONTHDAY:day}%{SPACE}%{HOUR:hour}:%{MINUTE:minute}:%{SECOND:sec}\] ID=%{POSINT:ID} DEV=%{HOSTNAME:DEV}\r\n%{GREEDYDATA:command}\r" }
    
  }
}

とすると、こんな感じでパースできます。

messageに入った文字列をみて、Grokのパターンを考えるのがポイントです。

参考

Grokのパターンを考える際は、KibanaのDevToolsにあるGrok Debuggerを使うと、簡易に試せて便利です。

参考2

パースする側からしてみると、 [日付]部分がTIMESTAMP_ISO8601の形式になっていればもっと簡単にGrokのパターンが書けて良さそうです。

これらの中身は、7.0.0の環境で試しています。ご参考になれば幸いです。