最近、大ブームな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などなどもあるっぽいです。
また気がついたことあったら追記/修正していきます!