雪にかこまれた温泉宿からこんちには。
クライアントライブラリを書いてからblogエントリにしようと思ったらこんな素敵エントリを書かれてしまった、くやしい……!
GrowthForecastでAPI使って複合グラフ作ったり、グラフの色を変えたりしてみた - mikedaの日記
みんな大好き GrowthForecast ですが、じつに簡単にグラフを作れてしまえるので調子に乗って作りまくった挙句、複合グラフを作る手作業で死んだり色を揃える作業で死んだりそもそも無いといけないグラフが本当にあるのか確認するのが面倒でうっちゃってたりするようなことがあります。必ずあるはずです。ですよねー。あるある。
ということでグラフの存在を確認したりグラフ設定を変更したりそもそも無ければ作ったり、という作業をコードからやりたかったので、ひとそろい作った。とりあえず GrowthForecast に JSON API を作り、それからクライアントライブラリも。クライアントライブラリはPerlとRubyでほぼ同機能のものを。
Net::GrowthForecast - A client library for awesome visualization tool GrowthForecast - metacpan.org
growthforecast | RubyGems.org | your community gem host
GrowthForecast本体のドキュメントにAPIの記述を追加してないなー。きっとkazeburoさんがやってくれる……。(もしくは書くのでリポジトリか何か教えてください > kazeburo)
なお、GrowthForecastのコードが相応に新しくないと JSON APIが存在しないのでクライアントライブラリも使えません。超具体的には、現在のリリースの最新版である v0.33 もしくはそれ以降のものを使用しましょう。
ちなみに最初はクライアントライブラリをGrowthForecastに手を入れない形で(HTMLをスクレイピングして)作ろうとしてたんだけど、あまりにいろいろつらくて途中で一度全部捨てた。一度全部捨ててからここまでの完成のほうがはるかに早かった……。
JSON API
簡単に書くとこんな感じ。なお対象が存在しない場合、単数が返るcallについては404が、リストが返るcallについては空リストが返る。*1
- GET /json/list/graph
- 存在するグラフの一覧を取得する、複合グラフは含まない
- service_name, section_name, graph_name および id (graphで一意) の組のリスト
- GET /json/list/complex
- 存在する複合グラフの一覧を取得する
- service_name, section_name, graph_name および id (complexで一意)*2 の組のリスト
- GET /json/graph/:id および /json/complex/:id
- グラフの詳細情報を返す、この表現形式が edit/delete でも使われる
- GET /json/list/all
- 全グラフ(複合グラフを含む)の詳細情報のリストを返す
- POST /json/edit/graph/:id および /json/edit/complex/:id
- POST /json/create/complex
- 複合グラフを作成する、設定内容は複合グラフの詳細情報形式で content body (JSON) で送る
いくつか注意点があります。
クライアントライブラリ
JSON APIはシンプルな実装を心掛けたので、それだけだと以下のように少し使いにくいです。
- グラフ作成は複合グラフしかない
- 通常のグラフは値をポストすれば作られるしね
- グラフ削除が複雑
- 複合グラフの削除は対象を id で指定するが通常のグラフは service/section/graph で指定する
なので、クライアントライブラリを作りました。とりあえず必要な人が多そうな*3PerlとRubyで。CPANとrubygems.orgに上げてあります。
主に以下のような機能があります。機能名からなんとなく察してください。グラフ追加は面倒なので省略……。詳しくは各ライブラリのREADMEにけっこうちゃんと書いてあります。
use Net::GrowthForecast; my $gf = Net::GrowthForecast->new(host => 'my.growthforecast.host.local', port => 80); $gf->graphs(); $gf->complexes(); $gf->all(); $gf->tree()->{servicename}->{sectionname}->{graphname}; #=> detail of graph/complex by hashref $gf->graph( $graph1->{id} ); $gf->complex( $complex1->{id} ); $gf->by_name('service', 'section', 'graph'); $graph->{description} = 'update now'; $gf->edit( $graph ); $gf->delete( $graph );
rubyだとこんな。
require 'growthforecast' gf = GrowthForecast.new('my.growthforecast.host.local', 80) gf.graphs() #=> instance of GrowthForecast::Path (has .id, .service_name, .section_name, .graph_name, .complex?) gf.complexes() #=> instance of GrowthForecast::Path gf.all() #=> array of instance of GrowthForecast::(Graph|Complex) gf.tree()['servicename']['sectionname']['graphname'] gf.graph( graph1.id ) #=> GrowthForecast::Graph gf.complex( complex1.id) #=> GrowthForecast::Complex gf.by_name('service', 'section', 'graph') graph.description = 'update now' gf.edit( graph ) gf.delete( graph )
まあそこそこラクに使えるのではないでしょうか!
これから
現状でもちょっとコード書かないといけないので、更にもうちょっと実装を進めて以下のようなツールを作るつもり。
- 定義をYAMLから読む
- 定義と引数に従って「GrowthForecast上に存在するはずのグラフ(のセット)」を確認する
- なければ作る
- あっても設定が違えば修正する
- 設定も同じものがあれば何もしない
- 引数としてサービス名を与えると、そのサービスに必要なグラフがひとそろい、コマンド一発で揃うような感じ
これはRuby版のクライアントライブラリに添付する形で作る。前はPerl版で作ろうと思ってたんだけどYAML実装が true/false を扱えないのを確認して挫折した。
1月中には作りたいなー。