GCPで定期的にデータを取得して可視化する！


データ可視化したいなぁーっ、可視化したいなぁーっと（い◯がわじゅ◯じ風に）思っていたら、
社内の勉強会で[Google Data Studio](https://datastudio.google.com)なるもの知ったので、
遊んでみようかと思いました。

しかし、可視化するにもデータがないっ！

ということで、
寝ててもいい感じにデータを定期的に取ってきてくれるような、そんな状況をサクッと作りたく、
GCPを使ってやってみようかと思いました。

## 使うGCPサービス

- App Engine: Cronジョブの実行、データ取得するAPIを動かす
- BigQuery: 取得したデータを保存
- Data Studio: 保存したデータを可視化

## データ取得用アプリケーション作成
今回はRails(5.1.4)で作ります。
取得データは [東京電力電力供給状況](http://tepco-usage-api.appspot.com/) をとってみようかと思いました。

とりあえずAPIモードで作成。

```
$ rails new myapp --api
```

取得したデータをBigQuery gem使うので[google-cloud-bigquery](https://github.com/GoogleCloudPlatform/google-cloud-ruby/tree/master/google-cloud-bigquery)をインストールしましょう。

## テーブルを用意（BigQuery）

[BigQuery](https://bigquery.cloud.google.com)の方もデータセットとテーブルを用意しましょう。

電力供給状況APIに合わせるとテーブルのスキーマは↓になります。

カラム名|タイプ
--- | --- | ---
capacity_updated|DATETIME
forecast_peak_usage|INTEGER
month|INTEGER
forecast_peak_period|INTEGER
capacity_peak_period|INTEGER
year|INTEGER
saving|BOOLEAN
day|INTEGER
capacity|INTEGER
hour|INTEGER
forecast_peak_updated|DATETIME
forecast|INTEGER
usage_updated|DATETIME
entryfor|DATETIME
usage|INTEGER

## サービスアカウントを用意（ない人は）

RailsからBigQueryにアクセスするためにサービスアカウントを作ってkeyfileも用意しましょう。
メニュー→「APIs & services」→「Credentials」→「Create credentials」→「Service account key」
から、
JSONタイプで新しいのを作りましょう。
そして、その生成されたファイルをRailsプロジェクトのどこかへ配置しましょう。
(gitな人は.gitignoreするのを忘れずに。心配な人はIAMでRoleを変えて制限したりとか！)

## Railsアプリ側

雑にcontroller一つに処理をまとめて書いています。

```denryoku_controller.rb
require 'google/cloud/bigquery'
class DenryokuController < ApplicationController
  def usage_status
    # App Engineからリクエストがきているかどうかのバリデーション
    if request.headers['X-Appengine-Cron']
      load
      head :ok
    else
      head :not_found
    end
  end

  private
  # 電力供給状況APIを読んでデータ取得してBigQueryへ保存する
  def load
    # 東京電力電力供給状況データ取得
    uri =  'http://tepco-usage-api.appspot.com/latest.json'
    result = JSON.parse(Net::HTTP.get(URI.parse(uri)))
    
    # BigQueryへ保存
    bigquery = Google::Cloud::Bigquery.new(
        project_id: "my-project",
        credentials: "/path/to/keyfile.json"
    )
    dataset = bigquery.dataset 'my_dataset'
    table = dataset.table 'my_table'
    table.insert result
  end
end
```

設定するパラメータ
- `my-project` : 自分のGCPプロジェクトID
- `/path/to/keyfile.json` : 配置したkeyfileのパス
- `my_dataset` : BigQueryのデータセット名
- `my_table` : BigQueryのテーブル名


ポイントとしてはApp EngineからのCronでのリクエストのみ受けとり、外部からのリクエストは弾きたいため、
`X-Appengine-Cron` ヘッダーがきている時のみ処理を行うようにしています。

参考: 
https://cloud.google.com/appengine/docs/flexible/ruby/scheduling-jobs-with-cron-yaml


## アプリケーションデプロイ、Cron設定
作ったRailsアプリをデプロイします。

App Engine設定ファイル

```app.yaml
entrypoint: bundle exec rackup --port $PORT
env: flex
runtime: ruby

env_variables:
  SECRET_KEY_BASE: my-secret-key-base
```

my-secret-key-base: 自分のsecret key base ( `bundle exec rails secret` で生成できる)

Cronの設定ファイル

```cron.yaml
cron:
- description: "電力使用状況データをBigQueryへ保存"
  url: /denryoku/usage_status
  schedule: every 1 hours
```

urlにはRails側で用意したAPIのパスを設定してください。

### デプロイ

あとはサクッとデプロイ。

```
$ gcloud app create

$ gcloud app deploy app.yaml cron.yaml
```

以上で10分おきに電力供給状況データを取得してそれをBigQueryに保存できるようになりました。

「App Engine」 → 「Task queues」　→ 「Cron Jobs」から登録されているジョブの確認と実行ができます。

<img width="1021" alt="スクリーンショット 2017-12-08 17.15.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/52622/00b8e13c-5879-1275-2ea9-2d6c8ce18a92.png">


## Google Data Studio

あとはサクッと「DATA SOURCES」からBigQueryデータを取り込んで、可視化してみましょう。

今回は `usage`、 `usage_updated` しか使わないですが↓のような感じで取り込みました。

<img width="914" alt="スクリーンショット 2017-12-09 13.57.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/52622/c073799d-5bcc-2a23-0f07-77856df07a2c.png">


## 結果

前日から現在までの電力使用状況データを可視化していますが、いい感じにとれていると思ったら...
んん、惜しい...途中なんかうまくとれてない。時間もUTCっぽい。

<img width="1043" alt="スクリーンショット 2017-12-09 14.36.37.png" src="https://qiita-image-store.s3.amazonaws.com/0/52622/7d3f2065-ec50-84b8-f250-561677a6f4b9.png">


今度はセンサーデータとかを可視化したいですねー。