読者です 読者をやめる 読者になる 読者になる

ほわいとぼーど

ぷろぐらまのメモ帳

fluentd-plugin-elasticsearchでのログ時刻の扱い

Elasticsearch fluentd

これまでの自分のElasticsearch関連の記事では"request_time"という
独自に定義したラベルを用いて登録を行っていました。
一方、fluentdは"time"というラベルを用いるとログの時刻をfluentd内で扱うイベントタイムとみなします。
"time"とした場合と、それ以外でfluentd-plugin-elasticsearchの動作に
違いが見られたのでメモしておきます。

ところで"request_time"としたのには理由があったのですが、
その理由は本筋ではないので最後に書くことにします。


①ログ時刻を通常のラベルを用いて登録する場合

この場合はラベル名を"time"以外にしてパースします。
つまりこれまでの場合は"request_time"としていました。
この時点では他の項目と同じJSON(MessagePack)の一項目なので文字列です。
そしてそのラベルに対してElasticsearchのフィールドを日付型としてMappingをします。
これによりElasticsearch内で"request_time"は日付型フィールドとして扱われるようになりました。
後はこの"request_time"フィールドをKibana3でtime fieldとして設定します。
例えばtimepickerの設定画面では以下になります。

f:id:a3no:20130916234322j:plain

index作成にlogstash形式を指定していた場合(logstash_format true)
logstash形式indexの日付はログをimportしたfluentdで読み込んだ日付になります。

ところで上記画像のtime fieldにはデフォルトでは"@timestamp"が設定されています。
@timestampフィールドはどうやったら使えるのでしょうか?


②fluentdで"time"ラベルを使う

その答えはfluentdの"time"ラベルにありました。
fluentdのパースを以下のように設定したとします。

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

この場合、記事の冒頭でも書きましたがログ時刻はfluentdのイベントタイムとして扱われます。
詳しくは書きませんがJSONボディ部とは異なる扱いになります。

そしてfluentd-plugin-elasticsearchでlogstash形式に設定すると、
"time"が"@timestamp"フィールドに登録されます。
更にこの場合、logstash形式index名もログ日付に追随します。
つまり、ログ日付と同じ日付でlostash-YYYY.MM.DDなindexが作成されます。

fluentdのパースの時点でちゃんと設定しておけば、
自動的にログの内容にあった登録がされるということですね。


なお、logstash形式ではなく自分でindex名を指定した場合は
"@timestamp"フィールドは出来ませんでした。
ただ以前に試した時はログ登録時刻で設定されてた気もするのでココは怪しいです。
(追記)確認しました。logstash_format trueなら@timestampフィールドが作られるが、
そうでない場合は@timestampフィールドは作られない、です。

それから、なぜ最初から"time"を使わず"request_time"にしてたのかですが、
fluentdの正規表現を書くのに@tagomorisさんのサイトを参考にテストしていたのですが、
「require 'time'」を見落として設定してなかったばっかりに
いくらやっても"time"としてパースするのに失敗したので
諦めて文字列なフィールドとして取得するようにしちゃったというオチでした。
間抜けすぎてどうしようもないですね。。。