Google CloudのCloud Runで動いているシステムのログを、定期的に解析・レポート化したいと思います。
開発・運用しているサービスのバックエンドでCloud Runを走らせており、定期的なリクエスト分析を行なってサービス改善に繋げることが動機。
大まかな流れは下記。
- Cloud Runの実行ログが、ログストレージ(Cloud Storage)に溜まる。
- ログをBigQueryに連携しSQLで処理した上で、1.とは別のバケットに格納する。
- 2.の処理を定期実行する。
- (今回のスコープ外)Cloud Storageの保存イベントをトリガーにして、後続の処理を行う。
Cloud Runの実行ログを、ログストレージに溜める
デフォルトで取得されるので割愛。
ログバケットの保存期間は_Defaultが120日、_Requiredが400日なので、必要に応じてログの転送(Monitoring > ログルータ)を設定しておくと良い。
ログをBigQueryに連携し、クエリする
「BigQuery > スタジオ」 を開き、左ペインから「エクスプローラ」を選択すると、プロジェクトID配下に「データセット」が出てくるのでクリックする。
ドリルダウンするとデフォルトで取得されているログテーブルが表示される。
今回は、Cloud RunのHTTPSリクエストに関するログのみを解析したいので、run_googleapis_com_requestsをクリックする。
テーブルの詳細(スキーマとか、データのプレビューとか)が表示されるので、必要があれば確認する。特に問題がなければ「クエリ」をクリックする。
クエリエディタに飛ぶ。あとはゴリゴリとSQLを書いていく。
IMPORTする先は{project_id}.{dataset}.{table}で指定されている。今回はopensearch-***.opensearch_logging.run_googleapis_com_requests。
「実行」をクリックすれば、手元でSQLの実行結果を確認することもできる。
良い感じになったら、「保存 > クエリを保存」で名前をつけて保存しておくと良い。
Cloud Storageに格納する
バケットの作成・設定
あらかじめ保存先のバケットを作成しておく。ここで注意すべきは下記。
注意: Cloud Storage バケットにデータをエクスポートする場合は、バケットでバケットロックと削除(復元可能)の保持ポリシーを無効にすることを強くおすすめします。これらの保持ポリシーが設定されたバケットにエクスポートすると、BigQuery はバケットへのファイルの書き換えを試みます。バケットの保持ポリシーでファイルの上書きが禁止されている場合、書き換えが失敗し、追加料金が発生する可能性があります。これらのポリシーは、エクスポートが完了した後に再度有効にできます。
サービスアカウントの作成
必要な権限を持ったサービスアカウントを作成する。
必要なのは下記。もしかしたら過剰かも。
- BigQuery テーブルからデータをエクスポートするための権限(
bigquery.tables.export) - 抽出ジョブの実行権限(
bigquery.jobs.create) - Cloud Storage バケットにデータを書き込む権限(
storage.objects.create,storage.objects.delete)
SQLの修正
作成したSQLを次のように変更する.
旧:
SELECT timestamp, httpRequest.requestUrl
FROM `opensearch-***`.`opensearch_logging`.`run_googleapis_com_requests`
WHERE
httpRequest.requestMethod = "GET"
ORDER BY timestamp
新(CSVで保存する場合):
-- YOUR_BUCKET にはデータ保存用に作成したバケット名を入れる
EXPORT DATA
OPTIONS (
uri = 'gs://{YOUR_BUCKET}/*.csv',
format = 'CSV',
header = TRUE,
field_delimiter = ';',
overwrite=TRUE
)
AS (
SELECT timestamp, httpRequest.requestUrl
FROM `opensearch-***`.`opensearch_logging`.`run_googleapis_com_requests`
WHERE
httpRequest.requestMethod = "GET"
ORDER BY timestamp
);
これを実行すると、{YOUR_BUCKET}/000000000000.csvが作成される。
いくつかの注意
- オプションで指定するURIからワイルドカードを削除すると、
Invalid uri specification. Option 'uri' value must be a wild card URI.エラーになる。- 一度に出力できるデータはファイルごとに1GBまでなので、これを超えると複数ファイルに分割して保存してくれる。
- ワイルドカードを指定しても、複数回エクスポートした際に自動採番してくれるわけではない(→次のセクション)。
-
overwriteオプションにFALSEを指定、もしくは削除すると、overwrite option is not specified and destination is not empty.エラーになる。 - JSON形式を指定して出力すると、レコードが複数存在する場合は「JSONを改行で連結した文字列」として保存される。
{"timestamp":"2025-12-13T02:51:58.533385+00:00","requestUrl":"https://api.example.com/v2/uri/BK527814?format=application/json"}
{"timestamp":"2025-12-13T02:51:58.722582+00:00","requestUrl":"https://api.example.com/v2/uri/BK527814/related?format=application/json"}
{"timestamp":"2025-12-13T05:37:06.854223+00:00","requestUrl":"https://api.example.com/v2/uri/BK839830?format=application/json"}
タイムスタンプによる命名
解析・出力を定期実行し出力ファイルを新規作成する場合には、クエリ側でファイル名(URI)を指定する必要がある。
タイムスタンプを使った指定方法は次のとおり。CURRENT_TIMESTAMPで現在時刻を受け取り、FORMAT_TIMESTAMPでstring文字列にフォーマット、CONCATで文字列を連結する。
EXPORT DATA
OPTIONS (
uri = CONCAT(
'gs://{YOUR_BUCKET}/',
FORMAT_TIMESTAMP('%Y%m%d_%H%M%S', CURRENT_TIMESTAMP()),
'_*.csv'
),
format = 'JSON',
header = TRUE,
field_delimiter = ';',
overwrite=TRUE
)
...
処理を定期実行する
タブから「スケジュール」を開き、必要な情報を入力する。
「サービスアカウント」では、「サービスアカウントの作成」に記載の権限を持つサービスアカウントを選択する。
終わり。
調べきれていない部分が多々あるので、順次加筆していく予定です。
ノートブックやパイプラインも使っていきたい。



