Google Data Studio で BigQuery ログを可視化してディレクターのデータ依頼から解き放たれる

この記事は[「エムスリー Advent Calendar 2016」](http://qiita.com/advent-calendar/2016/m3)の 10日目の記事です

今年の5月に無償版が提供されている [Google Data Studio](https://datastudio.google.com) ですが、使った人たちのコメントを見ているとドキュメントを読まなくても、いきなり使えるというメリットがあったものの、**SQLを書けない**というデメリットがあって、 他の無料ツールの [Re:dash](https://redash.io/) (無料だとサーバーが必要)の方がデータ分析的に使えるかなと思っていました。

しかし、最近[この記事](https://bita.jp/dml/ga_datastudio)を読んでいて、逆に **SQLクエリを書かなくて良い** ということが ~~(ディレクターに丸投げできるという意味で)~~ 最大の魅力ということに気づきました。ということで、 Google Data Studio を使うことで、ディレクターがよく見たい指標ランキングTOPに挙がるであろうユーザーのアクセスログを可視化したので、ログ収集部分からまるっと解説します。



## データの流れ
Web アプリサーバー (Heroku)のアクセスログ
-> fluentd サーバー （Heroku)
-> BigQuery
-> Google Data Studio

## Web アプリサーバーのログ流し込み設定
※今回の例は Heroku で Rails アプリを運用しているパターンですが、ログを HTTP POST できば何でも大丈夫です。Heroku では log drains というものがあるのでそれで fluentd に流し込みます。
[Log Drain| Heroku](https://devcenter.heroku.com/articles/log-drains>)

今回は HTTP 通信で流し込む

```
# heroku で運用しているアプリから fluentd があるサーバーへログを転送
$ heroku drains:add https://my-fluentd-app.herokuapp.com/log -a myapp
```

これで、fluentd サーバーの /log へ POST してくれます。ログの内容は body の中にJSON形式で、`message` という key で入れられます。今回は Heroku にデフォルトである [Heroku Router](https://devcenter.heroku.com/articles/http-routing#heroku-router-log-format) のログを使います。
body の中身はこんな感じ

```json
{"message" : "262 <158>1 2016-12-06T23:00:32.420809+00:00 host heroku router - at=info method=POST path=\"/log?user_id=23&client=android\" host=myapp.herokuapp.com request_id=65e1bjkf-7le5-4a11-8236-ac24a3b71bb7 fwd=\"231.137.44.83\" dyno=web.1 connect=0ms service=8ms status=200 bytes=492\n"
```

本来は `userid` などのパラメータはクエリストリングではなく Http ヘッダーに入れて出力したかったのですが、Heroku Router に Http ヘッダーを出力する機能が見つからなかったので、今回はクエリストリングに入れました。。

## BigQuery と GCP の登録
今回のストレージとなる BigQuery 及び Google Cloud Platform でのサービスアカウントの登録を事前に行っておきます。
※BigQuery はクエリのストレージとクエリ発行などが有料です
[プラン](https://cloud.google.com/bigquery/pricing)
[登録方法| Google](https://cloud.google.com/bigquery/docs/quickstarts?hl=ja)


参考
[データ分析基盤としての BigQuery 運用のベストプラクティス](http://tech.vasily.jp/entry/bigquery_data_platform)
[FluentdでGoogle BigQueryにログを挿入してクエリを実行する](http://qiita.com/harukasan/items/0e0da49c65839e9517c4)




## Fluentd サーバーを Heroku に立てる
流し込み先が Treasure Data だとこういった[すごく便利なプラグイン](https://github.com/kiyoto/heroku-td-agent)もあるのですが、今回はデータの送り先がBigQuery なので自前で fluentd 用のサーバーを Heroku に立てます

#### [Fluentd プロジェクトを作成して Herokuに push](http://docs.fluentd.org/articles/install-on-heroku#with-non-treasure-data-backend)
```
# Clone
$ git clone git://github.com/treasure-data/heroku-td-agent.git
$ cd heroku-td-agent
$ rm -fR .git
$ git init
$ git add .
$ git commit -m 'initial commit'

# Heroku 上にアプリ作成
$ heroku create --stack cedar 

$ git push heroku master
```

一旦これで heroku にアプリが立ち上がってるかを確認するとよいです。

次にBigQueryへログを流すために、以下のファイルを設定します。

```ruby:Gemfile
gem 'fluentd', '~> 0.12.0'
gem 'fluent-plugin-td'
gem 'fluent-plugin-parser'
gem 'fluent-plugin-bigquery'
gem 'fluent-plugin-rewrite'
```


```text:Procfile
# デフォルトだとここで fluentd への source 設定があるが td-agent.conf へ設定は寄せる
web: bundle exec fluentd --use-v1-config -c td-agent.conf
```

```apacheconf:td-agent.conf
<source>
  @type http
  port "#{ENV['PORT']}" # herokuで自動設定される環境変数
  keepalive_timeout 10s
  format none # none にしないと heroku の router ログは読み取ってくれない
</source>

# heroku のログには「"」や「\\n」が混じっているので削除
<match access_log>
  @type rewrite
  add_prefix filetered
  <rule>
    key message
    pattern \"|\\n
    replace
  </rule>
</match> 

# ログをマッチパターンのみにフィルタ
<match filetered.access_log>
  @type parser
  key_name message
  tag bigquery
  format /\<.*\>\d (?<strtime>.+)\..* method=(?<method>.+) path=(?<path>.+)(\?|\&)user_id=(?<userid>.+)&client\=(?<client>.+) host=(?<host>.+) request_id=(?<request_id>.+) fwd=(?<fwd>.+) dyno=(?<dyno>.+) connect=(?<connect>.+) service=(?<service>.+) status=(?<status>.+) bytes=(?<bytes>.+)$/
</match>


# フィルタ後のログをBigQueryに送信
<match bigquery>
  @type bigquery

  method insert

  auth_method json_key
  # この値は GCP で使うservice account の値を入れる
  email XXXXXXXX@YYYYY.iam.gserviceaccount.com
  json_key ./yourprojectZZZZZZZ.json 

  # この値はBigQueryで設定した値を入れる
  project [YOUR_PROJECT]
  dataset [YOUR_DATASET]
  auto_create_table true
  table log%{time_slice} # 日付単位でテーブルはローテート

  time_field strtime
  field_string strtime,path,status,method,userid,client,fwd,service,bytes,host,request_id,dyno,connect

  buffer_path ./buffer/td
  buffer_chunk_limit 1m
  buffer_queue_limit 512
</match>
```

### ローカルで Fluentd の挙動を試す

```
$ bundle
$ export PORT=8888
$ bundle exec fluentd -c td-agent.conf
$ curl -X POST -d "262 <158>1 2016-12-06T23:00:32.420809+00:00 host heroku router - at=info method=GET path=\"/my_page?user_id=23&client=android\" host=myapp.herokuapp.com request_id=65e1bdfa-72e5-4a11-8236-ac24a2b71bb7 fwd=123.137.16.73 dyno=web.1 connect=0ms service=8ms status=200 bytes=492"\
 http://localhost:8888/access_log
```

これで BigQuery 側にデータが挿入されていばOKです。

## Google Data Studio で可視化する

ということでやっと Google Data Studio。ただしやることはあまりないです！
1. [ログイン](https://datastudio.google.com/)
2. レポートを新規作成

<img width="748" alt="レポートを新規作成.png" src="https://qiita-image-store.s3.amazonaws.com/0/90436/9e0bbd49-dc55-7c74-337f-c3fff0cf2198.png">

3.リソースを追加
<img width="748" alt="リソースを追加.png" src="https://qiita-image-store.s3.amazonaws.com/0/90436/ff6342d3-6f32-47e8-8655-c109c8cc5cb4.png">


4.ディメンションとメトリクスを選ぶ
<img width="748" alt="スクリーンショット 2016-12-10 9.06.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/90436/8b18a08d-86f5-c1b4-e0fb-4eb147755a01.png">


5.完了

<img width="748" alt="完了.png" src="https://qiita-image-store.s3.amazonaws.com/0/90436/4d5eeac6-ea7a-377b-84b0-35370f975ba6.png">



## まとめ
ということであっという間にアクセスログを可視化し、あとはデータ分析をしたい人がガシガシ使えば良い環境をつくりました。
BigQuery はデータ量によっては多少お金がかかりますが（私の場合は3日使ったところでまだ0円) ほぼ無料でここまで簡単にアクセスログを可視化できるなんて感動ですね。