※2016年10月1日より、サービス名称が「Yahoo!ビッグデータインサイト」から「トレジャーデータサービス by IDCF」に変更となっております。
ビッグデータ・ソリューションアーキテクトの高階(takashina)です。
みなさんの社内や組織内のコミュニケーションには、どんなツールを使ってますか? 電話、メール、ケータイメッセージはもちろんのこと、LINE、FacebookのMessenger、Skype、Facetime、Slack、chatwork、HipChatなどといった様々なジャンルのツールを使っているかと思います。プッシュ通知されるツールだと、タイムラインを追っていくだけで必要な情報や通知内容が読めるので、手間が少なくて便利ですよね。
ログのバッチ処理をしている場合、自動的にその集計結果を送ってきてもらえたら、それも手間が少なくて便利そう。
そこで今日は、Yahoo!ビッグデータインサイト(以下「YBI」)で実行したクエリの結果をSlackへ通知する手順についてご紹介します。
前提条件
ここから先、次の前提で綴っていきます。
- CentOSサーバーの基本的な操作ができる
- 外部のBotから投稿してもOKなSlackのアカウントを持っている
- YBIのアカウントを持ち、YBIの基本機能を理解している
用意するモノ
- YBIのアカウント 1つ (無料利用期間あり 新規アカウント登録はこちら)
- Slackのアカウント 1つ (無料プランあり)
- CentOSサーバー 1台 (なかったらIDCFクラウドでワンコインサーバーをどうぞ)
手順
1. IDCFクラウドで仮想サーバー作成、ネットワークの設定
まずはIDCFクラウドでSlackへの投稿を操作するサーバーを作ります。 他のサーバーを使う方は、適宜同様の設定をしてください。
IDCFクラウドで仮想サーバーを作成する手順についてはIDCFクラウド ヘルプサイトをご覧ください。
なお、今回はおすすめTemplateのCentOS 7.1 64-bitで作成しました。
ネットワークの設定は下記のように行います。
SSH(22/TCP)とSinatra(4567/TCP)でアクセス可能としてください。
※Sinatraが何者か、は後述します。
まずIPアドレスの取得
ファイアウォールの設定
ポートフォワードの設定
2. Slackでの準備
続いてSlack側で準備をしていきます。通知を送りたいSlackのteamにアクセスしておきましょう。
外部のツール等からSlackへ投稿できる機能としてIncoming Webhooksがあります。今回はこの機能を使ってYBIからSlackへのクエリ結果通知を実現していきます。
なお、既にIncoming Webhooksの設定がされているSlackのChannelであれば、ここの手順は不要です。
2-1. Slack設定ページ
歯車マークのChannel Settingsから「Add an app or integration」を選択します。
すると、Slackの細かな設定ができるページへ飛びます。 ここの検索窓で「incoming webhooks」を入力すると候補に「Incoming Webhooks」が現れるのでクリックします。
2-2. Incoming Webhooks設定ページ
team名の右側にある「configure」、「Add Configuration」とクリックします。
Post to Channelで、Incoming Webhooksで投稿する先のchannelを選択して、
「Add Incoming WebHookss integration」ボタンをクリックします。
2-3. 投稿用URLの発行
https://hooks.slack.comで始まるWebhook URLが発行されます。
外部ツールからこのURLにデータを投げるとSlackのChannel投稿されるわけです。
このページでは、Webhookを使った投稿者名、アイコン等を変更することができますが、とりあえず今はそのまま次に進みます。 「Save Settings」をクリックして、Slack側での準備は完了です。
※注意!
このWebhook URLは関係者以外に知られないようにしてください。バレてしまうと誰でもChannelへ投稿できるようになってしまいます!
2-4. Webhook URLのテスト
Webhook URLを使った投稿ができるかどうか、CentOSサーバーにログインして、試してみましょう。
$ curl -X POST --data-urlencode 'payload={"text": "Test Message"}' https://hooks.slack.com/services/xxxxxxxxx/xxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxx
うまく行けば、SlackのChannelにこんな投稿がされているはずです。
3. td2slackの準備
続いて、CentOSサーバーにてtd2slackをインストールします。 YBIはTreasure Dataのサービスをベースにしています。YBIからSlackへ通知する仕組みについては、Treasure Dataのクエリ結果をSlackに流せる「td2slack」があるので、これを使います。
td2slackは、RubyによるWebアプリケーションを簡単に実現するためのソフトウェアであるSinatraで作られています。
今回ご紹介しているtd2slackは、YBIから送られてきたHTTP PUTをSinatraでフッキングしてSlackへ送る、という動きをしています。
Sinatraについて詳しく知りたい方はこちらをどうぞ。
3-1. yumインストール
td2slackをインストールするのにbundlerを使っていきます。
その前に、インストールに使うruby-devel、gcc、rubygem-bundlerをyumでインストールします。RubyGemsもアップデートしておきましょう。
$ sudo yum install ruby-devel gcc rubygem-bundler (中略) New leaves: gcc.x86_64 ruby-devel.x86_64 rubygem-bundler.noarch $ sudo gem update --system Updating rubygems-update Fetching: rubygems-update-2.6.4.gem (100%) Successfully installed rubygems-update-2.6.4 Installing RubyGems 2.6.4 RubyGems 2.6.4 installed (中略) RubyGems system software updated
3-2. git clone
適当なディレクトリ配下にgit cloneします。
$ git clone https://github.com/treasure-data/td2slack.git Cloning into 'td2slack'... remote: Counting objects: 49, done. remote: Total 49 (delta 0), reused 0 (delta 0), pack-reused 49 Unpacking objects: 100% (49/49), done.
3-3. 環境変数設定
下記の環境変数を設定します。
$ export SLACK_WEBHOOK_URL=https://hooks.slack.com/services/xxxxxxxxx/xxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxx $ export RACK_ENV=production
- Sinatraアプリケーション(app.rb)からSLACKへ投稿する際に、SLACK_WEBHOOK_URLの環境変数で指定したURLへ送っています。
- RACK_ENVは、Sinatraアプリケーションを外部のサーバーから利用できるようにするために設定しています。
3-4. td2slackインストール
td2slackで使われるjsonのgemがGemfileに含まれていなかったため、追記したうえでbundlerでインストールします。
$ cd td2slack $ vi Gemfile source 'https://rubygems.org' gem 'sinatra' gem 'slack-notifier' gem 'json' (← 一行追加) $ bundle install --path vendor/bundle Fetching gem metadata from https://rubygems.org/............. Resolving dependencies... Installing json 1.8.3 Installing rack 1.6.0 Installing rack-protection 1.5.3 Installing tilt 2.0.1 Installing sinatra 1.4.6 Installing slack-notifier 1.1.0 Using bundler 1.7.8 Your bundle is complete! It was installed into ./vendor/bundle
これで実行環境が整いました。
4. 実行テスト
とりあえず実行してみましょう。
$ bundle exec ruby app.rb [2016-05-23 20:21:05] INFO WEBrick 1.3.1 [2016-05-23 20:21:05] INFO ruby 2.0.0 (2014-11-13) [x86_64-linux] == Sinatra (v1.4.7) has taken the stage on 4567 for production with backup from WEBrick [2016-05-23 20:21:05] INFO WEBrick::HTTPServer#start: pid=11116 port=4567
この状態でYBIのWeb UIからクエリを実行してみます。
適当なDatabaseを選んで、テスト用に「SELECT ‘aaa’ AS foo」などという単純なクエリを書きます。
このクエリの結果は「foo」カラムに「aaa」という文字列が1行だけ現れます。
これをResult Exportの機能で「HTTP PUT」へエクスポートします。記入個所はHost、Port、Pathの3箇所です。
ここまで設定したら、Web UI右上にある「Run」!
すると..Slackにこんな投稿がされるはずです。
CentOSサーバーにはこんなログが出てます。
WARN: tilt autoloading 'tilt/erb' in a non thread-safe way; explicit require 'tilt/erb' suggested. xxx.xxx.xx.xx - - [23/May/2016:20:23:54 +0900] "PUT /example HTTP/1.1" 200 - 0.4638 xxx-xxx-xx-xx.jp-east.compute.idcfcloud.com - - [23/May/2016:20:23:54 JST] "PUT /example HTTP/1.1" 200 164 - -> /example [2016-05-23 20:23:54] ERROR Errno::ECONNRESET: Connection reset by peer /usr/share/ruby/webrick/httpserver.rb:80:in `eof?' /usr/share/ruby/webrick/httpserver.rb:80:in `run' /usr/share/ruby/webrick/server.rb:295:in `block in start_thread'
確認できたらSinatraは止めておきましょう。Ctrl-Cです。
5. td2slackをデーモンで動かす
Sinatraアプリであるtd2slackは、rackupコマンドでデーモン起動可能です。下記では4567/TCPポートで起動しています。netstatで起動状況を確認してみましょう。
$ bundle exec rackup -D config.ru -p 4567 $ netstat -tnap Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:4567 0.0.0.0:* LISTEN 18591/ruby
止める時はkillしてください。
$ kill -9 ${pid}
6. 出力結果のフォーマット作成
Result Exportを設定する際に、 Path: /example
と設定しました。
これは、CentOSサーバーのtd2slack/viewsディレクトリ配下にあるerbファイルに沿って出力されています。
example.erbファイルを見てみると..
$ more views/example.erb This is <%=@td['foo'][0]%>
クエリの結果は「foo」カラムに「aaa」という文字列が1行だけ現れるもので、Slackへの投稿された内容は以下の通りでした。
<%=@td['foo'][0]%>
の部分にクエリ結果の「aaa」が代入されていたのですね。
このようにviewsディレクトリ配下のerbファイルを設定すると、いろいろと出力結果をカスタマイズできます。
ところで、YBIにはsample_datasetsというデータベース内に、過去のNasdaq株価データが入ったテーブルがサンプルデータとして格納されています。このデータセットに対して、次のようなクエリを実行して、結果をSlackへ流してみましょう。Sinatraアプリを起動しておくのをお忘れなく。
$ bundle exec rackup -D config.ru -p 4567
設定ファイル:トップ5をフォーマットして表示しています。
$ vi views/rate_of_increase.erb Nasdaq株価上昇率トップ5 日付 | 銘柄 | 上昇率 <% 5.times do |i| %> <%= i + 1 %>位 <%= @td['date'][i] %> | <%= @td['symbol'][i] %> | <%= @td['rate_of_increase'][i] %> <% end %>
クエリ:日毎・銘柄毎の株価上昇率を計算して、上昇率トップ5を取得しています。
SELECT TD_TIME_FORMAT(time, 'yyyy-MM-dd') AS date, symbol, (close - open) / open AS rate_of_increase FROM nasdaq WHERE TD_TIME_RANGE(time, '2012-01-01', '2013-01-01') AND (close - open) > 0 AND open > 0 ORDER BY rate_of_increase DESC LIMIT 5
Result Exportの設定は次のようにします。
Export to: HTTP PUT Host: td2slackが動くホスト名かIPアドレス Port: 4567 Username: 空白 Passowrd: 空白 Path: /rate_of_increase
クエリをRunしてみましょう。Slackへ出力される結果は次のようになるはずです。
今回の環境
$ cat /etc/redhat-release CentOS Linux release 7.2.1511 (Core) $ /usr/bin/ruby -v ruby 2.0.0p598 (2014-11-13) [x86_64-linux] $ /usr/bin/gem -v 2.6.4 $ /usr/bin/bundler -v Bundler version 1.7.8
おわりに
いかがでしたか。
クエリ結果を定期的にSlackへ出力してもらえると、監視アラートの代わりに使うこともできますね。
それでは、ごきげんよう!