Edited at

fluentdで不要なログを取り除くfilterプラグインを作った

More than 3 years have passed since last update.


概要

Fluentd v0.12から利用できるFilterの機能を利用して、ログから正規表現でマッチしたものを取り除くfluent-plugin-ignore-filterを作りました。


grep-filterと何が違うのか

Fluentd v0.12以降には grep Filter Plugin という @sonots さんの

fluent-plugin-grep を取り込んだフィルタが組み込まれています。

こちらはログから正規表現で「マッチしたものを抽出する」プラグインです。

grepフィルタにはexcludeオプションがあるため、こちらを利用することで不要なログを取り除くことは一応可能です。

しかし、こちらのプラグインは「マッチしたログを通す」ためのフィルタのため、

マッチしたものを除外する目的で利用しようとすると、パース済みのログに対しand条件で除外できないという問題がありました。

例えば、ELBからのヘルスチェックだけ取り除きたいときに、path:/healthcheck.txtかつ client_ip:10.0.0.0/16 のログのみを除外するといった記述ができません。

<filter access.nginx.**>

@type grep
exclude1 path ^/healthcheck\.txt$
exclude2 client_ip ^10\.0\.
</filter>

と記述するとexcludeがor条件になってしまうため、path:/healthcheck.txt すべてと client_ip:10.0.0.0/16 すべてが取り除かれてしまいます。

私が作成したignoreフィルタは「マッチしたものを取り除く」ので、grepフィルタとは逆の動作になります。

grep-pluginはもともとmatch向けのため、必要なものを通すという記法が理解しやすかったのだと思います。

しかし、filterプラグインは何重にも掛けることが出来るため、「必要なものを通す」を1つ書くよりは「不要なものを除く」記述を複数書くほうが理解しやすくなると思い、作成しました。


使い方


インストール

# for fluentd

$ gem install fluent-plugin-ignore-filter

# for td-agent2
$ sudo td-agent-gem install fluent-plugin-ignore-filter


記法

記法はgrepフィルタとほぼ同じです。

regexpN <key> <pattern> 全てにマッチしたもののうち、

excludeN <key> <pattern> 全てにマッチしないもの

を除外します。


具体例


ELBからのヘルスチェックだけ取り除きたい

ELBはVPCの中なのでclient_ipがprivate_ipなになる。

(client_ipにはx_forwarded_forの最後の値か、なければremote_ipが入っている設定)

<filter access.nginx.**>

@type ignore
regexp1 path ^/healthcheck\.txt$
regexp2 client_ip ^10\.0\.
</filter>


syslogから特定のメッセージ以外のinfo|noticeを除外したい

corosync使ってるとcrmdがnoticeレベルで結構重要な情報を出すので

level:notice でもident:crmdかつ message:process_lrm_event〜 は通したいとき。

<filter alert.messages.**>

@type ignore
regexp1 level info
</filter>
<filter alert.messages.**>
@type ignore
regexp1 level notice
exclude1 ident crmd
</filter>
<filter alert.messages.**>
@type ignore
regexp1 level notice
regexp2 ident crmd
exclude1 message ^process_lrm_event
</filter>

Filterは何重にも書けられるので便利ですね!


補足


  • Fluentdのfilter_grep.rb をかなり参考にさせてもらっています。 @sonots さんありがとうございます。


    • grep Filterも併用してわかりやすい記述にするのが良さそうです。



  • Rubyは初めて書いたので変なところがあるかもしれません。Pull-request歓迎です!




その他


  • 同様のプラグインはあるかもしれません。


    • 名称をexclude-filterにしようとしたら既に存在していました。(ただしfilter pluginではないようです。)



  • Filterプラグインはまだ数が少ないので、ネーミングルールが分かりませんでした。


    • 名称がFilterでもout pluginが多いですね。



  • ignoreのexcludeって分かりにくい気はしています。


    • 仕方ないですかね...