Kibana向けFluentd設定例①アクセスログ可視化
どちらかというとFluentdの設定の話なのですが、
Kibana上でデータを扱うことも考慮して、くらいの感じで。
アクセスログの可視化はよくあるやつなので細かい所は飛ばします。
1段目:ログ収集先からの転送設定
<source> type tail path /path/to/apache_access.log format /(?<message>.*)/ pos_file /var/log/td-agent/apache_access.pos tag apache.access.HOSTNAME </source> <match **> type forward flush_interval 1s <server> host FORWARD_HOST </server> </match>
以前の記事ではin_tail
にパースを書いていましたが、
パラメータが増減するのに毎回対応したり、パースするための負荷がかかることを考えると、
ログ収集ホスト上のin_tail
で正規表現をゴリゴリ書くのはあまり得策じゃない気がしています。
そこで1行を1メッセージとして送るような設定にしています。
fluentdが0.10.39以降であればformat none
とすることで同様のことが出来ます。
収集ログに日付が付与する場合はin_tail
の変わりにfluent-plugin-tail-ex
を使うといいですね。
2段目:ログ受信側パース
<source> type forward </source> <match apache.access.**> type parser add_prefix parsed format /(正規表現)/ time_format %d/%b/%Y:%H:%M:%S %z key_name message </match>
ここからはログ解析サーバ上です。
forwardされたイベントをfluent-plugin-parser
でパースします。
key_name
には解析したいフィールド名、ここではmessageになります。
format
には正規表現を書きますが、ログフォーマット側でLTSV
にしておけば
format ltsv
するだけでよくて楽ですね。
3段目:データ加工
<match parsed.apache.access.**> type record_reformer output_tag reformed.${tags[1]}.${tags[2]} ip ${forwardedfor[/([^,]*),*/,1]} method ${req[/^([^ ]*) .*$/,1]} uri ${req[/^[^ ]* ([^ ]*) .*$/,1]} sessionId ${req[/^[^ ]* \/path\/to\/api\?sessinId\=(.*?)(\¶m\=[^ ]*)? .*$/,1]} log_host ${tags[3]} </match>
2段目の時点で生のデータを扱う分には十分なのですが、
時にはデータ加工したい場合があり、fluent-plugin-record-reformer
が便利です。
整形したデータを生のレコードに+αしてくれるのが良いです。
しかも複数項目書けます。
例えば「req (referer情報)」に「GET /path/to/api?sessionId=10000001¶m=1 HTTP/1.0」
という情報が入っているとして、1つ目をmethod、2つ目の部分をuriとして取り出しています。
あるいはuri全体ではなく、getパラメータに入っているsessionIdを取り出したりします。
またforwardedforにはproxyを通すとカンマ区切りで複数のアドレスが入っているので、
1番先頭だけを取り出して続くgeoipの判定に使います。
整形は${フィールド名[/(正規表現)/,n]}
のように書いて取り出したい部分をグループ化して
nで何番目のグループを取り出したいかを指定します。
この辺りはrubyの正規表現のとり扱いになるので、
rubyのコンソールとかで少し試してみればすぐわかると思います。
log_hostは以前の記事でfluent-plugin-elasticsearch
上でtag_key @log_name
で行っていた
収集元ホストの登録をここで行うように変更したものです。
fluent-plugin-elasticsearch
のtag_key
だとtagをかなりうまいこと編集する必要がありましたが、
tags
使うと簡単に必要な部分だけ取り出せますね。
${tags[3]}
はtagをカンマで分割した4番目を取得しています。
なお、fluent-plugin-record-reformer 0.1.1
からはfluent-plugin-forest
と表記を合わせて
tag_parts
が使えるようになります。
今回の記事のポイントはほぼ3段目に集約されます。
methodやuriはログフォーマットで直接指定すれば加工しなくても済みますが、
既に運用されているような場合に出力元に変更を加えるのが簡単じゃない場合も多いし、
そういう場合に受け取った先で簡単に加工できるという例です。
4段目:
<match reformed.**> type geoip geoip_lookup_key ip enable_key_country_code geoip_country add_tag_prefix es. </match>
fluent-plugin-geoip
用の設定。
pluginとは別にライブラリのインストールが必要なので注意してください。
ここまで見てきてplugin毎にtagの扱い方が異なるので若干混乱しますね。
5段目:
<match es.reformed.**> type forest subtype elasticsearch remove_prefix es.reformed <template> type_name ${tag} host localhost port 9200 logstash_format true logstash_prefix logstash flush_interval 10s </template> </match>
fluent-plugin-elasticsearch
はplaceholderに対応してないのでfluent-plugin-forest
推奨。
fluent-plugin-record-reformer
でのoutput_tag
との組み合わせにより
type_name
に入る値は今回の例では「apache.access」となります。
以前はtype_name、host名なんかを登録するのにtag操作が結構大変でしたが、
tagのplaceholderが便利になったお陰でかなり楽になりました。
fluentdではこんな感じでログ出力をいい感じに加工してデータストアに投入できます。
Kibana関係ないじゃないかって言われそうですが、Kibanaで表示する内容を考えた結果、
fluent-plugin-record-reformer
で途中で加工するのが便利っていう話です。
Kibanaで解析するときにユーザIDやセッションIDみたいなのをfacet集計したい事例はよくあると思うので、
切り出しておいてmappingをnot_analyzed
で用意するとランキング集計しやすいですね。
Kibana上ではterms
パネルで対象項目を指定するだけで表示できます。
デフォルトで5項目になってるけど数字を増やせばもっと表示可能。
(1000くらいにはしたことある)
参考例。本当はもっとランキングぽいの出したかったけど手元に出せるデータがなく。
3つ例を書くつもりだったけど、調査修正して動確してたらハマって時間かかってしまった。
record_reformerは前に設定書いた時点ではtag_parts
使えてたんだけど、
手元で実施したら0.1.1ではなく0.1.0が入ってしまって使えなかったり、
Elasticsearch-1.0.0.Beta2を使ったら0.90.7で動いてたmapping templateが動かなかった。
記事は書いたものの色々と調査するものが増えてしまった・・・