現状のfluentdでは、タグを動的に扱う方法がいまいち無い。具体的に言うと設定項目にタグに応じて変化するような指定をしたい場合、タグごとに分けて書くしかない。例えば out_file で出力先ファイル名をタグに応じてつけたい場合、タグの数だけ match 節を書く必要がある。
<match hoge> type file path /var/log/hoge.log </match> <match pos> type pos path /var/log/pos.log </match> # 以下いっぱい
これには極めて簡単にわかる範囲で、ふたつの大きな問題がある。
- 多数のタグを扱う場合、設定ファイル全体のボリュームが肥大化して管理コストが増大する(品質が低下する)
- 新しく扱うタグが増える場合、設定ファイルの更新と適用が必要となり、管理コストが増大する
既に手元でこの問題に悩まされていて、HoopServerに書き込みに行くfluentd*1の設定ファイルの行数が既に18タグ分、417行にわたっていてかなり末期的な症状を呈していた。大部分コピペなんだけどところどころ違うのがたちが悪い。
ぶっちゃけ、このように書いたらあとは適当にfluentdがやってくれたりすると嬉しい。
<match *> type file path /var/log/__TAG__.log </match>
無いのなら、作ってしまえ、プラグイン
fluent-plugin-forest
ということで fluent-plugin-forest を作った。とりあえずまる1日動かしたところ問題なさそうなのでrubygems.orgにリリースし、手元では全台に配布済。
tagomoris/fluent-plugin-forest · GitHub
fluent-plugin-forest | RubyGems.org | your community gem host
これを使うことで417行あった設定ファイルが55行まで圧縮され、しかもタグが増えても再起動も要らず、タグごとの設定の違いもたいへん分かりやすいという天国的な状況に! ヤッタネ!
ちなみに上の単純な out_file のパターンだとこのようになる。
<match *> type forest subtype file <template> path /var/log/__TAG__.log </template> </match>
どう使えるか
fluent-plugin-forestは以下のように動作する。
- タグひとつにつき output plugin のインスタンスをひとつ生成する
- 設定中の任意の場所で __TAG__ というプレースホルダを使用できる
- この部分はタグ文字列に置き換えられた設定として output plugin に渡される
- なおここには remove_prefix / add_prefix が評価された後のタグが入る
- 設定では template セクションと case セクションを使用できる
- template セクションは全タグ文字列に対して適用する設定内容
- case セクションは case hoge.** のようにパターンを記述でき、そのパターンにマッチする場合だけ適用する設定内容
- 現状 server セクションや store セクションなどを用いる output plugin について、そのサブセクション内だけを置き換えるような書き方はできない
このあたりを理解して、自分の手元の実例を挙げるとこうなる。まず従来の設定内容。sourceや最後のforwardまわりの細かい設定は省いてある。
# original configurations <source> type forward </source> <match converted.serviceX> type copy <store> # Hoop server への書き込み、流量が多いのでノードごとにファイルを分けるもので NODENAME には実際にはfluentd動作ノード名がサーバごとに書かれる type hoop hoop_server hoop.server.local:14000 path /hoop/log/%Y%m%d/serviceX-%Y%m%d-%H.NODENAME.log username hoopuser flush_interval 60s output_include_time false output_include_tag false output_data_type attr:hhmmss,vhost,path,method,status,bytes,duration,referer,rhost,userlabel,agent,FLAG,status_redirection,status_errors,rhost_internal,suffix_miscfile,suffix_imagefile,agent_bot add_newline true </store> <store> # 監視用サンプリング設定 type sampling_filter interval 100 remove_prefix converted add_prefix sampled.100 </store> </match> <match converted.serviceY> # 流量の少ないサービス、path指定NODENAMEがないこと、サンプリングレートが 10 であることのみ異なる type copy <store> type hoop hoop_server hoop.server.local:14000 path /hoop/log/%Y%m%d/serviceY-%Y%m%d-%H.log username hoopuser flush_interval 60s output_include_time false output_include_tag false output_data_type attr:hhmmss,vhost,path,method,status,bytes,duration,referer,rhost,userlabel,agent,FLAG,status_redirection,status_errors,rhost_internal,suffix_miscfile,suffix_imagefile,agent_bot add_newline true </store> <store> type sampling_filter interval 10 remove_prefix converted add_prefix sampled.10 </store> </match> # 以下16回(!)くりかえし <match sampled.**> type forward <server> host watcher01.local </server> <server> host watcher02.local </server> </match>
眺めるだけでアタマが痛いですね!!!!! これを fluent-plugin-forest を使うことによりこれだけに圧縮した。
<source> type forward </source> <match converted.*> type copy <store> type forest subtype hoop remove_prefix converted <template> hoop_server hoop.server.local:14000 username edge-dev flush_interval 60s output_include_time false output_include_tag false output_data_type attr:hhmmss,vhost,path,method,status,bytes,duration,referer,rhost,userlabel,agent,FLAG,status_redirection,status_errors,rhost_internal,suffix_miscfile,suffix_imagefile,agent_bot add_newline true </template> <case {serviceX,serviceZ}> path /hoop/log/%Y%m%d/__TAG__-%Y%m%d-%H.NODENAME.log </case> <case *> path /hoop/log/%Y%m%d/__TAG__-%Y%m%d-%H.log </case> </store> <store> type forest subtype sampling_filter remove_prefix converted <case {serviceA,serviceX}> interval 100 add_prefix sampled.100 </case> <case *> interval 10 add_prefix sampled.10 </case> </store> </match> <match sampled.**> type forward <server> host watcher01.local </server> <server> host watcher02.local </server> </match>
これで全部。どうよこの画期的にわかりやすい(?)設定! これでタグが増えてもデフォルトルールに従うだけなら設定変更はいらないし、メンテナンスも極めて簡単になって言うことなしですね!!!!!