最近、大ブームなFluentd+GrowthForecastを試し始めました!
で、サクッと『GrowthForecastで複合グラフ作ったりグラフいじったりするの┌┤´д`├┐ダル〜』となりました。
なんとかサボれないかなーとソースを眺めていたら、JSON APIっぽいものがあるのに気づきました。
GrowthForecast:Web.pm
@tagomorisさんが最近コミットしたようです。
add json api to get/list/edit graph and complex, and to create complex
それっぽいURL叩くとJSONが返ってくる!
[mikeda@fluentd01 api]$ curl -s http://localhost:5125/json/list/graph
[{"service_name"=>"test","graph_name"=>"percentile_95","section_name"=>"access","id"=>88},{"service_name"=>"test","graph_name"=>"avg","section_name"=>"access","id"=>87},{"service_name"=>"test","graph_name"=>"5xx_count","section_name"=>"access","id"=>86},...というわけでザクっとひと通り使ってみました。
/json/list/graph:グラフのリストを取得
[mikeda@fluentd01 api]$ curl -s http://localhost:5125/json/list/graph | ruby -r json -r pp -e 'pp JSON.parse(ARGF.read)'
...
{"service_name"=>"test",
"graph_name"=>"3xx_count",
"section_name"=>"access",
"id"=>80},
{"service_name"=>"test",
"graph_name"=>"2xx_count",
"section_name"=>"access",
"id"=>78},
...パス情報とIDだけが返ってくるようです。
/json/graph/:グラフの詳細情報を取得
[mikeda@fluentd01 api]$ curl -s http://localhost:5125/json/graph/78 | ruby -r json -r pp -e 'pp JSON.parse(ARGF.read)'
{"llimit"=>-1000000000,
"number"=>0,
"stype"=>"AREA",
"mode"=>"gauge",
"complex"=>false,
"adjustval"=>"1",
"created_at"=>"2012/12/26 12:05:35",
"color"=>"#99cc33",
"service_name"=>"test",
"gmode"=>"gauge",
"ulimit"=>1000000000,
"section_name"=>"access",
"id"=>78,
"graph_name"=>"2xx_count",
"description"=>"",
"sort"=>0,
"unit"=>"",
"sulimit"=>100000,
"updated_at"=>"2012/12/26 15:16:07",
"adjust"=>"*",
"sllimit"=>-100000,
"type"=>"AREA"}かなりいろんな情報があります。また今度調べてみよう
/json/list/complex:複合グラフのリストを取得
[mikeda@fluentd01 api]$ curl -s http://localhost:5125/json/list/complex | ruby -r json -r pp -e 'pp JSON.parse(ARGF.read)'
...
{"service_name"=>"test",
"graph_name"=>"response_time",
"section_name"=>"access",
"id"=>7},
{"service_name"=>"test",
"graph_name"=>"access_status",
"section_name"=>"access",
"id"=>44},
.../json/list/graphと同じですね。
/json/complex/:複合グラフの詳細情報を取得
[mikeda@fluentd01 api]$ curl -s http://localhost:5125/json/complex/44 | ruby -r json -r pp -e 'pp JSON.parse(ARGF.read)'
{"number"=>0,
"complex"=>true,
"created_at"=>"2012/12/30 03:30:55",
"service_name"=>"test",
"section_name"=>"access",
"id"=>44,
"graph_name"=>"access_status",
"data"=>
[{"gmode"=>"gauge", "stack"=>false, "type"=>"AREA", "graph_id"=>78},
{"gmode"=>"gauge", "stack"=>true, "type"=>"AREA", "graph_id"=>80},
{"gmode"=>"gauge", "stack"=>true, "type"=>"AREA", "graph_id"=>83},
{"gmode"=>"gauge", "stack"=>true, "type"=>"AREA", "graph_id"=>86}],
"sumup"=>false,
"description"=>"アクセス数(レスポンスコード)",
"sort"=>10,
"updated_at"=>"2012/12/30 03:30:55"}こっちはわかりやすいですね。
/json/list/all:全グラフ、複合グラフの詳細情報を取得
[mikeda@fluentd01 api]$ curl -s http://localhost:5125/json/list/all | ruby -r json -r pp -e 'pp JSON.parse(ARGF.read)'
...
{"number"=>0,
"llimit"=>-1000000000,
"mode"=>"gauge",
"stype"=>"AREA",
"complex"=>false,
"adjustval"=>"1",
"service_name"=>"test",
"created_at"=>"2012/12/26 12:05:35",
"gmode"=>"gauge",
"color"=>"#99cc33",
"section_name"=>"access",
"ulimit"=>1000000000,
"id"=>78,
"graph_name"=>"2xx_count",
"description"=>"",
"sort"=>0,
"unit"=>"",
"sulimit"=>100000,
"updated_at"=>"2012/12/26 15:16:07",
"adjust"=>"*",
"type"=>"AREA",
"sllimit"=>-100000},
...
{"number"=>0,
"complex"=>true,
"created_at"=>"2012/12/19 09:43:37",
"service_name"=>"test",
"section_name"=>"dev04",
"id"=>1,
"graph_name"=>"access",
"data"=>
[{"gmode"=>"gauge", "stack"=>false, "type"=>"AREA", "graph_id"=>"2"},
{"gmode"=>"gauge", "stack"=>true, "type"=>"AREA", "graph_id"=>"3"},
{"gmode"=>"gauge", "stack"=>true, "type"=>"AREA", "graph_id"=>"4"},
{"gmode"=>"gauge", "stack"=>true, "type"=>"AREA", "graph_id"=>"5"}],
"sumup"=>false,
"description"=>"アクセス数",
"sort"=>19,
"updated_at"=>"2012/12/19 09:43:37"}]豪快ダンプですね。通常のグラフか複合グラフ化はcomplexフラグで判別するようです。
/json/create/complex:複合グラフを作成
助かった!とばかりに全サービスに特定の複合グラフを作るスクリプトを作りました。
https://gist.github.com/4406576
ちょっと個人的な用途向けすぎなので、もうちょっとベーシックなサンプルを書いてみました。
#!/usr/lib64/fluent/ruby/bin/ruby # -*- encoding: utf-8 -*- require 'net/http' require 'json' require 'pp' GF_HOST = 'localhost' GF_PORT = 5125 # 複合グラフに統合するグラフ from_graphs= [ {:path => 'test/access/2xx_count', :gmode => 'gauge', :stack => true, :type => 'AREA'}, {:path => 'test/access/3xx_count', :gmode => 'gauge', :stack => true, :type => 'AREA'}, {:path => 'test/access/4xx_count', :gmode => 'gauge', :stack => true, :type => 'AREA'}, {:path => 'test/access/5xx_count', :gmode => 'gauge', :stack => true, :type => 'AREA'}, ] # 複合グラフ to_complex = { :path => 'test/access/access_status', :description => 'アクセス数(レスポンスコード)', :sort => 10, } def api_get(path) json = '' Net::HTTP.start(GF_HOST, GF_PORT) do |http| res = http.get(path) json = res.body end JSON.parse(json) end def api_post(path, data) json = JSON.generate(data) Net::HTTP.start(GF_HOST, GF_PORT) do |http| res = http.post(path, json) pp res.body end end # 全グラフデータの取得 #/api/<sercice>/<section>/<graph>で個別に取るほうが簡単そうだからあとで直す。 all_graphs = api_get('/json/list/graph') # POSTデータの作成 graph_data = [] from_graphs.each do |from_graph| service, section, graph = from_graph[:path].split('/') graph_id = all_graphs.detect{|g| g['service_name'] == service && g['section_name'] == section && g['graph_name'] == graph }['id'] graph_data << { :gmode => from_graph[:gmode], :stack => from_graph[:stack], :type => from_graph[:type], :graph_id => graph_id } end to_service, to_section, to_graph = to_complex[:path].split('/') post_params = { :service_name => to_service, :section_name => to_section, :graph_name => to_graph, :description => to_complex[:description], :sort => to_complex[:sort], :data => graph_data } # 複合グラフ作成 pp post_params api_post('/json/create/complex', post_params)
/json/edit/graph/:グラフの設定を変更
これもサンプルを。
同じグラフなのに、サービスごとに色がバラバラだと見づらいですよね。


作成時に指定しないとランダムになるっぽいです。
... my @colors = List::Util::shuffle(qw/33 66 99 cc/); $color ||= '#' . join('', splice(@colors,0,3)); ...
とりあえず上のグラフの色を、こんな感じに変更してみましょう!
- 2xx_count:青
- 3xx_count:緑
- 4xx_count:黄色
- 5xx_count:赤
ソースコード
# -*- encoding: utf-8 -*- require 'net/http' require 'json' require 'pp' GF_HOST = 'localhost' GF_PORT = 5125 SERVICE_NAME = 'test' SECTION_NAME = 'access' GRAPH_COLORS = { '2xx_count' => '#1111cc', '3xx_count' => '#11cc11', '4xx_count' => '#cccc11', '5xx_count' => '#cc1111', } def api_get(path) json = '' Net::HTTP.start(GF_HOST, GF_PORT) do |http| res = http.get(path) json = res.body end JSON.parse(json) end def api_post(path, data) json = JSON.generate(data) Net::HTTP.start(GF_HOST, GF_PORT) do |http| res = http.post(path, json) pp res.body end end GRAPH_COLORS.each do |graph_name, color| path = [SERVICE_NAME, SECTION_NAME, graph_name].join("/") graph_data = api_get("/api/#{path}") # meta情報に変なのが入っちゃうのでいらなそうなの削除 %w[number adjust adjustval meta md5 created_at updated_at data unit mode].each{|key| graph_data.delete(key) } graph_data['color'] = color pp graph_data api_post("/json/edit/graph/#{graph_data['id']}", graph_data) end
でけた!!!
/json/edit/complex/:複合グラフの設定を変更
上と似たようなもんなので割愛!!!
まとめ?
だいぶ手が抜けそうで安心しました!
他にもRRDの設定やデータをダンプするAPIなどなどもあるっぽいです。
また気がついたことあったら追記/修正していきます!
