Edited at

fluentdでホスト名付きでログを受け取って解析してグラフにしたい

More than 5 years have passed since last update.

fluentd で Nginx などのログを解析してホスト名付きで growthforecast に POST してグラフを描いていました

しかしそのログを解析しているサーバーは AP サーバーでユーザーからのリクエストを処理しています

なのでログファイルを正規表現で parse する fluentd の処理は CPU を消費していました

そこで各 AP サーバーから fluentd でログを parse せずにそのまま他のサーバーに送信してそのサーバーがログの parse と growthforecast へ POST するようにしようと考えました

その時に各ホストは今まで通り別にグラフを描こうと思ったのですが想像以上に苦戦したので書いてみます

fluentd はほぼ初めてなので間違っているところやおかしなところがあればぜひ指摘して欲しいです


fluentd で parse せずに forward する

fluentd の in_tail プラグインでは format none にすればログを正規表現で parse しないでそのまま読み込むことができます

また forward プラグインだとホスト名が付与されないので以下のファイルを plugin ディレクトリに入れて forward_with_hostname プラグインを使えるようにしましょう


access_log_forward.conf

<source>

type tail
tag ap_front.access.service
path /var/log/nginx/access.log
pos_file /var/log/nginx/access.log.pos
format none
</source>

<match ap_front.access.service>
type forward_with_hostname
flush_interval 1s

buffer_type file
buffer_path /var/tmp/fluentd/buffer/ap.activity.*.buffer
buffer_chunk_limit 2m
buffer_queue_limit 128

<server>
name admin
host admin
</server>
</match>


こんな感じにすると admin ホストにログを parse せずそのまま送ることができます

これで message キーにログが一行入って host キーにホスト名が入った状態でログを受け取ることができます

またこのような使い方の場合 fluent-agent-lite の方が軽くていいと思うのでこちらにいずれ乗り換えるかもしれません


受け取ったサーバーでログを解析する

ログを受け取れるようになったのでここから処理を書いていきます

忘れてはいけないのはホスト名を最終的に growthforecast に投げるので最後まで保持しなければならない点です

ここは fluentd ではタグ名にする方法が一番簡単なのでそういう方針で行きます

まずなにはともあれログを解析します

を使います

デバッグのためにあらかじめ設定の最後に以下を書いておきます


fluentd.conf

<match **>

type stdout
</match>

こうしておけば match しなかったものはすべて標準出力に出力されます


access_log_parse.conf

<source>

type forward
</source>
<match ap_front.access.service>>
type parser
tag src.service.access
format ltsv
key_name message
reserve_data yes
</match>

format には正規表現か ltsv などが書けます

ログ自体はデフォルトだと message キーに格納されているので key_name message を指定します

またここで重要なのは reserve_data yes という指定です

このままだと parse した結果だけが引き継がれるので折角送ったホスト名が脱落してしまいます

reserve_data yes を指定すると parse される前の元データもそのまま引き継がれます

なのでホスト名はそのまま host キーに入った状態で引き継がれます


条件でタグを書き換える

fluentd でデータを引き継ぐのはタグでやるのが一番簡単です

そこでホスト名をタグに含めます

rewrite_tag_filter プラグインを使ってタグを書き換えます


rewrite_tag.conf

<match src.service.access>

type rewrite_tag_filter
remove_tag_prefix src
rewriterule1 host (.+) ${tag}.$1
</match>

${tag} で現在のタグが取得できます

なので今回の場合,ホスト名が host ならタグが service.access.host に書き換えられます


データを解析する

ログから今回グラフにしたいデータを取得します

これを参考にステータスコードとレスポンスタイムを取得します


analytics.conf

<match service.access.*>

type copy

<store>
type numeric_monitor
count_interval 60
aggregate tag
output_per_tag yes
tag_prefix monitor
monitor_key request_time
output_key_prefix response_time
percentiles 99
</store>

<store>
type datacounter
count_interval 60
aggregate tag
output_per_tag yes
tag_prefix count
outcast_unmatched true
count_key status
pattern1 200 ^200$
pattern2 304 ^304$
pattern3 403 ^403$
pattern4 404 ^404$
pattern4 499 ^499$
pattern5 500 ^500$
pattern6 504 ^504$
pattern7 5xx ^5\d\d$
</store>

</match>


それぞれのプラグインの使い方は以下を参考にしてください

基本的にタグを書き換えるような機能は各プラグインに依存しています

大体のプラグインには prefix を付けるなどの機能には対応していますが,自由に書き換えたい場合は先程紹介した rewrite_tag_filter などそれ専用のプラグインに頼る必要があります

今回のようにホスト名をタグに付けたいという場合は事前にタグ名にホスト名を付与することが重要です


growthforecast に POST する

growthforecast に POST するために以下のプラグインを使います

この際にタグ名からホスト名を取得する必要があるので今回は forest プラグインと組み合わせてみます


growthforecast.conf

<match monitor.service.access.*>

type forest
subtype growthforecast
<template>
gfapi_url http://localhost:5125/api/
graph_path service/${tag_parts[-1]}/${key_name}
name_key_pattern .
enable_float_number true
</template>
</match>

<match count.service.access.*>
type forest
subtype growthforecast
<template>
gfapi_url http://localhost:5125/api/
graph_path service/${tag_parts[-1]}/${key_name}
name_key_pattern .
enable_float_number true
</template>
</match>


forest プラグインを使うと ${tag_parts[-1]} のようにタグの一部を簡単に呼び出すことができます


まとめ

fluentd は様々なプラグインを組み合わせることで柔軟な設定が可能ですが,どのプラグインをどのように組み合わせればいいのかが場合によっては煩雑になります

fluentd で情報を引き継ぐのはタグくらいしかないのでタグにどういうデータを載せるのか考えて一つ一つ整理して確認しながら書いていきましょう

Fluentdの設定を考えるときはこんなかんじで考えると便利 - Qiita