ブラウザのログをCloud RunのREST APIで受けBigQueryに流す

by

@wapa5pow

最近はすべてのログはBigQueryに流すという運用をしています。iOS/AndroidのアプリログはFirebase AnalyticsでログをとってFirebaseの設定からBigQueryにエクスポートできます。

ブラウザの場合は自分は定まった方法をもっていなくて、Google Analyticsのカスタムイベントを送るとかがあるかなと思いますが今回はCloud RunのREST APIを使ってさくっと構築できる方法があったので構築方法を紹介します。

構築方法

構成は以下のようになります。

architecture

Cloud RunにREST APIを作ってGoのプログラムを実行し標準出力にJSON形式でログを出力します。そのログをLoggingのフィルタ機能を使ってフィルタし、エクスポート機能でBigQueryに出力します。

Cloud RunはUsing Cloud Pub/Sub with Cloud Run tutorialを参考するといいと思います。たとえば以下のようなコードでJSONをうけとってそのまま標準出力に出します。

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"
)

func main() {
	http.HandleFunc("/", LoggingHandler)
	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
		fmt.Printf("Defaulting to port %s\n", port)
	}
	fmt.Printf("Listening on port %s\n", port)
	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
}

type JSONMessage struct {
	Message interface{} `json:"message"`
}

func LoggingHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Access-Control-Max-Age", "86400")
	w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE")
	w.Header().Set("Access-Control-Allow-Headers", "Origin, Content-Type, Content-Length, Accept-Encoding, X-Access-Token, X-CSRF-Token, Authorization")
	w.Header().Set("Access-Control-Expose-Headers", "Content-Length")
	w.Header().Set("Access-Control-Allow-Credentials", "true")

	if r.Method == "OPTIONS" {
		w.WriteHeader(http.StatusOK)
		return
	}

	var m JSONMessage
	if err := json.NewDecoder(r.Body).Decode(&m); err != nil {
		fmt.Printf("json.NewDecoder: %v\n", err)
		http.Error(w, "Bad Request", http.StatusBadRequest)
		return
	}
	if m.Message == nil {
		http.Error(w, "Bad Request", http.StatusBadRequest)
	}

	j, _ := json.Marshal(m)
	fmt.Println(string(j))
}

Cloud Runにデプロイしたら実際に動くか確かめてみます。https://aaa.run.appはプロジェクトに合わせて変更して、以下のようにAPIをたたきます。

curl https://aaa.run.app -X POST -H "Content-Type: application/json" -d '{"message": { "name":"John", "age":30, "car":null }}'

次に、LoggingからBigQueryへのエクスポートを設定します。デプロイしたCloud Runのサービス名がloggerだとすると以下のようにLoggingのフィルタを設定するとmessageキーをもったJSONのログだけをフィルタすることができます。

resource.type = "cloud_run_revision"
resource.labels.service_name = "logger"
jsonPayload.message:*

うまくフィルタされたことを確認して、CREATE EXPORTからBigQueryへのエクスポートを作成します。

logging

これで完了です。先程実行したcurlコマンドを実行してしばらく待ってからBigQueryで確認してみると以下のようにログが取り込まれています。

bigquery

まとめ

Cloud Runを使ってブラウザのログをBigQueryへと取り込む方法を紹介しました。Cloud Runはまだベータで日本リージョンにないのでレスポンスタイムが気になりますがいずれ日本にくるはずなので待っています。どうしても日本リージョンで動かしたい場合はCloud Run on GKEを使うといいと思います。

今回認証も何もつけていませんが必要に応じてFirebase Authenticationを使ってセキュリティを高めてください。