どうも、かっぱです。
追記
Grafana を手動でポチポチがかったるそうだったので Scripted-dashboard を試してみた。
はじめに
以前に td-agent の monitor_agent を利用してこんなことをやっていたことを記事をツイートして頂いたようでして...
そっか〜 / “sinatra を使って td-agent(fluentd) のバッファの状態をモニタリングするダッシュボードを作ってみた - ようへいの日々精進 XP” http://t.co/GlfffnJTKI
— kenjiskywalker (@kenjiskywalker) 2014, 5月 29
汗...
お、td-monitoring の競合だ! / “sinatra を使って td-agent(fluentd) のバッファの状態をモニタリングするダッシュボードを作ってみた - ようへいの日々精進 XP” http://t.co/KbxQBJFFMn
— そのっつ (SEO Naotoshi) (@sonots) 2014, 5月 29
決して競合とかになろうとか思ったわけではない(笑)のだけども、ツイート頂いたことに感謝しつつ、あまりの不出来さに恥ずかしくなりながらも、次期バージョンwwに向けて Ruby や td-agent の勉強のつもりで取得出来る情報を Graphite と Grafana で可視化してみた。
尚、ちゃんとモニタリングしたい場合にはTreasure Agent Monitoring Serviceを使うと良いと思います!
monitor_agent についておさらい
monitor_agent は何をするのか?
上記を参考にすると...
HTTP経由でJSON形式の内部メトリックを取得できる監視エージェント24220ポートでListenするLTSV形式でも情報を取得することが出来る
どんな情報が取得出来るのか?
- 各ホストで稼働している
td-agentorfluentdのプラグイン情報 - 各
outputプラグインのretry_count/buffer_total_queued_size/buffer_queue_length - 下記の
td_monitor_agentはemit_countも合わせて取得出来る
設定
以下を td-agent.conf に追加して td-agent を再起動するだけ。
<source> type monitor_agent bind 0.0.0.0 port 24220 </source>
取得出来る情報
以下のように HTTP リクエストを投げると...
curl -s http://${TD_AGENT_HOST}:24220/api/plugins.json | jq .
/api/plugin.json でアクセスすると以下のように JSON でレスポンスが返ってくる。
{ "plugins": [ { "config": { "port": "24220", "bind": "0.0.0.0", "type": "monitor_agent" }, "output_plugin": false, "type": "monitor_agent", "plugin_id": "object:3f9bf86637c0" }, { "config": { "tag": "apache.access", "path": "/var/log/httpd/access_log", "format": "apache", "type": "tail" }, "output_plugin": false, "type": "tail", "plugin_id": "object:3f9bf72eedd4" },
/api/plugin でアクセスすると以下のように LTSV でレスポンスが返ってくる。
plugin_id:object:3f9bf86637c0 type:monitor_agent output_plugin:false plugin_id:object:3f9bf72eedd4 type:tail output_plugin:false plugin_id:object:3f9bf72f09b8 type:copy output_plugin:true plugin_id:object:3f9bf72f0508 type:stdout output_plugin:true plugin_id:object:3f9bf72f0080 type:file output_plugin:true buffer_queue_length:0 buffer_total_queued_size:2384070 retry_count:0 plugin_id:object:3f9bf731bcf8 type:file output_plugin:true buffer_queue_length:0 buffer_total_queued_size:2384070 retry_count:0 plugin_id:object:3f9bf731ae48 type:s3 output_plugin:true buffer_queue_length:0 buffer_total_queued_size:13183110 retry_count:0
Tresure Data が提供するモニタリングサービスについて
現時点ではベータ版となっているようだが Tresure Data がモニタリングサービスを提供している。

以下のようにホストのリソース情報も確認することが出来る。

設定は monitor_agent と同様 td-agent.conf に以下を追加してプロセスを再起動するだけで監視が開始される。(※apikey は事前にダッシュボードで取得しておく必要がある)
<source> type td_monitor_agent apikey xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx instance_id xxxxxxx disable_node_info true </source>
disable_node_info を true にしておくとホストのリソース情報以外の情報を送信する(デフォルトは false になっている)。また、instance_id を指定しない場合には td-agent.conf のパスが表示されるようなので必要に応じて instance_id は設定しておいた方がたくさんのホストを管理する場合には良いかと思われる。
詳細については...
- Treasure Agent Monitoring Service (ベータ)
- treasure-data/fluent-plugin-td-monitoring
- Treasure Agent MonitoringをProduction環境で使い始めた件
を見る。
で、どうするの?
こんな感じで...
各処理をどの位の粒度でメソッド化すれば良いのかも解らず、変数のスコープについてもシェルスクリプト的な使い方になってしまっているので突っ込みどころ満載。
大きな壁
monitor_agent は JSON や LTSV で返ってくることは解ったが、そのレスポンスからプラグイン毎で retry_count / buffer_total_queued_size / buffer_queue_length を取得する(JSON をパースする)のが(自分にとって)至難の技であることは間違い無かったが試行錯誤の上で以下のようにした。
返ってきた JSON の plugin に含まれる数(size メソッド)をプラグインの数として、そのプラグイン数分(実際には配列は 0 から始まるので取得したプラグイン数からマイナス 1 をする)のループ処理で JSON からプラグイン毎の必要な値を取得した。
Graphite へのメトリクスを投げる
これは意外に簡単だった。幾つか Gem が存在する中で以下の Gem を利用した。
require 'graphite-api' しておいて以下のようなメソッドで処理するようにした。
def post_graphite(host, type, rtc, bql, btqs)
client = GraphiteAPI.new( graphite: $graphite_host )
client.metrics(
"#{host}.#{type}.retry_count" => rtc,
"#{host}.#{type}.buffer_queue_length" => bql,
"#{host}.#{type}.buffer_total_queued_size" => btqs
)
end
Graphite が . ピリオドをメトリクスパスの区切りとして利用する為 host という変数は . を - に変換する処理を行っている。
実際に Graphite には以下のように登録される。

Grafana だと...
以下のような感じになる。

ホストが増えてくると手動でポチポチするのが耐えられなくなると思われる...(そこで Grafana の Scripted-dashboardsの出番だったりするのかな...)
最後に
JSONをパースして結果をどうこうするという勉強にはなったが、もっと効率とか見栄え、メンテナンスし易い書き方を模索したい