新バージョンの Go ロギング ライブラリでの構造化ログのサポートを強化

Google Cloud Japan Team
※この投稿は米国時間 2022 年 7 月 2 日に、Google Cloud blog に投稿されたものの抄訳です。
Go 向け Google ロギング クライアント ライブラリの新しいバージョンがリリースされました。バージョン 1.5 では、新機能とバグの修正が追加されています。その一つである構造化ロギング機能は、Google ロギング クライアント ライブラリでの構造化ロギングのサポートを強化するための昨年の取り組みを完結するものです。
以下に、バージョン 1.5 で追加された新機能の一部をご紹介します。
アプリケーションの実行に使用されている Google Cloud リソースを検出およびキャプチャする方法の高速化と堅牢化。
ログのオブザーバビリティをサポートしてデバッグとトラブルシューティングを可能にするソースの場所の自動検出。
ログエントリ内のトレース情報をキャプチャするための W3C ヘッダー traceparent。
Logger インスタンス内で partialSuccess フラグをサポートすることによってログエントリの一括取り込みをより適切に制御。
構造化ロギング形式を使用してログを stdout および stderr にリダイレクトするプロセス外取り込みのサポート。
各機能について詳しく見ていきましょう。
リソース検出
リソース検出は、ロギング ライブラリの既存の機能であり、アプリケーションの実行に使用されているリソースを検出します。この機能は、リソースのメタデータを取得し、アプリケーションがライブラリを使用してログエントリを取り込むたびに、このメタデータを暗黙的に追加します。また、リソースのメタデータ サーバーからリソースの属性を多数収集するため、Google Cloud で実行されるアプリケーションで特に役立ちます。これらの属性は、取り込んだログを、VM の場所、コンテナの名前、AppEngine サービスのサービス ID などの追加情報で強化します。以下の JSON は、こちらのドキュメントに沿って GKE コンテナとしてのリソースの検出とリソース メタデータの取得を行った後の、取得された情報のサンプルを示しています。
実装は、データ収集プロセス中のパフォーマンスの低下を回避するように最適化されています。以前は、リソースを識別するためのヒューリスティックが、多くの誤検出を引き起こす可能性のある環境変数に大きく依存していました。また、実装時にメタデータ サーバーに対して実行されるクエリが多すぎるため、応答が遅れることもありました。1.5 リリースでは、ヒューリスティックが更新され、リソース検出ロジックの環境変数以外に追加のアーティファクトが使用されるようになり、メタデータ サーバーへのクエリの数が最小限に抑えられています。その結果、GCP リソースの誤検出が桁違いに減少し、非 GCP リソースでヒューリスティックを実行する場合のパフォーマンスの低下も軽減されました。この変更は取り込みプロセスに影響せず、アプリケーションのコードを変更する必要がありません。
ソースの場所のキャプチャ
ログが取り込まれたコード内の場所をキャプチャする際に便利な機能です。主な用途はトラブルシューティングとデバッグですが、それ以外の状況でも役立つ場合があります。このバージョンのライブラリでは、Logger.Log() または Logger.LogSync() 関数を使用して取り込まれたログエントリごとに、ソースの場所のメタデータをキャプチャするようロガー インスタンスを設定できます。必要な操作は、ロガーの新しいインスタンスを作成するときに、Client.Logger() の呼び出しで SourceLocationPopulation() の出力を LoggerOption 引数として渡すだけです。次のスニペットは、重大度がデバッグに設定されたログが取り込まれるたびにソースの場所のメタデータを追加するロガー インスタンスを作成します。
関数 SourceLocationPopulation() は次の定数を受け入れます。
logging.DoNotPopulateSourceLocation - 取り込んだログでソースの場所をキャプチャできないようにするデフォルトの設定です。
logging.PopulateSourceLocationForDebugEntries - 重大度がデバッグのログにソースの場所メタデータを追加します。
logging.AlwaysPopulateSourceLocation - 取り込んだすべてのログにソースの場所を入力します。
Go でソースの場所をキャプチャする操作によって、ログの取り込みの合計実行時間が 2 倍に増える可能性があるため、この機能を明示的に有効にする必要があります。取り込んだすべてのログに対して有効にすることはおすすめしません。
トレースに W3C コンテキスト ヘッダーを使用する
以前のバージョンのライブラリでは、ログにトレース情報を追加できました。これを行う方法として、トレース ID、スパン ID と、オプションでサンプリング フラグを直接指定していました。次のコードは、トレース ID とスパン ID を手動で設定する方法を示しています。
または、間接的な方法として、次のように http.Request のインスタンスを HTTP リクエスト メタデータの一部として渡していました。
後者の場合、ライブラリは x-cloud-tracing-context ヘッダーからトレース情報を取得しようとします。このリリース以降、ライブラリは W3C トレース コンテキスト ヘッダーもサポートします。両方のヘッダーが存在する場合、トレース情報は W3C traceparent ヘッダーからキャプチャされます。
プロセス外ログの取り込み
デフォルトで、ライブラリは Cloud Logging API を直接呼び出すことにより、同期および非同期のログ取り込みをサポートします。ログの取り込みは、外部のロギング エージェントまたはログ収集の組み込みサポートを使用して行う方が適切な場合があります。このリリースでは、ログを Cloud Logging に直接取り込むのではなく、stdout または stderr にログを書き込むようにロガー インスタンスを設定できます。次の例では、特別にフォーマットされた JSON 文字列を使用してログを stdout にリダイレクトするロガーを作成します。
上記のコードの場合、標準出力への出力は次の行のようになります。
状況によっては、標準出力をログの出力に使用できない場合、出力を標準エラー(os.Stderr)にリダイレクトして同じ効果を得るようにロガーを設定できます。
プロセス外ロギングを使用する場合は、次の点に注意してください。
メソッド Logger.Log() と Logger.LogSync() は、ロガーがプロセス外ロギング オプションを使用して設定されている場合と同様に動作し、指定された io.Write ライターに Jsonified ログを書き込みます。外部のロギング エージェントがログの収集と取り込みを決定します。
ログ ID は制御できません。ロギング エージェントまたはマネージド サービス(Cloud Run など)の組み込みサポートによって取り込まれるすべてのログは、プロセス外で決定されたログ ID を使用します。
バッチ取り込みの制御機能の強化
Logger.Log() 関数を使用してログを取り込む場合、非同期取り込みは entries.write Logging API を使用し、複数のログエントリを一括で取り込みます。集約ログのうち 1 つでも取り込みが失敗すると、ログは取り込まれません。このリリース以降、部分的な成功フラグを有効にすることで、このロジックを制御できます。このフラグを設定すると、INVALID_ARGUMENT や PERMISSION_DENIED などの永続的なエラーが原因で他のログエントリが失敗した場合でも、Logging API はすべてのログを取り込もうとします。このオプションを有効にするには、PartialSuccess ロガー オプションを使用して新しいロガーを作成するときに次のように指定します。
まとめ
バージョン 1.5 にアップグレードすると、ライブラリの動作を変更することなく、より堅牢で確定的なリソース検出アルゴリズムを利用できます。プロセス外取り込み、ソースの場所、バッチ取り込み制御などの追加機能は、ロガー オプションを使用して有効にできます。これらの新機能とバグの修正により、ライブラリの動作がより確定的で堅牢になります。
このリリースの詳細は go.pkg.dev に掲載されています。GitHub でライブラリのプロジェクトもご確認ください。