Cloud Run services ログ監視「だいたいぜんぶ」

## はじめに
こんにちは、Datadog Japan で Sales Engineer をしている [**AoTo**](https://qiita.com/AoTo0330) です。
Google Cloud で好きなサービスは、圧倒的に **Cloud Run** です！

この投稿は **[<font color="#6495ED">AoTo Advent Calendar 2024</font>](https://qiita.com/advent-calendar/2024/aoto) 16日目**の記事です。

皆さんは　**Cloud Run** の監視、きちんと行えているでしょうか？

**Cloud Run** は **Google Cloud** のマネージドサービスであり、デフォルトで **Cloud Logging, Cloud Monitoring, Cloud Trace** と統合されています。

![Monitoring_CloudRun.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2363567/17ae2c59-bb66-d48b-3a1b-a65c4740fc85.png)

では、**Cloud Run service** ではどのようなログが確認できるのでしょうか？
本ブログでは **Cloud Run services** が **Cloud Logging** に連携するログの種類とその仕組みを、**Cloud Run** の構造と共に体系的にまとめています🐶

:::note info
ちなみに Cloud Run 監視の基本は、[**Cloud Run Advent Calendar 2023**](https://qiita.com/advent-calendar/2023/cloud-run)」で Google Cloud Japan の諏訪さんがまとめられています。
:::

https://zenn.dev/google_cloud_jp/articles/cloudrun-monitoring

## Cloud Run の構造とログ連携
Cloud Run services は以下の箇所から3種類のログを記録し Cloud Logging に連携します。

![Logging_CloudRun_number.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2363567/f109fa83-07e1-1946-b576-f78b0a68da69.png)

 - ①**リクエストログ**: Cloud Run services に送信されたリクエストから**自動的に作成される**ログ
 - ②**コンテナログ**: コンテナが作成し [Cloud Logging で自動取得できる出力先](https://cloud.google.com/run/docs/logging?hl=ja#container-logs)に出力したログ
 - ③**システムログ**[^1]: プラットフォームが自動的に生成したコンテナインスタンスのログ
[^1]: 日本語 Google Cloud 公式ドキュメント「[Cloud Run でのログの記録と表示](https://cloud.google.com/run/docs/logging?hl=ja)」でのみ記載が確認できます。実際のメモリ制限を超過しコンテナインスタンスがシャットダウンされる際などに `varlog/system` に記録されます。

それぞれのログは自動的に作成または収集され、**Cloud Logging** から確認できます。`/var/log/`, `/dev/log/` ファイルパス以外のローカルファイルシステムにログを記録した場合、ログは収集されず **Cloud Run service** のメモリを消費して一時的に保存されます。

![CloudRun_AllLogs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2363567/ddc6b4ca-e10c-de86-635b-3cc8397923c4.png)

それぞれのログを Cloud Run の構成要素と合わせて示すと上図のようになります。

### ①リクエストログ
Cloud Run は高パフォーマンスなサーバレスコンテナ環境を実現するために、**Google Front End** を経由したリクエストの受信と、**HTTP プロキシ**によるアプリケーションインスタンス到達前のリクエスト終端が用意されます。これらの要素はマネージドサービスである **Cloud Run** では利用者が意識せず利用できます。

そして、**Cloud Run** に到達するリクエストを記録する**リクエストログ**は **Cloud Run** の HTTP プロキシの時点で自動的に作成されると推測されます。これにより、ゼロスケールする Cloud Run へのリクエストログを常に記録し、コンテナインスタンスやコンテナの起動やパフォーマンスに影響しません。

リクエストログは**ログ ID** に `run.googleapis.com%2Frequests`[^2] を持ち、リクエストとレスポンスに関連する様々な情報を記録します。以下のクエリで検索できます。
[^2]: 「%2F」は「/」の ASCII 文字から URL エンコードした文字です。

```hql: requestlog.ebnf
resource.type = "cloud_run_revision"
resource.labels.service_name = "<SERVICE_NAME>"
resource.labels.location = "<REGION_NAME>"
logName: "run.googleapis.com%2Frequests"
```

### ②コンテナログ
コンテナログは、アプリケーションコンテナのコードによって生成される様々なログの総称です。
具体的には、以下の複数の出力先のログを自動的に収集します。

 - 標準出力(`stdout`)・標準エラー(`stderr`)ストリーム
 - `/var/log` ディレクトリにあるすべてのファイル
 - syslog（`/dev/log`）

**Cloud Logging** への自動収集を利用せずに、出力先に **Cloud Logging** を直接指定することもできます。

 - [Cloud Logging クライアントライブラリ](https://cloud.google.com/logging/docs/reference/libraries)を使用して作成されたログ

各言語のロギングライブラリや **fluentd** を使用すると、[**Cloud Logging API v2**](https://cloud.google.com/logging/docs/reference/v2/rest) を利用して直接 **Cloud Logging** へ送信できます。もちろんこれらのログを上述のファイルパスにログファイルとして保存しても、**Cloud Logging** に自動転送されます。

前述のリクエストログと同様に、**ログ ID** にが `run.googleapis.com%2F` で始まり、ログの種類によって `stdout`, `stderr`, `/dev/log`, `/var/log` などの自動収集されたログの出力先が続きます。

```hql: requestlog.ebnf
resource.type = "cloud_run_revision"
resource.labels.service_name = "<SERVICE_NAME>"
resource.labels.location = "<REGION_NAME>"
logName: "run.googleapis.com%2F<LOGS_OUTPUTS>"
```

### ③システムログ
システムログの記述は2024年12月時点では日本語以外のドキュメントにはありません。
ですが、実際に Cloud Logging を確認すると、`logName: run.googleapis.com%2Fvarlog%2Fsystem` のようなログを確認できます。

これは **Cloud Run** インスタンス上でコンテナの起動や終了を扱う **Linux システムコール**が記録されます。具体的には `SIGTERM`, `SIGKILL` などが 「Conteiner called exit(1)」のような形で記録されます。

また、[コンテナのヘルスチェック](https://cloud.google.com/run/docs/configuring/healthchecks?hl=ja)で構成した [TCP 起動プローブ](https://cloud.google.com/run/docs/configuring/healthchecks?hl=ja#tcp-startup-probe)の内容もこちらに記録されます。

これらのシステムログより、**Cloud Run** の管理側からコンテナのスケールや終了のシステムコールや起動プローブが発行された記録を確認できます。以下のクエリで確認してみましょう。

```hql: requestlog.ebnf
resource.type = "cloud_run_revision"
resource.labels.service_name = "<SERVICE_NAME>"
resource.labels.location = "<REGION_NAME>"
logName: "run.googleapis.com%2Fvarlog%2Fsystem"
```

## Cloud Run のログ可視化
それぞれの方法で出力し **Cloud Logging** に収集されると **Logs Explorer** から検索可能になります。特に、自動収集されたログは、**Cloud Run** サービス・リビジョン・ロケーションに自動的に関連付けられます。これらのログに含まれる例外が **Cloud Logging** に統合されたエラー管理機能の **Error Reporting** に報告されます。

### Cloud Logging
Cloud Logging はシリアル化された JSON(構造化データ)を `jsonPayload` に配置し、単純なテキストメッセージは `textPayload` に配置します。これらの情報を含む[特殊フィールド](https://cloud.google.com/logging/docs/agent/logging/configuration?hl=ja#special-fields)は [LogEntry](https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry) の対応フィールドに書き込まれます。

[**Cloud Trace**](https://cloud.google.com/trace/docs/overview?hl=ja) と連携する場合、[Cloud Logging クライアントライブラリ](https://cloud.google.com/logging/docs/reference/libraries)を使用して `X-Cloud-Trace-Context` ヘッダーから抽出されたトレース ID を、 `logging.googleapis.com/trace` フィールドに含めた構造化 JSON ログを作成する必要があります。

こうした各 JSON フィールドは Logs Explorer での検索条件に指定できます。
Cloud Run から自動収集されたログにはそれぞれ様々な[ラベル](https://cloud.google.com/logging/docs/api/platform-logs#cloud_run)が自動的に付与され、`INFO`, `WARNING`, `ERROR` などの重大度も記録されます。

一方で前述の通り、**Cloud Run** のログは `resource.type = "cloud_run_revision"` を必ず持ちます。これは **Cloud Monitoring** と同様に **Cloud Run service** のリソースがリビジョン単位で記録されることを意味します。

それぞれのログの検索方法は上にも示していますが、より **Cloud Logging** を使いこなすためには[サンプルクエリ](https://cloud.google.com/logging/docs/view/query-library?hl=ja)をご参照ください。

### Error Reporting
Cloud Logging に収集された Cloud Run ログは、`severity >= ERROR` の場合、Error Reporting の対象となります。自動的に表示されるエラーは以下の通りです。

 - スタック トレースを含み、`stdout`, `stderr` などのログに送信されるすべての例外
 - 「Memory limit exceeded」と「No instances available」のシステムログに記録されるエラー

エラーを検索するために特別なクエリは必要ありません。
「cloud run」のように検索の対象としたい Google Cloud サービス名を入れると、対象のサービスから収集されたエラーが表示されます。Seen In 列に対象の Cloud Run サービス・リビジョンが表示されます。

https://cloud.google.com/run/docs/error-reporting?hl=ja

## 番外編: Cloud Run 監査ログ
Google Cloud サービスは、Google Cloud リソース内の管理アクティビティとアクセス アクティビティを記録する監査ログを生成します。Cloud Run サービスもこちらに漏れず、監査ログ(Audit Log)が記録され Cloud Logging では以下のクエリで検索できます。

```hql: requestlog.ebnf
protoPayload.serviceName="run.googleapis.com"
```

監査ログは IAM リソースによる操作を記録するため、各権限タイプ別に `type` プロパティへ値が記録されます。権限タイプは `ADMIN_READ`, `ADMIN_WRITE`, `DATA_READ`, `DATA_WRITE` のいずれかになります。

監査ログは2種類に分類されます。
データアクセス監査ログは、`type` プロパティ値が `DATA_READ`, `DATA_WRITE`, `ADMIN_READ` の IAM 権限を必要とするメソッドの記録です。管理アクティビティ監査ログは、`type` プロパティ値が `ADMIN_WRITE` の IAM 権限を必要とするメソッドの記録です。

記録される全ての監査ログの一覧は公式ドキュメントをご参照ください。

https://cloud.google.com/run/docs/audit-logging?hl=ja

## おわりに
**Cloud Run services** で記録される様々なログを、Cloud Run の構成要素と共に図解し解説しました。

**Cloud Run services** は利用者が意識しないで記録されるリクエストログ・システムログ・監査ログがある一方、アプリケーションコンテナから生成されるコンテナログがあります。これらの違いを理解して、コンテナログを生成する際に正しく Cloud Logging へ連携される方法の理解に繋がれば嬉しいです🐶