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 プラグインを使えるようにしましょう
<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 ではタグ名にする方法が一番簡単なのでそういう方針で行きます
まずなにはともあれログを解析します
を使います
デバッグのためにあらかじめ設定の最後に以下を書いておきます
<match **>
type stdout
</match>
こうしておけば match しなかったものはすべて標準出力に出力されます
<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 プラグインを使ってタグを書き換えます
<match src.service.access>
type rewrite_tag_filter
remove_tag_prefix src
rewriterule1 host (.+) ${tag}.$1
</match>
${tag}
で現在のタグが取得できます
なので今回の場合,ホスト名が host ならタグが service.access.host
に書き換えられます
データを解析する
ログから今回グラフにしたいデータを取得します
これを参考にステータスコードとレスポンスタイムを取得します
<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 プラグインと組み合わせてみます
<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 で情報を引き継ぐのはタグくらいしかないのでタグにどういうデータを載せるのか考えて一つ一つ整理して確認しながら書いていきましょう