読者です 読者をやめる 読者になる 読者になる

そんな今日この頃でして、、、

コード書いたり映画みたり。努力は苦手だから「楽しいこと」を探していきたい。

Dockerでデータ可視化環境をサクッと用意する

Docker Ruby Bitcoin サーバ コーディング

先週に引き続きBitcoin関連で週末コーディング。

blue1st.hateblo.jp

取引アルゴリズムを考える前に、とりあえずは可視化(と仮説の検証)が必要だろうということで。


ポート管理やら各種パスやら環境変数やらに煩わされたくない怠惰系のアプリケーションエンジニアとしては、 この手のツールがDockerで用意されてると簡単に試せて本当に助かる。

以下Docker Compose導入後という前提で。

blue1st.hateblo.jp



簡単なグラフ化ならGrowthForecast

表題どおり、何かしらの時間で変化する数値をサクッとグラフ化するだけの要件なら、GrowthForecastを立ち上げてスクリプトなり何なりから値を投げ込むのが楽だろう。

GrowthForecast - Lightning fast Graphing / Visualization

導入

適当にディレクトリを用意し(僕は~/Docker/[サービス名]みたいな感じでまとめてる)、下記のdocker-compose.ymlを作成して$ docker-compose up -dで起動するだけ。

growthforecast:
  image: kazeburo/growthforecast
  ports:
    - 5125:5125 #ホストの5125番ポートにGrowthForecastで使用するコンテナの5125ポートを割り当てる
  volumes:
    - $PWD/data:/var/lib/growthforecast #ホストの./dataディレクトリにファイルを吐くようにする
    - /etc/localtime:/etc/localtime:ro #ホストとコンテナのタイムゾーンを合わせる

上手くいってればhttp://[サーバのIP]:5125/にアクセスすると一覧ページが表示される。

データ投入

ドキュメント通り$ curl -XPOST http://localhost:5125/api/test1/test2/test3 -d number=12345とか投げた後に再度ページにアクセスすれば、グラフ化されていることが確認できる。

実際的にはbtcboxのAPIから取り出した値をグラフ化したいので下記のようなrubyスクリプトを組んだ。

require 'btcbox'
require 'net/http'
require 'uri'

btc = Btcbox::Client.new(PUBLIC_KEY, SECRET_KEY)
balance = btc.balance
res = Net::HTTP.post_form(URI.parse("http://localhost:5125/api/btcbox/jpy/lock"), {number: balance["jpy_lock"].to_i, type: "gauge"})
res = Net::HTTP.post_form(URI.parse("http://localhost:5125/api/btcbox/jpy/balance"), {number: balance["jpy_balance"].to_i, type: "gauge"})

(ていうか、今ドキュメント読みなおしてみたらそれ用のgemもあったのね。tagomoris/rb-growthforecast · GitHub )

f:id:blue1st:20151206235012p:plain

f:id:blue1st:20151206235021p:plain


そんなわけで「小難しいことはいいからとりあえず時系列グラフを!」という場合にGrowthForecastは非常に便利なのだが、一点注意しなければいけないことが。

投げ込めるnumberは整数のみ対応なので、小数を含む値を投げ込むとエラーとなってしまう。

$ curl -XPOST http://localhost:5125/api/test1/test2/test3 -d number=12345.5
{"messages":["a INT number is required for \"number\""],"error":1}

なので必要におうじて桁を繰り上げるなり四捨五入なりをする必要がある。

Bitcoin関連だと小数を扱う機会も少なくなく、変に繰り上げばかりしていると混乱してしまいそうなので、次のElasticsearch&Kibanaにも手を出してみた。



様々な要求に対応するならElasticsearch&Kibana

昨今なにかと名前を見かけるElasticsearch。

良い機会だったのでちょっとだけかじってみた。(その程度なんで僕自身まだ理解度は浅め)

全文検索エンジンであるElasticsearchと、フロントエンドであるKibanaを連結して使う。

導入

docker-compose.ymlは下記を使用。

elasticsearch:
  image: elasticsearch
  volumes:
    - $PWD/esdata:/usr/share/elasticsearch/data
    - /etc/localtime:/etc/localtime:ro #ホストとコンテナのタイムゾーンを合わせる
  ports:
    - 9200:9200 # データ投入用のポート
kibana:
  image: kibana
  volumes:
    - /etc/localtime:/etc/localtime:ro #ホストとコンテナのタイムゾーンを合わせる
  links:
    - elasticsearch:elasticsearch
  ports:
    - 5601:5601 # フロントエンド用のポート

これでhttp://[サーバのIP]:5601でKibanaのページが表示される。

データ投入

一応こちらもcurlからデータ投入できなくはないが、ちょっと面倒なJSONの形なので大人しく各言語のライブラリを使った方が良い。

以下rubyスクリプトで

require 'elasticsearch'
require 'btcbox'

btc = Btcbox::Client.new(PUBLIC_KEY, SECRET_KEY)
orders = btc.orders

es = Elasticsearch::Client.new log: false
for order in orders
  id = order["tid"].to_i
  data = {price: order["price"], amount: order["amount"], type: order["type"]}
  data['@timestamp'] = Time.at(order["date"].to_i).utc.iso8601
  es.index index: 'btcbox', type: 'order', id: id, body: data
end

es.indices.refresh index: 'btcbox'

btcboxというインデックスにorderのデータを突っ込んでいく。

時系列のイベントとして判定されるように@timestampというキーを用意していることに注意。

設定

さっき突っ込んだデータを表示するためにKibana上で設定を行う。

Index name or patternに先ほど指定していたbtcbox、時間を示すTime-field name@timestampを指定してCreate。

これでスクリプトから突っ込んだデータを扱えるようになる。

f:id:blue1st:20151206235121p:plain

グラフ描画

VisualizeメニューよりLine ChartFrom a new searchを選択する。

縦軸Y-AxisとしてAggregationAverageFieldpriceとして指定。

横軸としてX-AxisAggregationDate HistgramField@timestamp指定。

上の|>ボタンを押してグラフを描画できる。

f:id:blue1st:20151206235109p:plain

時間の都合上あまりいじれなかったが、売り買いを別の線にするとか取引量をプロットの太さにするとか、もっと複雑なことだってできる。

サーバ/インフラエンジニア養成読本 ログ収集~可視化編 [現場主導のデータ分析環境を構築!] (Software Design plus)

サーバ/インフラエンジニア養成読本 ログ収集~可視化編 [現場主導のデータ分析環境を構築!] (Software Design plus)



怠惰なアプリケーションエンジニアへのDockerのススメ

今回いれてみたツールはいずれも導入が簡単だということが売りの一つだったりするので、 実のところ個々に入れたってそんなに苦になるものではない。

だた、そうはいっても僕のような怠惰なアプリケーションエンジニアにとっては、サーバに何か導入して管理するという事自体が面倒だったりする。

個々のツールの設定ファイルの場所は忘れるしポートはごっちゃごちゃになるし、挙句どこで起動したんだか、どう落とすのが安全なんだか分からなくなる。

そのあたりの面倒を最小化してくれるので、Docker(というかDocker Compose)はすごくありがたい。

プログラマのためのDocker教科書 インフラの基礎知識&コードによる環境構築の自動化

プログラマのためのDocker教科書 インフラの基礎知識&コードによる環境構築の自動化