oranie's blog

旧:iをgに変えると・・・なんだっけ・・・

fluentd tailプラグインの仕様について

ウィークリーFluentdユースケースエントリリレー #1の記事です。

fluentdを使う上で最も多くの人が使うであろう基本中の基本、tailプラグインの仕様を日本語にした内容+以前教えてもらった内容をまとめてみます。
公式ドキュメント:http://fluentd.org/doc/plugin.html#tail
Githubhttps://github.com/fluent/fluentd/blob/master/lib/fluent/plugin/in_tail.rb

tailプラグインLinuxコマンドで言う「tail -F」と同じような挙動を取る事により、ファイルに追記された情報をfluentd内に取り込む事が出来ます。追記されたかどうかはIOイベントを読み取って動作します。
簡単に説明すると

1)新規に設定されたファイルは終端から読む
2)ログローテーションされたら次のファイルを先頭から読む
3)再起動時には前回読み終わった位置から読み始める(位置はファイルに保存しておく)

という動きになります。その為、一時的にfluentdを停止してもファイルが失われていない or ローテートされていなければ処理は最後に読み込んだ所から問題無く再開されます。

読み込んだデータは指定したフォーマットに変換してfluentd内で扱う事が可能になります。例として

- 127.0.0.1 - - [06/Oct/2012:17:00:12 +0900] "GET /server-status?auto HTTP/1.0" 200 48 "-" "ApacheStats/0.4 wget/1.8" 221

という内容のログファイルを読み取り、tailプラグインが指定された正規表現に基づいたparseをする事で

2012-10-06T17:00:12+09:00       apache.access   {"XFF-host":"-","host":"127.0.0.1","user":"-","method":"GET","path":"/server-status?auto","status":"200","size":"48","referer":"-","agent":"ApacheStats/0.4 wget/1.8","response_time":"221"}

という構造のデータに変換します。これによりjson内での任意の項目を他のプラグインで処理する事が可能になります。(例えば、response_time項目だけを集計して中の値を計算したりなど。)

構文は以下の形になります。

<source>
  type tail
  path /var/log/httpd-access.log
  tag apache.access
  format apache
</source>

それぞれの内容を以下に解説します。

path

path(必須): tailする対象のファイルパスを指定します。これは必須です。「,」で区切って複数記述することが出来ます(今ドキュメント読んで気づいた・・・。)

tag

tag(必須) : tailしたデータのtagを指定します。これは必須です。

format

format : tailする対象のデータ形式をすでにあるテンプレート名か正規表現 ‘/’で記述します。
正規表現は、少なくとも一つの名前付き後方参照 (?PATTERN)を指定する必要があります。正規表現で "time"と指定した項目は、ログの時間として使用されます。time_formatパラメータを使用して時刻の書式を指定することができます。正規表現内に'tag'と指定した項目がある場合は、「tagパラメータで指定した値」+「tag項目の値」がログのタグに付与されます。
用意されているテンプレートは「apache」と「syslog」の二種類です。
apacheテンプレートは以下の正規表現をformatに記述した場合と同じ動作になります。host, user, time, method, path, code, size, referer, agentをfieldとしてfluentdに取り込みます。

format /^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")?$/
time_format %d/%b/%Y:%H:%M:%S %z

これはapacheのデフォルトログフォーマットを想定しているテンプレートなので、もしApacheログフォーマットに項目の追加や、区切り文字の変更等のフォーマット変更を行なっている場合は使えないでしょう。

syslog(/var/log/syslog等のsyslogが出しているログなどを想定)テンプレートは以下の正規表現と同じ動作になります。
time, host, ident, messageをfiledとしてfluentdに取り込みます。

format /^(?<time>[^ ]* [^ ]* [^ ]*) (?<host>[^ ]*) (?<ident>[a-zA-Z0-9_\/\.\-]*)(?:\[(?<pid>[0-9]+)\])?[^\:]*\: *(?<message>.*)$/
time_format %b %d %H:%M:%S
time_format

time_format(任意): timeフィールドの形式。このパラメータは、'time'という項目がデータに含まれていて、それが自動的に解析できない場合にのみ必要です。詳細はTimeクラスを見ましょう。

逆に言うと「time項目の指定がデータ内に無い、もしくは指定されても解析が出来なかった場合、fluentdのログ時間には処理した時間が付与される」という事になります。
例えばそのログが11:59に出力されたにも関わらず、fluentdで読み込んだ時間が16:00だったら

2012-10-06T16:00:15+09:00       apache.access   {"XFF-host":"-","host":"127.0.0.1","user":"-","method":"GET","path":"/server-status?auto","status":"200","size":"48","referer":"-","agent":"ApacheStats/0.4 wget/1.8","response_time":"246","time":1349506815}

という日付が付与される事になります。

rotate_wait

rotate_wait(任意:デフォルト5秒) :
in_tail はログを取りこぼさないようにもしローテートでファイルが切り替わっても(fdを開きっぱなしにして)前に読んでいたファイルの監視をしばらく続ける。デフォルトで5秒後にファイルを閉じて次のファイルを読む。これはアプリケーションが実際にログファイルを開き直すまでに追記されるログを取りこぼさないようにする為。この間隔を調整できる項目になります。

pos_file

pos_file(任意:デフォルト:パス設定無し): tailしているファイルのどこまでtailしたかという位置情報をファイルに保存する場合、そのファイルパスを記述します。

  pos_file /var/log/td-agent/tmp/access.log.pos

と記述することで、/var/log/td-agent/tmp/access.log.pos内に以下のようなデータを保存します。

/var/log/httpd/access_log       00000000001c22fd        0032026b
/tmp/access_log 00000000000025a8        00340008

これでもしもfluentdがダウンしても元の場所からtailが再開できます。もしこのデータに基づいて探索した際にファイル自体が無かったりした場合は、このデータは破棄して新しい位置情報を保存します。
ちなみに、このパラメータを設定しないと「this parameter is highly recommended to save the position to resume tailing.」というログが出ます。そこまで重要なファイルなので/tmp/とかにデフォルトで出してあげても良い気もします。

最後に良くある間違い。

ちゃんと指定したファイルが読めない

パーミッションは大丈夫?ファイル自体はread権限付いていても、ディレクトリがfluentd実行ユーザで許可されていないとか。「 plugin/in_tail.rb:262:initialize: following tail of /var/log/httpd/access_log」というようなログが出ているか確認しましょう。あと、普通にtypo無いかもチェックしましょう。

ファイルはちゃんとopen出来ているのに、データが取り込めていない

正規表現大丈夫?一度テストしてみると良いと思います。
Fluentdのformat(正規表現)の作り方について試行錯誤中
等を参考に自分でfluentdで指定した正規表現と同じparseをする簡単なスクリプトを作って、対象のログがちゃんとparseされるかテストしてみましょう。
僕はperlですがこんな感じのスクリプトを使って正規表現がちゃんと大丈夫か確認してconfigに記載しています。

次の記事はstudio3104 さんです!!宜しくお願いします!