> ## Documentation Index
> Fetch the complete documentation index at: https://docs.logbrew.co/llms.txt
> Use this file to discover all available pages before exploring further.

# 分散トレーシング：トレース、スパン、コンテキスト

> LogBrew で、分散トレースとスパンがリクエスト、ログ、課題、アクション、メトリクスをどう結び付けるかを説明します。

分散トレーシングは、1件のリクエストや処理を、計測済みのサービスをまたいで追跡します。トレースは、その処理のスパンをまとめます。各スパンは、HTTP リクエスト、データベース呼び出し、キュー操作、バックグラウンドジョブなど、時間を計測した1つの処理です。スパンが欠けていると、経路の一部はわかりません。

ログが障害を報告していても処理の経路がわからない場合は、トレースを使います。トレースからは次のことがわかります。

* どの処理がリクエストを開始したか。
* リクエストがどこで時間を使ったか。
* どの子の処理がエラーを返したか。
* 同じトレース ID を持つログ、課題、アクション、メトリクスはどれか。
* 各スパンを送信したサービス、環境、リリースはどれか。

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

| フィールド | 意味 |
| - | - |
| `trace_id` | スパンが属するトレースを識別します。 |
| `span_id` | トレース内の1つの処理を識別します。 |
| `parent_span_id` | 子の処理を、それを開始した処理に結び付けます。ルートスパンにはありません。 |
| `name` | ルートテンプレートなど、処理の名前です。 |
| `operation` | `http.server` や `db.query` など、処理の種類です。 |
| `status` | `ok`、`error`、`cancelled` など、報告された結果です。 |
| `started_at` | 処理が開始した時刻です。 |
| `duration_ms` | 処理の実行にかかった時間（ミリ秒）です。 |
| `service_name`、`environment`、`release` | スパンを送信したサービスの範囲です。 |

