Skip to main content
分散トレーシングは、1件のリクエストや処理を、計測済みのサービスをまたいで追跡します。トレースは、その処理のスパンをまとめます。各スパンは、HTTP リクエスト、データベース呼び出し、キュー操作、バックグラウンドジョブなど、時間を計測した1つの処理です。スパンが欠けていると、経路の一部はわかりません。 ログが障害を報告していても処理の経路がわからない場合は、トレースを使います。トレースからは次のことがわかります。
  • どの処理がリクエストを開始したか。
  • リクエストがどこで時間を使ったか。
  • どの子の処理がエラーを返したか。
  • 同じトレース ID を持つログ、課題、アクション、メトリクスはどれか。
  • 各スパンを送信したサービス、環境、リリースはどれか。

トレースとスパンのフィールド

ルートスパンはトレースを開始し、親を持ちません。子スパンは、同じトレース ID、独自のスパン ID、親の ID を持ちます。処理どうしを結び付けるのは、これらの ID だけです。タイムスタンプだけでは結び付きません。LogBrew がスパンをエラースパンとして数えるのは、その status が error の場合だけです。

サービスをまたぐリクエスト

  1. Web サービスが、チェックアウトのルートでサーバースパンを開始します。
  2. 決済クライアントが、外部への HTTP リクエストのために子スパンを作成します。
  3. 決済サービスが、自身のサーバースパンでトレースを引き継ぎます。
  4. データベースのヘルパーが、書き込みの子スパンを記録します。
  5. アプリが、アクティブな決済スパンの中で安全なエラーログを送信します。
5件のレコードはすべて同じトレース ID を持ちます。サービスがトレースコンテキストを受け取らないと、時間が重なっていても、その処理はトレースに加わりません。

コンテキストを伝搬する

LogBrew の SDK は W3C トレースコンテキストを使います。たとえば Node.js SDK は、受信した有効な traceparent ヘッダーを、新しいリクエストスパンで引き継ぎます。ヘッダーがないか無効な場合は、新しいルートスパンを開始します。そのリクエストの範囲内で取得したログ、課題、アクション、メトリクスは、リクエストのトレースを持ちます。 外部への呼び出しの計測は、tracePropagationTargets などで設定した送信先にだけ traceparent ヘッダーを書き込みます。トレースコンテキストは、信頼できる計測済みのサービスにだけ送信してください。トレース ID は処理どうしを関連付けるものです。認証ではありません。 キューのメッセージもトレースコンテキストを運べます。Node.js では、プロデューサーの処理で createLogBrewQueueTraceHeaders() を呼び出し、メッセージに traceparent ヘッダーを追加します。コンシューマーでは、そのヘッダーを traceparent として queueOperationWithLogBrewSpan() に渡します。JavaScript のキューのトレーシングを参照してください。 Node.js と Python のリクエストと外部呼び出しの連携は、リクエストやレスポンスのボディ、クエリ文字列、任意のヘッダー、traceparent の生の値をスパンに記録しません。スパンには、具体的な URL ではなくルートテンプレートの名前を付けてください。ご利用のランタイムの連携については、SDK 連携を読んでください。

取得用のスパン

LogBrew は、新しいログ、課題、アクション、メトリクスをすべてトレース ID 付きで保存します。シグナルが同じ配信内のスパンを参照していない場合、LogBrew はそのシグナルのために取得用のスパンを1つ追加します。 その後、シグナルの span_id は取得用のスパンを識別します。シグナルにトレースコンテキストがなかった場合、LogBrew はそのシグナルのために新しいトレース ID を作成します。このトレースは、LogBrew がシグナルを保存したことを示します。リクエストの経路は示しません。1つのトレース内の取得用のスパンを、1件のリクエストとして読まないでください。 取得用のスパンは span_count と error_span_count に数えられます。そのため、アプリケーションの処理がどれも失敗していないトレースでも、エラーログがあれば --status error で選ばれることがあります。結論を出す前に、各エラースパンの operation を読んでください。

トレースを読む

ログ、課題、トレース一覧から得た正確なトレース ID を使います。
--status error は、エラースパンを1つ以上持つトレースを選びます。--status ok は、エラースパンを持たないトレースを選びます。--min-duration-ms 500 は、500ミリ秒以上かかったトレースを選びます。 まずルートスパンの所要時間を読みます。次に、最も長い子スパンとエラーのステータスを調べます。ステージング環境のトレースが本番環境についての証拠にならないように、プロジェクト、サービス、環境、リリースを常に確認してください。 1つのトレースが示すのは1回の実行で、パフォーマンスの基準値ではありません。パフォーマンスの変更を提案する前に、複数のトレースを関連するメトリクスの推移と比較してください。

トレースの要約

GET /api/telemetry/traces/{trace_id}/summary は、スパンの属性を含まない要約を返します。 root_span.parent_span_id に値がある場合、本当のルートスパンはトレース内にありません。root_span をリクエストの開始として読まないでください。

トレースを説明する

logbrew explain trace は、トレースの調査結果を返します。
analysis.causality は evidence_only です。この分析は根本原因を証明しません。CLI はレスポンスのバージョン3を要求します。このバージョンでは、関連する課題、アクション、メトリクスのそれぞれにも正確な span_id が付きます。 1つのスパンを、その親、子、サービスの境界とともに調べるには、次を実行します。
topology.parent_chain_status は、親の連なりが完全かどうかを示します。

トレースコンテキストの欠落

すべてのイベントに、そのリクエストのトレースがあるわけではありません。トレースの状態を読んでください。 not_linked はエラーではありません。available のトレースが、イベントにリクエストのコンテキストがなかったことを示す場合もあります。イベントの取得用のスパンに parent_span_id がなければ、アプリがイベントを取得したときにアクティブなスパンはありませんでした。リクエストの範囲外で動くバックグラウンド処理では、よくこの結果になります。欠けている関係を見つけるには、次のようにします。
  1. イベントのプロジェクト、サービス、環境、リリース、時刻を読みます。
  2. その処理が、計測済みのリクエストや処理の中で実行されたことを確認します。
  3. クライアントとサーバーの連携が、その境界をまたいでコンテキストを伝搬していることを確認します。
  4. 計測を修正したら、新しいイベントを取得して読みます。
SDK の新しいバージョンは、以前に送信したイベントにトレースコンテキストを追加しません。タイムスタンプ、ルート、メッセージ、リリースでイベントをトレースに結び付けないでください。

1つのプロジェクトのトレーシングを計画する

チェックアウトなど、重要なリクエストやジョブを1つ選んで始めます。境界は1つずつ計測します。
  1. 受信したリクエスト、またはバックグラウンドの処理のスパンを作成します。
  2. 重要な外部呼び出しに子スパンを追加します。
  3. 信頼できるサービスの境界をまたいで、W3C トレースコンテキストを引き継ぎます。
  4. アクティブなスパンの中で安全なログを送信します。
  5. そのログを読み、トレース ID を開いて、ルートスパン、子スパン、サービス、環境、リリース、ステータス、所要時間を確認します。
この確認に合格してから、次の境界を追加します。トレースを共有していることは相関を示します。1つのスパンが課題の原因であることを証明するものではありません。 スパン名を確認するには、logbrew traces --project "<project_id>" --pagination cursor --json を実行します。naming_quality オブジェクトは、そのページ内で、ルートスパンの名前が汎用的なトレース(generic_name_traces)と、どのルートにも一致しないトレース(unmatched_route_traces)を数えます。名前の付け方に対応が必要な場合、naming_quality.next_action.code は improve_trace_naming になります。