Logstash 特定データのみをフィールドに指定したい

Logstashのfilter句にて、
下記inputデータの「192.168.0.224」のみを「"client_address" => "192.168.0.224"」のようにフィールドを指定したいです。

▼inputデータ
1286536308.779 180 192.168.0.224 TCP_MISS/200 411 GET http://liveupdate.symantecliveupdate.com/minitri.flg - DIRECT/125.23.216.203 text/plain

本ケースのようにinputデータを空白区切りで左からn番目の値のみを取り出すということが可能なfilterプラグインはありますか?

上記のようなプラグインは存在しない場合、
Grok filterにて、以下のように記述する方法が良いでしょうか?

filter {
 grok {
   match => {
     "message" => "%{NUMBER:timestamp}%{SPACE}%{NUMBER:duration}\s%{IP:client_address}%{GREEDYDATA:rest}"
    }
   remove_field => [ "message", "timestamp","duration" ]
  }
}

もし分かる方がいらっしゃいましたら、回答を宜しくお願い致します。

指定文字列で文字列を分割して、n番目の要素を取得する、ということでしたら
mutateのsplitが使えるかと思います。


filter {
    mutate {
        # messageを空白文字で分割する
        split => ["message", " "]
        # n番目の要素、ここでは2番目をclient_addressにセットする
        add_field => { "client_address" => "%{[message][2]}" }
        # 元のmessageを消す
        remove_field => ["message"]
    }
}

確認環境: Logstash7.3.2

もちろんGrok Filterも使えるかと思います。

早急に回答頂きありがとうございます。
mutateのsplitが使えるのですね。勉強になりました。

【追加のご質問】
filter句にmutate+translateの記載を行い、Elasticsearchにてindex登録を行ったところ、
"client_address"の値がinputデータの「192.168.0.224」ではなく「%{[message2][2]}」で登録されました。
add_field => { "client_address" => "%{[message][2]}" }の記載に誤りがありますでしょうか。
もし分かりましたら教えてください。

Logstashバージョン:7.3.1

▼Logstashのconfig
input {
beats {

}
}

filter{
    mutate {
        split => ["message", " "]
        add_field => { "client_address" => "%{[message][2]}" }
        remove_field => [ "message" ]
    }

    translate {
        field => "client_address"
        destination => "blacklist"
        exact => true
        regex => true
        dictionary_path => "/var/tmp/data/translate.yml"
        fallback => "2"
  }

}
output{
    elasticsearch{
 …
}

Logstash7.3.1( + OpenJDK11 ) で確認しましたが、その書き方で期待した動作になったので、書き方はあってるかと思います。

一方、message[2]が取得できないような場合に、おっしゃるような状況になります。
一度、remove_field => [ "message" ]の部分を外して、状況がおきるときのmessageの中身を確認いただくことはできますか?

問題の単純化のために、入力と出力をstdinとstdoutにしてLogstashを動かしてみると良いと思います。

input {
    stdin{}
}

filter {
    mutate {
        split => ["message", " "]
        add_field => { "client_address" => "%{[message][2]}" }
        # remove_field => ["message"]
    }
}

output {    
    stdout { }
}

この状態で、一番最初の投稿にあったような文字を標準入力で入れますと、こうなるかと思います。

1286536308.779 180 192.168.0.224 TCP_MISS/200 411 GET http://liveupdate.symantecliveupdate.com/minitri.flg - DIRECT/125.23.216.203 text/plain

もし、messageが空白を含まない文字、あるいはSplitできるけど、2番目の要素がないようなときは、こうなりました。

image

ですので、messageをremoveしているところを、いったん外していただいて、
Splitが期待通りされていること、指定する要素番号が存在することを確認いただくのが良いのではないかと思います。

ご確認いただければ幸いです。

1 Like

早急に回答頂きありがとうございます。

上記記載で試したところ、"client_address"に期待の値を取得できました。
大変助かりました。

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