0%

DashingとTreasure Data - Part3: Rubyのtd-clientを使う

Part2Treasure Data Serviceへtdコマンドから簡単なクエリを実行しました。
DashingはSinatraアプリなのでRubyでTreasure Data Serviceにクエリするプログラムを書きます。
ちょっとしたDBアクセス用のライブラリも用意してみました。

Dockerコンテナ起動

-eオプションで環境変数を指定してコンテナを起動します。TD_API_KEYには、td apikey:showで確認した値を使います。

$ ~/docker_apps/phusion/
$ docker run -t -i -p 3030:3030 -e TD_API_KEY=xxx -v ~/docker_apps/workspaces/dashing:/root/sinatra_apps masato/baseimage:1.0 /sbin/my_init /bin/bash

環境変数の確認

コンテナに環境変数がセットされていることを確認します。
SSH接続すると-eオプションで指定した環境変数が反映されないので、コンテナを起動した/bin/bashのまま作業します。

root@67413c80299f:/# echo $TD_API_KEY
xxx

byobu

サーバーアプリを開発する場合、Emacsのmulti-termだけを使うよりも、
マルチプレクサでEmacsとサーバーで別ウィンドウで作業すると便利なのでbyobuを起動します。

$ byobu
$ byobu-config
$ byobu-select-backend
$ byobu-ctrl-a

Gemfile

このコンテナでも-vオプションを使い、Dockerホストの共有ディレクトリをマウントして作業します。
プロジェクトのディレクトリに移動して確認します。

$ cd /root/sinatra_apps/cloud_td
$ ls
Gemfile README.md config.ru history.yml lib sql widgets
Gemfile.lock assets dashboards jobs public test.rb

Gemfileにtd-clientを追加します。

/root/sinatra_apps/cloud_td/Gemfile
gem 'td-client'

bundle installします。

$ bundle install

Dashingの起動確認

とりあえずDashingサーバーを起動して確認します。

$ dashing server

デフォルトで同梱されているsampleダッシュボードの表示を確認します。
-vオプション-eオプションを使って、少しずつDisposable Infrastructureらしくなってきました。

http://{Dockerホスト}:3030/sample

lib/db_client.rb

Treasure Dataに接続するコードを、libディレクトリに書きました。
API_KEYは、docker runの環境変数のオプションに渡している値を使います。一応initializeでオーバーライドできるようにしています。

/root/sinatra_apps/cloud_td/lib/db_client.rb
# -*- coding: utf-8 -*-

require 'td-client'

module DBClient
class TD
def initialize(apikey: nil)
apikey = ENV['TD_API_KEY'] unless apikey
@client = TreasureData::Client.new apikey
end
attr_reader :headers

def wait_finished db_name,sql,type, &block
job = @client.query(db_name, sql,
result_url=nil, priority=nil, retry_limit=nil,
opts={type: type})

puts "waiting until job_id:#{job.job_id} finished... "
until job.finished?
sleep 2
job.update_progress!
end
job.update_status!
puts "job_id:#{job.job_id} finished, status:#{job.status} "

block.call(job)
end

def query(db_name, sql, type: nil)
type ||= :hive
results = []
wait_finished(db_name,sql,type) do |job|
job.result_each do |row|
results << {label: row[0], value: row[1]}
end
@headers = results.map{|m| m[:label]} unless @headers
end
results
end
end
end

job

前回Treasure Data Toolbeltで使ったのと同じSQLをヒアドキュメントに書きます。さきほど書いたlibディレクトリ下のコードをrequre_relativeします。

確認用に、取得したデータは、sampleダッシュボードの右側にあるdata-id="buzzwords"のウィジェットを使って表
示してみます。data-view="List"widgets/listウィジェットを使っているので、リスト表示のサンプルにちょうど良いです。

send_eventの引数でdata-idにIDとしてlistを使います。
SCHEDULER.every '1d'は、rufus-schedulerを使って、1日1回ジョブを実行する定義です。
:first_in => 0とすることで、初回のジョブがDashing起動後すぐに実行されるようにします。

/root/sinatra_apps/cloud_td/jobs/access_count.rb

require_relative "../lib/db_client"

client = DBClient::TD.new

SCHEDULER.every '1d',:first_in => 0 do |job|
db_name = 'clouddb'
sql = <<-EOS
SELECT TD_TIME_FORMAT(time, 'yyyy-MM-dd', 'JST') AS day,
COUNT(1) AS cnt
FROM www_access
GROUP BY TD_TIME_FORMAT(time, 'yyyy-MM-dd', 'JST')
ORDER BY day DESC
EOS

results = client.query(db_name,sql)
send_event('buzzwords', { items: results })
end

sampleダッシュボードのbuzzwordsのdata-idで、ウィジェットを定義している箇所を確認します。

/root/sinatra_apps/cloud_td/dashboards/sample.rb
    <li data-row="1" data-col="1" data-sizex="1" data-sizey="2">
<div data-id="buzzwords" data-view="List" data-unordered="true" data-title="STATUS COUNT" dat\
a-moreinfo="# of times said around the office"></div>
</li>

確認

デフォルトのsampleダッシュボードの右側に、Treasure Dataから取得したデータがリスト形式で表示されることを確認します。
http://{Dockerホスト}:3030/sample

git push

Dockerホストから別のシェルを起動して、SSH接続するためにIPアドレスを確認します。

$ docker inspect 67413c80299f | jq -r '.[0] | .NetworkSettings | .IPAddress'
172.17.0.2

Dockerコンテナには鍵をコピーしていないので、
Gitのリモートリポジトリに使っている鍵を、ssh-agentに追加して、コンテナにSSHで接続します。
Dockerホストと同じVLAN上に配置している、リモートリポジトリにコンテナ内部からpushします。

$ eval `ssh-agent`
$ ssh-add ~/.ssh/private_key
$ ssh -A root@172.17.0.2
$ cd ~/sinatra_apps/cloud_td/
$ git add -A
$ git commit -m 'add td_client library'
$ git push origin master

まとめ

今回はデフォルトのsampleダッシュボードを使って、Treasure Data Serviceからデータを取得して表示してみました。
簡単なDB接続用コードを書いて、複数のジョブからrequireして簡単にSQLを実行できるようにしました。

sample.rbを参考にしながら、ウィジェットを定義する自分のダッシュボードを作っていくと簡単にカスタマイズできます。

次回は、fluentdの安定版であるtd-agentを使って、ApacheやTomcatのログをストリームでインポートしてみます。