ログの書き込みと表示

このページでは、App Engine アプリで使用可能なログと、ログエントリの作成、関連付け、表示を行う方法について説明します。

App Engine では次の 2 種類のログを収集します。

  • リクエストログ: アプリに送信されたリクエストのログ。デフォルトでは、App Engine は、アプリが受信した HTTP リクエストごとにログエントリを自動的に出力します。

  • アプリログ: サポートされているフレームワークまたはファイルに書き込んだログエントリに基づいて App Engine アプリが出力するログエントリ。

App Engine は、リクエストログとアプリログの両方を Cloud Logging エージェントに自動的に送信します。

アプリログを書き込む

App Engine はアプリに送信されたリクエストのログを自動的に出力します。ユーザーがリクエストログを作成する必要はありません。このセクションでは、アプリログを書き込む方法について説明します。

App Engine アプリからアプリログを書き込むときに、次の方法でログが書き込まれていれば、Cloud Logging が自動的にログを取得します。

Cloud Logging との統合

App Engine アプリを Cloud Logging と統合できます。この方法では Cloud Logging が提供するすべての機能を使用できます。Google 固有のコードを数行追加するだけで済みます。

Go 用 Cloud Logging ライブラリを使用すると、Cloud Logging を使用する際により高レベルのレイヤが提供されます。詳細については、Go 用に Cloud Logging を設定するをご覧ください。

構造化ログを stdoutstderr に書き込む

デフォルトでは、App Engine は Cloud Logging クライアント ライブラリを使用してログを送信します。ただし、このメソッドは構造化ロギングをサポートしていません。構造化ログを書き込むには、stdout/stderr を使用する必要があります。また、テキスト文字列を stdoutstderr に送信することもできます。デフォルトでは、ログのペイロードはログエントリの textPayload フィールドに保存されたテキスト文字列です。文字列は、ログ エクスプローラ、コマンドライン、Cloud Logging API にメッセージとして表示され、メッセージを発行した App Engine のサービスとバージョンに関連付けられます。

ログからより多くの情報を取得するには、ログ エクスプローラで重大度レベルを使用して、これらの文字列をフィルタします。文字列をフィルタするには、文字列を構造化データとしてフォーマットする必要があります。これを行うには、シリアル化された JSON を 1 行形式でログに書き込みます。App Engine は、このシリアル化された JSON 行を取得して解析し、ログエントリの textPayload ではなく jsonPayload フィールドに配置します。

次のスニペットは、このような構造化ログの書き込みを示しています。

各ログエントリの構造は、Entry タイプによって指定されます。


// Entry defines a log entry.
type Entry struct {
	Message  string `json:"message"`
	Severity string `json:"severity,omitempty"`
	Trace    string `json:"logging.googleapis.com/trace,omitempty"`

	// Logs Explorer allows filtering and display of this as `jsonPayload.component`.
	Component string `json:"component,omitempty"`
}

// String renders an entry structure to the JSON format expected by Cloud Logging.
func (e Entry) String() string {
	if e.Severity == "" {
		e.Severity = "INFO"
	}
	out, err := json.Marshal(e)
	if err != nil {
		log.Printf("json.Marshal: %v", err)
	}
	return string(out)
}

App Engine スタンダード環境では、構造化ログを stdoutstderr に書き込んでも、Cloud Logging API での 1 分あたりのログ取り込みリクエスト数にカウントされません。

メッセージ内の特別な JSON フィールド

特殊フィールドのドキュメントで説明されているように、構造化ログを JSON ディクショナリとして提供すると、いくつかの特殊フィールドが jsonPayload から削除され、生成された LogEntry の対応フィールドに書き込まれます。

たとえば、JSON に severity プロパティが含まれている場合、jsonPayload から削除され、代わりにログエントリの severity として表示されます。message プロパティが存在する場合は、ログエントリのメイン表示テキストとして使用されます。

リクエストログとアプリログを関連付ける

エントリを JSON オブジェクトとしてフォーマットし、特定のメタデータを提供すると、フィルタリングだけでなく、リクエストログとの関連付けも有効にできます。リクエストログのエントリとアプリログのエントリを関連付けるには、リクエストのトレース ID が必要です。手順に沿ってログ メッセージを関連付けます。

  1. X-Cloud-Trace-Context リクエスト ヘッダーからトレース ID を抽出します。
  2. 構造化ログエントリで、ID を logging.googleapis.com/trace という名前のフィールドに書き込みます。X-Cloud-Trace-Context ヘッダーの詳細については、リクエストを強制的にトレースするをご覧ください。

相関ログを表示するには、ログ エクスプローラで相関ログエントリを表示するをご覧ください。

ログを表示する

アプリログとリクエストログを表示する方法はいくつかあります。

ログ エクスプローラを使用する

