ようへいの日々精進XP

よかろうもん

td-agent(fluentd) の monitor_agent で取得出来る情報を Graphite + Grafana で見る試み

どうも、かっぱです。

追記

Grafana を手動でポチポチがかったるそうだったので Scripted-dashboard試してみた。

はじめに

以前に td-agentmonitor_agent を利用してこんなことをやっていたことを記事をツイートして頂いたようでして...

汗...

決して競合とかになろうとか思ったわけではない(笑)のだけども、ツイート頂いたことに感謝しつつ、あまりの不出来さに恥ずかしくなりながらも、次期バージョンwwに向けて Rubytd-agent の勉強のつもりで取得出来る情報を Graphite と Grafana で可視化してみた。

尚、ちゃんとモニタリングしたい場合にはTreasure Agent Monitoring Serviceを使うと良いと思います!


monitor_agent についておさらい

monitor_agent は何をするのか?

上記を参考にすると...

  • HTTP 経由で JSON 形式の内部メトリックを取得できる監視エージェント
  • 24220 ポートで Listen する
  • LTSV 形式でも情報を取得することが出来る

どんな情報が取得出来るのか?

  • 各ホストで稼働している td-agent or fluentdプラグイン情報
  • output プラグインretry_count / buffer_total_queued_size / buffer_queue_length
  • 下記の td_monitor_agentemit_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 がモニタリングサービスを提供している。

f:id:inokara:20140531064529p:plain

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

f:id:inokara:20140531072133p:plain

設定は monitor_agent と同様 td-agent.conf に以下を追加してプロセスを再起動するだけで監視が開始される。(※apikey は事前にダッシュボードで取得しておく必要がある)

<source>
  type td_monitor_agent
  apikey xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  instance_id xxxxxxx
  disable_node_info true
</source>

disable_node_infotrue にしておくとホストのリソース情報以外の情報を送信する(デフォルトは false になっている)。また、instance_id を指定しない場合には td-agent.conf のパスが表示されるようなので必要に応じて instance_id は設定しておいた方がたくさんのホストを管理する場合には良いかと思われる。

詳細については...

を見る。


で、どうするの?

こんな感じで...

各処理をどの位の粒度でメソッド化すれば良いのかも解らず、変数のスコープについてもシェルスクリプト的な使い方になってしまっているので突っ込みどころ満載。

大きな壁

monitor_agentJSONLTSV で返ってくることは解ったが、そのレスポンスからプラグイン毎で retry_count / buffer_total_queued_size / buffer_queue_length を取得する(JSON をパースする)のが(自分にとって)至難の技であることは間違い無かったが試行錯誤の上で以下のようにした。

返ってきた JSONplugin に含まれる数(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 には以下のように登録される。

f:id:inokara:20140531075832p:plain

Grafana だと...

以下のような感じになる。

f:id:inokara:20140531075900p:plain

ホストが増えてくると手動でポチポチするのが耐えられなくなると思われる...(そこで GrafanaScripted-dashboardsの出番だったりするのかな...)


最後に

  • JSON をパースして結果をどうこうするという勉強にはなったが、もっと効率とか見栄え、メンテナンスし易い書き方を模索したい