Auth0のログをBigQueryを使って永続化したかった

**2019/8/13 追記しました & タイトル変えました**

BigQueryに入れたり、テキストファイルとしてどこかに保存しておけばよいのはわかっていました。
いざAuth0 Management APIを叩いてみたところ癖があったのでメモとして残しておきます。

## Auth0 のログがクセモノだった件
すべてこのドキュメントに書いてあります。
https://auth0.com/docs/logs

### 1. ログの種類が豊富

> The Logs page of the Dashboard displays all events that occur, including user authentication and administrative actions such as adding/updating Applications, Connections, and Rules.

日本語にすると、`ダッシュボードのログページで、ユーザー認証、管理関係の操作、アプリ・コネクション・ルール追加の全イベントが確認できます` ということで、Auth0に関連するログのすべてを一箇所で確認できます。便利ですね。ただし、ユーザー属性別に抽出する方法などがあれば最高なのですが、そういった事は現時点ではできないようです。また、注意点として、管理関係の操作は `API Operation` として表示される点に注意、とあります。

ダッシュボード上でフィルターする際は `query syntax` を使って検索ができます。例えば、管理系イベントだけをフィルターしたい場合は `type:"sapi" OR "fapi"` のようにすればよいです。

ログの種類一覧はこちらに記載されています。
https://auth0.com/docs/logs#log-data-event-listing

### 2. 保管期間が短い

一方で、保管期間が無料版では2日、エンタープライズでも30日と、決して長いとは言えません（多分この辺がセキュリティーポリシーに引っかかって使えないというプロジェクトがあるのではないでしょうか）。なので、これ以上長期保管するには、外部サービスやファイルへのエクスポートが必要になります。今回は、BigQueryにしました。
※ちなみにこういったExtensionがあったのですが、こちらは利用者のログだけ取れればいいという意図のものと思われ、`API Operation` には対応しておらず、利用を見送りました。
https://github.com/hongymagic/auth0-logs-to-google-cloud

### 3. APIの仕様

Auth0 には Management API と呼ばれる管理情報を取得・作成・更新・削除できるエンドポイントがあります。この中にLogを取得できるエンドポイントがあるのでこちらを利用します。
https://auth0.com/docs/api/management/v2#!/Logs/get_logs

この手のエンドポイントは取得件数上限があったりしますが、Auth0も存在します。具体的には、`100件/ページ` で、10ページ目を表示しようとするとエラーとなるので、**実質1,000件が上限** となります。
また、ログの取得範囲を指定できる `from` オプションがあります。Auth0のログには `log_id` というものがあり、指定した `log_id` **より後に発生したログだけ**を取得できます。`指定した log_id < 取得したい log_id` ですね。こちらを利用した際は `take` パラメーターで取得する件数を指定できます。デフォルトでは50、最大100ということで、範囲指定した場合は **100件が上限** となります。
ページングどこいったの？と思われると思いますが、 `from` `take` を利用した際は **ページングが利用できず** 、条件未指定の際には動作する `sort` も機能しなくなり、**不安定な降順固定** となります。~~これドキュメントに書いてないので、~~処理結果が意図した内容になっていないことに気づけず再帰処理の中で何度も同じ結果を取得するAPIをコールしてしまいました…。こちら、取得結果が入る配列を sort することで対応しています。

8/9追記: ちゃんとここに利用できない旨書いてありました
https://auth0.com/docs/logs#get-logs-by-search-criteria
> Important: When fetching logs by checkpoint, the q or any other parameter other than from and take will be ignored. Also the order by date is not guaranteed.

### 4. 内容がスキーマレス
実はBigQuery触ったのが初めてだったので、てっきりBigQuery = NoSQLだと思っていましたが、スキーマフルでした…。
Auth0のログ自体はスキーマレスなので、突っ込む際は、上記したログ種類一覧をすべて網羅したスキーマを定義する必要があり、ちょっと現実的ではないなと感じ、どうにかできないか（例えば `JSON.stringfy` して文字列として突っ込むなど）考えましたが、可用性を考えると到底容認できず。
結果的には、Stackdriver Loggingに突っ込み、BigQueryにエクスポート（シンク）する方法で逃げました。これだとオートスキーマが効くのでこの問題も解消できました。
StackdriverもGCP関連サービス以外のログは保持期間30日なので辛いですね(´・ω・｀)

### 5. 8/13追記:結局Storageに突っ込み直しました
いざ実証実験を始めたところ、Stackdriver logging に吐き出したログの件数とAuth0で発生したログの件数が一致しておらず、確認したところ、BigQueryに出力する処理でエラーが起きていました…**オートスキーマでは最初の100件のログから類推されるため、ケースによってはBigQueryのスキーマが不足**し、2回目以降のログが正しくBigQueryに入らないようです。
ということで、今回はログを解析したりする予定はなく、永続化が目的なので、エクスポート先をBigQueryからStorageに変更しました。

## まとめ
ということで、こんな感じでAuth0のログの永続化に成功しました！
<img width="930" alt="スクリーンショット 2019-08-06 18.57.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236279/8c508fa4-adad-4acb-b9d5-54da55bb77cc.png">
追記8/13: 結局最後はBigQueryではなくStorageです。絵を作り直すモチベが消えた。

Firebase 単体で面倒な設定無しに Cloud Scheduler を利用できるのがとっても便利でした。
https://firebase.google.com/docs/functions/schedule-functions?hl=ja
> 指定した時刻に実行されるように関数をスケジュール設定する場合は、`functions.pubsub.schedule().onRun()` を使用します


## 今後の展望
再掲になりますが、[こちらのExtension](https://github.com/hongymagic/auth0-logs-to-google-cloud)を利用すればAuth0でイベントが発火したタイミングでStackdriverにログが流れるので、前記した100件ルールに縛られることなくログを長期保存できるようになります。こちらに `sapi` 対応するような修正が入れば最高ですね。PR出してもいかもしれません。

それでは！