ルートスパンはトレースを開始し、親を持ちません。子スパンは、同じトレース 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 のキューのトレーシング](/ja/guides/sdk-ingestion#javascript-queue-tracing)を参照してください。

Node.js と Python のリクエストと外部呼び出しの連携は、リクエストやレスポンスのボディ、クエリ文字列、任意のヘッダー、`traceparent` の生の値をスパンに記録しません。スパンには、具体的な URL ではなくルートテンプレートの名前を付けてください。ご利用のランタイムの連携については、[SDK 連携](/ja/guides/sdk-ingestion)を読んでください。

## <span id="capture-spans">取得用のスパン</span>

LogBrew は、新しいログ、課題、アクション、メトリクスをすべてトレース ID 付きで保存します。シグナルが同じ配信内のスパンを参照していない場合、LogBrew はそのシグナルのために取得用のスパンを1つ追加します。

| フィールド | 値 |
| - | - |
| `name` | `log capture`、`issue capture`、`action capture`、`metric capture` のいずれか |
| `operation` | `logbrew.log`、`logbrew.issue`、`logbrew.action`、`logbrew.metric` のいずれか |
| `duration_ms` | `0` |
| `parent_span_id` | アプリがシグナルを取得したときにアクティブだったスパン。アクティブなスパンがなければ空です。 |
| `status` | 課題、`error` または `critical` のログ、失敗したアクションでは `error`。それ以外は空です。 |
| `attributes.logbrew.evidence` | `signal_capture` |

その後、シグナルの `span_id` は取得用のスパンを識別します。シグナルにトレースコンテキストがなかった場合、LogBrew はそのシグナルのために新しいトレース ID を作成します。このトレースは、LogBrew がシグナルを保存したことを示します。リクエストの経路は示しません。1つのトレース内の取得用のスパンを、1件のリクエストとして読まないでください。

取得用のスパンは `span_count` と `error_span_count` に数えられます。そのため、アプリケーションの処理がどれも失敗していないトレースでも、エラーログがあれば `--status error` で選ばれることがあります。結論を出す前に、各エラースパンの `operation` を読んでください。

## トレースを読む

ログ、課題、トレース一覧から得た正確なトレース ID を使います。

```bash theme={null}
logbrew read traces --project "<project_id>" --status error --since 24h --json
logbrew read trace "<trace_id>" --project "<project_id>" --json
```

`--status error` は、エラースパンを1つ以上持つトレースを選びます。`--status ok` は、エラースパンを持たないトレースを選びます。`--min-duration-ms 500` は、500ミリ秒以上かかったトレースを選びます。

まずルートスパンの所要時間を読みます。次に、最も長い子スパンとエラーのステータスを調べます。ステージング環境のトレースが本番環境についての証拠にならないように、プロジェクト、サービス、環境、リリースを常に確認してください。

1つのトレースが示すのは1回の実行で、パフォーマンスの基準値ではありません。パフォーマンスの変更を提案する前に、複数のトレースを関連するメトリクスの推移と比較してください。

### トレースの要約

`GET /api/telemetry/traces/{trace_id}/summary` は、スパンの属性を含まない要約を返します。

| フィールド | 意味 |
| - | - |
| `root_span` | 親がトレース内にないスパンのうち最も早いもの。すべてのスパンの親がトレース内にある場合は、最も早いスパン。 |
| `slowest_child_span` | 親を持つスパンのうち最も長いもの。 |
| `slowest_path` | ルートスパンから最も遅い子スパンまでの、わかっている親の連なり。 |
| `error_spans` | ステータスが `error` のスパンのうち、長いものから最大5件。 |
| `services` | 各サービスのスパン数、エラースパン数、最も長いスパンの所要時間。 |
| `duration_ms` | 最も早いスパンの開始から、最も遅いスパンの終了までの時間。 |

`root_span.parent_span_id` に値がある場合、本当のルートスパンはトレース内にありません。`root_span` をリクエストの開始として読まないでください。

### トレースを説明する

`logbrew explain trace` は、トレースの調査結果を返します。

```bash theme={null}
logbrew explain trace "<trace_id>" --json
```

| フィールド | 意味 |
| - | - |
| `analysis.status` | `errors_observed`、`latency_focus`、`no_error_observed` のいずれか。 |
| `analysis.first_error_span`、`analysis.first_error_path` | 最も早いエラースパンと、わかっている親の連なり。 |
| `analysis.bottleneck_span`、`analysis.bottleneck_path` | 親を持つスパンのうち最も長いものと、わかっている親の連なり。 |
| `correlations` | 同じトレース ID を持つ課題、ログ、アクション、メトリクス。各リストには `status` と `truncated` があります。 |
| `evidence` | 取得済み、未取得、秘匿済み、一部省略のフィールド。 |
| `next_actions` | 次に読むもの。優先度の高い順です。 |

`analysis.causality` は `evidence_only` です。この分析は根本原因を証明しません。CLI はレスポンスのバージョン3を要求します。このバージョンでは、関連する課題、アクション、メトリクスのそれぞれにも正確な `span_id` が付きます。

1つのスパンを、その親、子、サービスの境界とともに調べるには、次を実行します。

```bash theme={null}
logbrew explain span "<trace_id>" "<span_id>" --project "<project_id>" \
  --environment production --release "<release>" --json
```

`topology.parent_chain_status` は、親の連なりが完全かどうかを示します。

| 値 | 意味 |
| - | - |
| `root` | スパンに親の ID がありません。 |
| `complete` | ルートスパンまでのすべての親がトレース内にあります。 |
| `missing` | 親の ID が、トレース内にないスパンを参照しています。 |
| `cycle` | 親の ID がループしています。 |
| `truncated` | レスポンスの上限のため、連なりを完全に返せません。 |
| `unavailable` | トレースの読み取りを完了できませんでした。 |

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

すべてのイベントに、そのリクエストのトレースがあるわけではありません。トレースの状態を読んでください。

| 状態 | 意味 |
| - | - |
| `available` | 正確なトレースの証拠を読み取れます。 |
| `not_linked` | イベントにトレース ID がありません。古いイベントの一部にはトレース ID がありません。 |
| `not_found` | イベントにはトレース ID がありますが、選択した範囲で一致するトレースがありません。 |
| `unavailable` | その時点では、トレースの証拠を読み取れませんでした。 |

`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` になります。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.