ログ エクスプローラを使用して、アプリログとリクエストログを表示できます。

  1. Google Cloud コンソールの [ログ エクスプローラ] に移動します。

    [ログ エクスプローラ] に移動

  2. ページの上部にある既存の Google Cloud プロジェクトを選択します。

  3. [リソースの種類] で [GAE アプリケーション] を選択します。

ログ エクスプローラでは、App Engine サービスとバージョン、その他の条件でフィルタリングできます。ログで特定のエントリを検索することもできます。詳細については、ログ エクスプローラの使用をご覧ください。

単純なテキスト エントリを標準出力に送信する場合は、ログビューアを使用して重要度でアプリエントリをフィルタリングすることはできません。また、特定のリクエストに対応するアプリログを表示することもできません。ログ エクスプローラでは、テキストやタイムスタンプなど、他のタイプのフィルタを使用することもできます。

ログ エクスプローラで相関ログエントリを表示する

ログ エクスプローラで、親ログエントリに関連付けられた子ログエントリを表示するには、ログエントリを開きます。

たとえば、App Engine リクエストのログエントリとアプリケーション ログエントリを表示するには、次のようにします。

  1. Google Cloud コンソールのナビゲーション パネルで、[ロギング] を選択してから、[ログ エクスプローラ] を選択します。

    [ログ エクスプローラ] に移動

  2. [リソースの種類] で [GAE アプリケーション] を選択します。

  3. リクエストログを表示して関連付けるには、[ログ名] で [request_log] を選択します。また、リクエストログで関連付けるには、[関連付け] をクリックして [request_log] を選択します。

    ログの関連付け

  4. [クエリ結果] ペインで、ログエントリを開くには、[開く] をクリックします。エントリを開くと、各リクエストログに関連付けられたアプリログが表示されます。

ログのフィルタを作成すると、各リクエストログに対応するアプリログが子ログとして表示されます。ログ エクスプローラは、アプリケーションが google-cloud-logging ライブラリを使用していると仮定して、アプリログの trace フィールドと特定のリクエストログを関連付けます。

次の図は、trace フィールドでグループ化されたアプリログを示しています。

アプリログのエントリがリクエストログのエントリにネストされている。

Google Cloud CLI を使用する

App Engine のログをコマンドラインから表示するには、次のコマンドを使用します。

gcloud app logs tail

詳細については、gcloud app logs tail をご覧ください。

プログラムでログを読み取る

プログラムでログを読み取るには、次のいずれかの方法を使用します。

料金、割り当て、ログの保持ポリシー

リクエストログとアプリログの両方に適用される料金については、Cloud Logging の料金をご覧ください。

ログの保持ポリシーとログエントリの最大サイズについては、割り当てと上限をご覧ください。ログを長期間保存する場合は、Cloud Storage にログをエクスポートできます。ログをさらに処理するために、BigQuery や Pub/Sub へエクスポートすることもできます。

ログリソース使用状況の管理

アプリのコードからログエントリの書き込み量を調整することで、アプリログからロギング アクティビティの量を制御できます。リクエストログは自動的に作成されるため、アプリに関連付けられたリクエスト ログエントリの数を管理するには、Cloud Logging のログ除外機能を使用します。

既知の問題

第 2 世代のランタイムのロギングに関する問題は次のとおりです。

  • アプリログのエントリが、リクエストログに関連付けられない場合がある。これは、アプリがリクエストを初めて受信した場合および、App Engine がアプリログにステータス メッセージを書き込む場合に発生します。詳細については、https://issuetracker.google.com/issues/138365527 をご覧ください。

  • ログシンクから Cloud Storage にログを転送した場合、Cloud Storage の転送先にはリクエストログのみが格納されます。App Engine は、複数のフォルダにアプリのログを書き込みます。

  • BigQuery は、リクエストログの @type フィールドが原因でログを取り込めません。BigQuery ではフィールド名に @type を使用できないため、自動スキーマ検出が中断されます。この問題を解決するには、スキーマを手動で定義し、リクエストログから @type フィールドを削除する必要があります。

  • ロギング REST API を使用すると、バックグラウンド スレッドが Cloud Logging にログを書き込みます。メインスレッドがアクティブでない場合、インスタンスは CPU 時間を取得しないため、バックグラウンド スレッドが停止します。ログ処理時間が遅延します。ある時点でインスタンスが削除され、送信されていないログがすべて失われます。ログが失われないようにするには、次のいずれかのオプションを使用します。

    • gRPC を使用するように Cloud Logging SDK を構成します。gRPC を使用すると、ログはすぐに Cloud Logging に送信されます。ただし、これは必要な CPU の上限を引き上げる可能性があります。
    • stdout/stderr を使用して、Cloud Logging にログメッセージを送信します。このパイプラインは App Engine インスタンスの外部にあるため、スロットルされることはありません。

次のステップ