Cloudflare zaraz + Workers + Cloud Functions + BigQueryメモ

自分で運営するSaaSにアクセス解析を組み込もうという話、いろいろ考えた結果BigQueryがやっぱりコスパと使い勝手がいいんじゃなかろうかという話になり、組んでみることにした。忘れないようにメモを残す。

まず、PVを検知する場所であるが、これは何らかのJavaScriptトラッカーを動作させる必要がある。こいつがブラウザの様々な情報を収集し、単純なアクセスだけでなく、画面サイズなど追加要素を取得したり、ゆくゆくは「ページの6割以上スクロールした」などを検知することが可能になるわけだ。
今回はこの部分にCloudflare Zarazを用いた。ZarazはGoogle Tag Managerなどタグマネージャに相当する製品で、マーケティングツールなどのスクリプトを取りまとめて一括で配信制御できるツールだ。
GTMをいままで使ってきたが、よりページスピードを向上させたいというのが一つ目の目的だ。
うまく使えばクライアント上で動作させるスクリプトをエッジでエミュレート動作させ、直接必要な値をサーバに送出するという機能も付いているのだ。しかもCloudflareがプロキシしていることを活用するので、自ドメインで動作する。
もうひとつは、GTMだとタグを張って動作させるところまでしかできないが、ZarazはHTTP Postが使えるので、PageViewを計測するたびに任意のエンドポイントに投げるということができるようになっている。今回はこの機能を活用することにした。

次に、ZarazのPostはいきなりCloud Functionsに投げてもよいのだが、メンテナンスなどを考慮してキューイングするのがよいだろうと考え、同じくCloudflare製品のWorkers Queueを活用することにした。
同様にGCP製品にもキュー製品があったのだが、今回の用途を考えると、無数に飛んでくるアクセスを、ある程度束ねた形で書き込みたかったので、複数のキューがまとまってワーカーに降ってくる形式が好ましかった。GCPでもPubSubを使ってPullすればよいのだが、Cloudflare Queueはよりシンプルに実現できた。
これにより、Zaraz->Workersに10アクセス分一気に飛んできても、10アクセス分のメッセージを含んだWorkerが1回呼ばれるだけなので、FaaSの起動回数およびBigQueryへの接続回数を大幅に削減することが可能になる。
さらに、検証はしていないが、Cloudflare製品を使うということは前段にBot対策やWAFなどが使えるはずなので変なアクセスをカウントしなくて済むという利点もある。これは自前で組むときとても心強い。

さて、BigQueryにデータを書き込むにはいろいろな方法があるが、現在推奨されているものはStorage Write APIと呼ばれるもののようだ。これはプロトコルにgRPCを用いるため、Cloudflare Workersではたぶんできない。できたとしても面倒なコードを多数書かなければいけないため、手軽さでPythonを用意した。
注意点としては、Ubuntuでaptを使ってインストールするprotocが古かったため、公式サイトから最新版を入れなおしたくらい。あとはすんなり使えた。

これで、ブラウザからBigQueryまでデータが流れるようになった。途中データ成型として、最初のWorkerにてイベントごとの振り分け処理をいれたり、データ節約のためOSなどメタデータの記録はPVのみに限定するなどの処理を入れた。
また、想定外だったのは、GTMと異なり、Zarazは純粋なPageviewとhashchangeイベントをどちらもPageviewとして扱う挙動を見せた。SPAでも簡単に使えることを意識してだと思うが、ドクセルの場合はスライドがめくるたびにシェアしやすいようにハッシュを変更しているので、大量の偽PVが生まれてしまい困った。仕方なく手動でPageViewEventイベントをトリガーさせてしのいでいるが、あとで気づいたがSPA modeのようなフラグをオフにすることで元に戻せた。
あとは、1時間ごとにPV/UU/Eventを集計して、7日分だけMySQLに持ってくれば、即時性が必要なユーザーダッシュボードにも出せそうという感じである。
また、間にWorkersを導入したことにより、じつはWorkersのAnalytics Engineを使えば即時性が必要な直近の速報処理はこっちにオフロードできるかもしれないと考えている。これはこれで楽しみだ。

さらに追記すると、ここまでやって(GA4をBQ連携するだけでいのでは?)というのが脳裏に浮かんだが、べつのSaaSでは法人向けのマルチテナントサービスを運営しており、サービスワイドの運営側GAは入れていないので、そういうときでも適切に集計できるのがよいと思った。
このあたりはOSS含むアクセス解析系プロダクトが、「データをだれとも共有せず自分のコントロール下に」みたいなのを売りにしていたのがわかる気がする。

ここから11か月運用して、結論から言うとCloudflare製品はすべて除去した。現在は自前のJSトラッカー、CloudFunctions、Cloud PubSub+BigQuery writeサブスクリプションというフルGCPの構成になっている。
CloudflareはProプラン以下だとまともにサポートが受けられない。サポートチケットもコミュニティフォーラムもdiscordもだめだった。Businessプラン以上、できれば(数千万ともいわれている)エンタープライズプランを使うほどしっかり活用するのがよさそうだ。
Zarazが突然HTTP Postの形式を変えてきたためQueueに送るべき情報不足で落ちていたようだったが、どこにも仕様変更のアナウンスはなかった。Betaだから仕方ないねとも思ったが、今年の7月にGAになっていた。いずれにしても返事が来ないので確認もできずフルGCP体制に移行した。