1. anoworl

    Posted

    anoworl
Changes in title
+GrowthForecastのデータをHRForecastにインポートする
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,94 @@
+## はじめに
+じょう「KPI測定しよう!」
+おいら「いいですね!GrowthForecast入れました!」
+じょう「打ち合わせで使うからExcelでデイリーの増減データちょうだい!」
+おいら「りょ、りょうかいです!(rrdfetchをコマンドラインで叩いてデータをCSVに整形)」
+じょう「デイリーの増減をグラフで見れてなおかつCSVでデータをダウンロード出来るページ無いの?」
+おいら「りょ・・・ちょ、ちょっと待ってください!」
+
+## やったこと
+上記の依頼を受けた際まず始めに、GrowthForecastで使われているRRDtoolの良さ気なフロントエンドを探しましたが、要件に見合うものが見つかりませんでした。(あったら知りたいです・・・出来るだけオレオレツールは作りたくないのです・・・)
+RRDtoolには対応していないもののHRForecastが要件を満たしそうでした。そこでGrowthForecastのデータをHRForecastにインポートするスクリプトを書きました。それが以下になります。
+
+## やりかた
+### GrowthForecastのxportを拡張する
+GrowthForecastにはxportというデータをjsonでエクスポート出来る機能が付いています。これを拡張しstepとcf (統合関数) (これらの単語について詳しく知りたい方は[RRDtoolのドキュメント](http://agj.at/~fors/sysworks/data/rrdtool/rrdgraph.txt)参照) を指定できるようにします。
+[xportにてstepとcf (統合巻数) を指定できるように修正](https://github.com/anoworl/GrowthForecast/commit/b414e22678bacc5abfaeb84c92ce28514427a7d6)
+
+### 移行スクリプトを動作させる
+以下の移行スクリプトをHR_URL (HRForecastのURL) とGF_URL (GrowthFOrecastのURL) 、またAUTH (双方にかかっているBasic認証のユーザ名とパスワード)を埋めて実行すれば、GrowthForecastのデータがデイリーに変換されHRForecastにそのままのURL構造でインポートされます。またそれだけではなく"-substract"という接尾語が付いた前日との増減を記録したグラフも作成されます。
+ONLY_YESTERDATをtrueにすると昨日のデータだけをインポートするので速くなります。一番最初にfalseのまま全データを移行した後は、その後trueにして一日おきにCronで回せば最新のデータに追従出来ます。
+
+```rb
+# -*- encoding: utf-8 -*-
+require 'open-uri'
+require 'pp'
+require 'multi_json'
+require 'oj'
+require 'net/http'
+require 'uri'
+require 'active_support'
+require 'active_support/all'
+
+ONLY_YESTERDAT = false
+
+HR_URL = 'http://hr_url'
+GF_URL = 'http://gf_url'
+AUTH = ['hogehoge', 'hagehage']
+
+Time.zone = 'UTC'
+ENV['TZ'] = 'UTC'
+
+def gf_read(path)
+ json = open(GF_URL + path, http_basic_authentication: AUTH).read
+ MultiJson.load(json)
+end
+
+def hr_post(path, data={})
+ url = URI(HR_URL)
+ http = Net::HTTP.new(url.host, url.port)
+ request = Net::HTTP::Post.new(url.path + path)
+ request.basic_auth(*AUTH)
+ request.set_form_data(data)
+ response = http.request(request)
+end
+
+graphs = gf_read('/json/list/graph')
+graphs.each do |graph|
+ graph_path = [graph['service_name'], graph['section_name'], graph['graph_name']].join('/')
+
+ graph_json = gf_read("/json/graph/#{graph_path}")
+ created_at = Time.parse(graph_json['created_at'])
+
+ from = created_at.tomorrow.beginning_of_day
+ to = Time.now.utc.yesterday.beginning_of_day
+ from = to.yesterday.beginning_of_day if ONLY_YESTERDAT
+ options = {
+ t: 'c',
+ to: to.to_date.to_s(:db),
+ from: from.to_date.to_s(:db),
+ step: 86400,
+ cf: 'MAX'
+ }
+ xport = gf_read("/xport/#{graph_path}?#{URI.encode_www_form(options)}")
+ start_xport = Time.at(xport['start_timestamp']).to_date
+ end_xport = Time.at(xport['end_timestamp']).to_date
+
+ dailies = (start_xport..end_xport).zip(xport['rows'].flatten)
+
+ dailies.each do |date, num|
+ options = { number: num.to_i , datetime: date.to_s(:db) }
+ hr_post("/api/#{graph_path}", options)
+ end
+
+ dailies.each_with_index do |value, i|
+ date, num = *value
+ next if i < 1
+ options = { number: num.to_i - dailies[i-1][1].to_i, datetime: date.to_s(:db) }
+ hr_post("/api/#{graph_path}-subtract", options)
+ end
+end
+```
+
+## おわりに
+こんな家内制手工業みたいなことやりたくないです!!!なんか全てが統合されたよさげな環境ほしいです・・・。KibanaとかSplunkを触ってみようと思っているのですが、何かよさげなソリューションあったら教えて下さい・・・。