コンテキスト伝搬
コンテキスト伝搬を使用すると、シグナル(トレース、メトリクス、およびログ)を生成された場所に関係なく相互に関連づけることができます。 トレースに限定されないものの、コンテキスト伝搬により、トレースはプロセスおよびネットワークの境界を超えて任意に分散されたサービス全体にわたってシステムに関する因果関係の情報を構築できます。
コンテキスト伝搬を理解するには、コンテキストと伝搬の2つの概念を理解する必要があります。
コンテキスト
コンテキストは、送信サービスと受信サービス、または実行ユニットが1つのシグナルを別のシグナルと関連づけるための情報を含むオブジェクトです。
サービスAがサービスBを呼び出すと、サービスAはコンテキストの一部としてトレースIDとスパンIDを含めます。 サービスBはこれらの値を使用して、同じトレースに属する新しいスパンを作成し、サービスAからのスパンを親として設定します。 これにより、サービスの境界を超えたリクエストの完全なフローを追跡できます。
伝搬
伝搬は、サービスとプロセス間でコンテキストを運ぶメカニズムです。 コンテキストオブジェクトをシリアライズまたはデシリアライズし、あるサービスから別のサービスに伝搬される関連情報を提供します。
伝搬は通常、計装ライブラリによって処理され、ユーザーからは透過的に行われます。 コンテキストを手動で伝搬する必要がある場合は、Propagators APIを使用できます。
OpenTelemetryは、いくつかの公式のプロパゲーターをメンテナンスしています。 デフォルトのプロパゲーターは、W3C TraceContext仕様で指定されたヘッダーを使用します。
例
Frontendというサービスは、POST /cart/addやGET /checkout/などのさまざまなHTTPエンドポイントを提供し、GET /productというHTTPエンドポイントを介して下流サービスであるProduct Catalogにアクセスしてユーザーがカードに追加したい商品や決済対象の一部である商品の詳細を取得します。
Frontendからのリクストのコンテキスト内でProduct Catalogサービスのアクティビティを把握するために、コンテキスト(ここではトレースIDと「親ID」としてのスパンID)はW3C TraceContext仕様で定義されているtraceparentヘッダーを使用して伝搬されます。
これはつまり、IDがヘッダーのフィールドに埋め込まれていることを意味します。
<version>-<trace-id>-<parent-id>-<trace-flags>
例
00-a0892f3577b34da6a3ce929d0e0e4736-f03067aa0ba902b7-01
トレース
前述のように、コンテキスト伝搬によりトレースはサービス全体にわたって因果関係の情報を構築できます。
この例では、traceparentヘッダーからリモートコンテキストを抽出し、ローカルコンテキストに挿入してトレースIDと親IDを設定することにより、Product CatalogサービスのHTTPエンドポイントGET /productへの2つの呼び出しをサービスFrontend内の上流の呼び出しと関連づけることができます。
これにより、Jaegerなどのバックエンドで、2つのリクエストを1つのトレースのスパンとして表示できます。
ログ
OpenTelemetry SDKは、ログをトレースと自動的に関連づけることができます。 これは、ログレコードにコンテキスト(トレースID、スパンID)を挿入できることを意味します。 これにより、ログが属するトレースとスパンのコンテキストを表示できるだけでなく、サービスまたは実行ユニットの境界を越えて共に属するログを表示することもできます。
メトリクス
メトリクスの場合、コンテキスト伝搬により、そのコンテキスト内の測定値を集約できます。
たとえば、すべてのGET /productリクエストのレスポンスタイムを確認するだけでなく、POST /cart/add > GET /productおよびGET /checkout < GET /productといった組み合わせのメトリクスも取得できます。
| 名前 | 毎秒の呼び出し回数 | 平均レスポンスタイム |
|---|---|---|
* > GET /product | 370 | 300ms |
POST /card/add > GET /product | 330 | 130ms |
GET /checkout > GET /product | 40 | 1703ms |
カスタムコンテキスト伝搬
ほとんどのユースケースでは、コンテキスト伝搬を処理する計装ライブラリまたはネイティブライブラリの計装が見つかります。 場合によっては、そのようなサポートが利用できず、自分でサポートを作成したい場合があります。 そのためには、前述のPropagators APIを活用する必要があります。
- 送信側では、コンテキストはキャリアに注入されます。 たとえば、HTTPリクエストのヘッダーに注入されます。 それ以外の場合では、リクエストのメタデータを保存できる場所を見つける必要があります。
- 受診側では、コンテキストはキャリアから抽出されます。 HTTPの場合は、ヘッダーから取得されます。 それ以外の場合は、送信側でコンテキストを保存するために選択した場所を選択します。
メタデータの専用フィールドがないプロトコルでコンテキストを伝搬することも可能ですが、受信側でデータが処理される前に抽出および削除されることを確認する必要があります。 さもなければ、未定義の動作が発生する可能性があります。
以下の言語については、カスタムコンテキスト伝搬のステップバイステップのチュートリアルがあります。
セキュリティのベストプラクティス
伝搬にはサービスの境界を超えてデータを送受信することが含まれるため、セキュリティ上の影響があります。
外部サービス
自身のサービスと外部サービス(自身で所有していない、または信頼していないサービス)とやり取りする場合、次の点を考慮してください。
- 受信コンテキスト: 外部ソースからのコンテキストを受け入れる際は注意してください。 悪意のある攻撃者は、偽造したトレースヘッダーを送信してトレーシングデータを操作したり、コンテキスト解析の脆弱性を悪用する可能性があります。 信頼できないソースからのコンテキストを無視またはサニタイズすることを検討してください。
- 送信コンテキスト: 外部サービスに伝搬する内容に注意してください 内部のトレースID、スパンID、またはバゲッジアイテムによって、内部アーキテクチャやビジネスロジックに関する機密情報が漏洩する可能性があります。 プロぱゲーターを構成して、外部またはパブリック向けのエンドポイントにコンテキストを送信しないようにすることを検討してください。
バゲージ {#baggage
バゲージを使用すると、任意のキーと値のペアを伝搬できます。 このデータはサービスの境界を超えて伝搬されるため、バゲージに機密情報(ユーザー資格情報、APIキー、またはPIIなど)を含めないでください。 ログに記録されたり、信頼できない下流サービスに送信されたりする可能性があります。
言語SDKでのサポート
OpenTelemetry APIおよびSDKの個々の言語特有の実装については、それぞれのドキュメントページでコンテキスト伝搬のsパオートに関する詳細を確認できます。
.NET、Rust、Swift言語の場合、コンテキスト伝搬に関する言語固有のドキュメントが不足しています。 これらの言語のいずれかを知っていて、協力に興味がある場合は、貢献方法を確認してください!
仕様
コンテキスト伝搬に関する詳細は、コンテキスト仕様を参照してください。
フィードバック
このページは役に立ちましたか?
Thank you. Your feedback is appreciated!
Please let us know how we can improve this page. Your feedback is appreciated!