Propagators API

この記事は英語の原文を日本語に翻訳したものです。原文: https://opentelemetry.io/docs/specs/otel/context/api-propagators/

翻訳元: open-telemetry/opentelemetry-specification v1.60.0(コミット 29ae8c7

ステータス: 特記のない限りStable

Overview

横断的関心事は、Propagatorを使って自身の状態を次のプロセスに送信します。Propagatorとは、アプリケーション間でやり取りされるメッセージに対してコンテキストデータを読み書きするために使われるオブジェクトとして定義されます。各関心事は、サポートされるPropagatorの型ごとにPropagatorの集合を作成します。

Propagatorは、それぞれの横断的関心事(トレースやBaggageなど)についてデータを注入・抽出するためにContextを活用します。

伝搬は通常、ライブラリ固有のリクエストインターセプターとPropagatorsが連携することで実装されます。インターセプターが受信・送信リクエストを検出し、それぞれPropagatorのextract操作とinject操作を使います。

Propagators APIは、計装ライブラリを書くユーザーによって活用されることが想定されています。

Propagator Types

Propagatorの型は、特定のトランスポートによって課される制約を定義し、プロセス境界を越えてインバンドのコンテキストデータを伝搬するために、あるデータ型に束縛されます。

Propagators APIは現在、1つのPropagator型を定義しています。

  • TextMapPropagatorは、文字列のキーと値の組としてキャリアへ値を注入し、キャリアから値を抽出する型です。

Carrier

キャリアとは、Propagatorが値を読み書きするために使う媒体です。それぞれの特定のPropagator型は、文字列マップやバイト配列といった、期待されるキャリアの型を定義します。

Injectで使われるキャリアはミュータブルであることが期待されます。

Operations

Propagatorは、値をキャリアに書き込み、キャリアから値を読み込むために、それぞれInject操作とExtract操作をMUST定義するものとします。それぞれのPropagator型は、特定のキャリア型をMUST定義するものとし、追加のパラメータをMAY定義してもよいものとします。

Inject

値をキャリアに注入します。例えばHTTPリクエストのヘッダーへの注入です。

必須の引数:

  • Context。Propagatorは、SpanContextBaggage、その他の横断的関心事のコンテキストといった適切な値を、まずContextからMUST取得するものとします。
  • 伝搬フィールドを保持するキャリア。例えば送信メッセージやHTTPリクエストです。

Extract

受信リクエストから値を抽出します。例えばHTTPリクエストのヘッダーからの抽出です。

キャリアから値をパースできない場合、その横断的関心事について、実装は例外をMUST NOTスローするものとし、既存の有効な値を保持するためにContextへ新しい値をMUST NOT保存するものとします。

必須の引数:

  • Context
  • 伝搬フィールドを保持するキャリア。例えば受信メッセージやHTTPリクエストです。

引数として渡されたContextから派生した新しいContextを返します。この新しいContextは抽出された値を含み、それはSpanContextBaggage、その他の横断的関心事のコンテキストになり得ます。

TextMap Propagator

TextMapPropagatorは、プロセス境界をインバンドで越えて移動するキャリアに対して、横断的関心事の値を文字列のキーと値の組として注入・抽出を行います。

伝搬されるデータのキャリアは、クライアント側(インジェクター)とサーバー側(エクストラクター)の両方で、通常はHTTPリクエストです。

互換性を高めるため、キーと値の組は、RFC 9110に準拠した有効なHTTPヘッダーフィールドを構成するUS-ASCII文字のみでMUST構成されるものとします。

GetterSetterは、それぞれ抽出と注入のために使われる任意のヘルパーコンポーネントであり、キャリアをラップする追加のインターフェース実装オブジェクトを必要とせずにその内容にアクセスできるようにするために、実行時のメモリー割り当てを避ける目的でキャリアとは別のオブジェクトとして定義されます。

GetterSetterはステートレスでなければならず(MUST)、実行時のメモリー割り当てを効果的に避けるために定数として保存できなければなりません(MUST)。

Fields

事前に定義された伝搬フィールドです。キャリアが再利用される場合、Injectを呼び出す前にここにあるフィールドを削除すべきです(should)。

フィールドは、キャリア内の形式固有のコンポーネントを識別する文字列キーとして定義されます。

例えば、キャリアが使い捨てまたは不変のリクエストオブジェクトである場合、以前に設定されたことがありえないため、フィールドをクリアする必要はありません。ミュータブルでリトライ可能なオブジェクトである場合、後続の呼び出しではまずこれらのフィールドをクリアすべきです。

これは以下のような用途で使われます。

  • gRPC Metadataのようなシステムにおいてフィールドの事前割り当てを可能にする
  • イテレーターの単一パスの走査を可能にする

TextMapPropagatorによって使われるフィールドの一覧を返します。

一部のPropagatorは、返される値に加えて、可変の名前を持つ追加のフィールドを定義する場合があることに注意してください。特定のキャリアオブジェクトに対するフィールドの完全な一覧を取得するには、Keys操作を使ってください。

TextMap Inject

値をキャリアに注入します。必須の引数は、基本のInject操作で定義されたものと同じです。

任意の引数:

  • 伝搬用のキーと値の組を設定するSetter。Propagatorは、複数の組を設定するためにこれを複数回呼び出してもよいです(MAY)。これは、キャリアへのデータの注入を助けるために言語が自由に定義できる追加の引数です。

Setter argument

Setterは、指定されたフィールドに値を設定するInjectの引数です。

Setterは、TextMapPropagatorが伝搬対象のフィールドをキャリアに設定できるようにします。

これを実装する1つの方法は、以下に説明するSetメソッドを持つSetterクラスです。

Set

伝搬対象のフィールドを、指定された値で置き換えます。

必須の引数:

  • 伝搬フィールドを保持するキャリア。例えば送信メッセージやHTTPリクエストです。
  • フィールドのキー
  • フィールドの値

使用するプロトコルが大文字・小文字を区別しない場合、実装は大文字・小文字を保持すべきです(SHOULD)(例えばContent-Typecontent-typeに変換すべきではありません)。それ以外の場合は大文字・小文字を保持しなければなりません(MUST)。

TextMap Extract

受信リクエストから値を抽出します。必須の引数は、基本のExtract操作で定義されたものと同じです。

任意の引数:

  • 取得対象の伝搬キーごとに呼び出されるGetter。これは、キャリアからのデータの抽出を助けるために言語が自由に定義できる追加の引数です。

引数として渡されたContextから派生した新しいContextを返します。

Getter argument

Getterは、指定されたフィールドから値を取得するExtractの引数です。

Getterは、TextMapPropagatorが伝搬されたフィールドをキャリアから読み取れるようにします。

これを実装する1つの方法は、以下に説明するGetKeysGetAllメソッドを持つGetterクラスです。言語によっては、代替の実装を選び、対応するメソッドをデリゲートなど他の方法で公開しても構いません。

Keys

Keys関数は、キャリア内のすべてのキーの一覧をMUST返すものとします。

必須の引数:

  • 伝搬フィールドのキャリア。例えばHTTPリクエストです。

Keys関数は、指定されたキャリア内のすべてのキーを走査するために、可変のキー名を使うPropagatorによって呼び出されることがあります。

例えば、B3 Propagation: Multiple Headersで定義されているように、X-B3-${name}というパターンに従うすべてのキーを検出するために使えます。

Get

Get関数は、指定された伝搬キーの最初の値をMUST返すものとし、キーが存在しない場合はnullを返すものとします。

必須の引数:

  • 伝搬フィールドのキャリア。例えばHTTPリクエストです。
  • フィールドのキー

Get関数は、大文字・小文字の区別の処理を担います。GetterがHTTPリクエストオブジェクトに対応することを意図している場合、Getterは大文字・小文字を区別しないものでなければなりません(MUST)。

GetAll

多くの言語実装では、GetAll関数はGetterの安定版リリースの後に追加されます。これらの言語では、Getterの実装にGetAllを含めることを要求すると、以前は正しく動作していた計装が失敗するという破壊的変更になります。言語実装は、これを認識し、後方互換性を保つ方法でGetAllを追加すべきです。例えば、Getに基づくデフォルトのGetAll実装を提供する方法や、拡張されたGetter型を作成する方法があります。

明示的に実装された場合、GetAll関数は指定された伝搬キーのすべての値をMUST返すものとします。キャリア内に現れる順序と同じ順序で返すべきです(SHOULD)。キーが存在しない場合、空のコレクションを返すべきです(SHOULD)。

必須の引数:

  • 伝搬フィールドのキャリア。例えばHTTPリクエストです。
  • フィールドのキー

GetAll関数は、大文字・小文字の区別の処理を担います。GetterがHTTPリクエストオブジェクトに対応することを意図している場合、Getterは大文字・小文字を区別しないものでなければなりません(MUST)。

Injectors and Extractors as Separate Interfaces

言語は、Propagator型を、InjectExtractメソッドを公開する単一のオブジェクトとして実装することも、責任をさらに個々のInjectorExtractorに分割することもできます。Propagatorは、個々のInjectorExtractorsを組み合わせて実装できます。

Composite Propagator

実装は、異なる横断的関心事から得られる複数のPropagatorをグループ化し、単一のエンティティとして活用できる機構をMUST提供するものとします。

複合Propagatorは、Propagatorのリストから、あるいはInjectorとExtractorのリストから構築できます。結果として得られる複合Propagatorは、指定された順序でPropagatorInjectorExtractorを呼び出します。

各複合Propagatorは、TextMapPropagatorのような特定のPropagator型を実装します。異なるPropagator型は異なるデータ型を操作する可能性が高いためです。

以下の操作を実現するための関数がMUST存在するものとします。

  • 複合Propagatorの作成
  • 複合Propagatorからの抽出
  • 複合Propagatorへの注入

Create a Composite Propagator

必須の引数:

  • Propagatorのリスト、またはInjectorExtractorのリスト

指定されたPropagatorを持つ新しい複合Propagatorを返します。

Composite Extract

必須の引数:

  • Context
  • 伝搬フィールドを保持するキャリア

TextMapPropagatorExtract実装が任意のGetter引数を受け付ける場合、以下の引数はREQUIREDであり、それ以外の場合はOPTIONALです。

  • 取得対象の伝搬キーごとに呼び出されるGetterのインスタンス

Composite Inject

必須の引数:

  • Context
  • 伝搬フィールドを保持するキャリア

TextMapPropagatorInject実装が任意のSetter引数を受け付ける場合、以下の引数はREQUIREDであり、それ以外の場合はOPTIONALです。

  • 伝搬用のキーと値の組を設定するSetter。Propagatorは、複数の組を設定するためにこれを複数回呼び出してもよいです(MAY)。

Global Propagators

OpenTelemetry APIは、サポートされるPropagatorの型ごとにpropagatorを取得する方法をMUST提供するものとします。計装ライブラリは、すべてのリモート呼び出しでコンテキストを抽出・注入するためにpropagatorを呼び出すべきです(SHOULD)。Propagatorは、言語によって様々な依存性注入の手法を使って設定されたり、グローバルなアクセサーとして利用可能になったりすることがあります(MAY)。

注: これは推奨されない方法ですが、一部の計装ライブラリは独自のコンテキスト伝搬プロトコルを使う場合や、特定のプロトコルにハードコードされている場合があります。そのような場合、計装ライブラリは、API提供のpropagatorを使わずに、コンテキストの抽出と注入のロジックをハードコードすることを選んでも構いません(MAY)。

OpenTelemetry APIは、明示的に設定されない限りno-op propagatorをMUST使用するものとします。コンテキスト伝搬は、トレース・メトリクス・ロギングなど様々なテレメトリーシグナルに対して使われる可能性があります。したがって、コンテキスト伝搬はそれぞれ独立に有効化MAYされてもよいものとします。例えば、Span exporterが未設定のままであっても、ログやメトリクスをエンリッチするためにトレースコンテキストの伝搬が設定されることがあります。

ASP.NETのようなプラットフォームは、すぐに使えるpropagatorを事前設定していることがあります。事前設定されている場合、Propagatorは、W3C Trace Context PropagatorとBaggage PropagatorBaggage APIで規定されているもの)を含む複合Propagatorにデフォルトで設定すべきです(SHOULD)。これらのプラットフォームは、事前設定されたpropagatorを無効化または上書きできるようにもMUST許容するものとします。

Get Global Propagator

このメソッドは、サポートされるPropagatorの型ごとにMUST存在するものとします。

グローバルなPropagatorを返します。通常これは複合インスタンスになります。

Set Global Propagator

このメソッドは、サポートされるPropagatorの型ごとにMUST存在するものとします。

グローバルなPropagatorインスタンスを設定します。

必須のパラメータ:

  • Propagator。通常これは複合インスタンスになります。

Propagators Distribution

OpenTelemetry organizationによってMUST保守され、OpenTelemetryのCore packagesとしてMUST配布されるべきpropagatorの公式な一覧です。

  • W3C TraceContext。OpenTelemetry APIの一部として配布されてもMAY構いません。
  • W3C Baggage。OpenTelemetry APIの一部として配布されてもMAY構いません。
  • B3

以下は、OpenTelemetryのCoreパッケージとして保守・配布されてもMAY構わない追加のpropagatorの一覧です。

  • Jaegerステータス: Deprecated。代わりにW3C TraceContextを使用してください。
  • OT Trace。OpenTracing Basic Tracersで使われる伝搬形式です。OpenTracingのエコシステムで広く採用されている形式ではないため、結果として得られるpropagatorの名前にMUST NOTOpenTracingを使用するものとします。ステータス: Deprecated。代わりにW3C TraceContextを使用してください。
  • OpenCensus BinaryFormat。OpenCensusで使われる伝搬形式であり、span contextをバイナリ形式にフォーマットする方法を記述しますが、キーは規定しません。grpc-trace-binという伝搬キーを使うOpenCensus gRPCで一般的に使われています。

AWS X-Ray trace headerプロトコルのようなベンダー固有のプロトコルを実装する追加のPropagatorは、OpenTelemetryのCoreパッケージの一部としてMUST NOT保守または配布されるものとします。

W3C Trace Context Requirements

W3C Trace Context propagatorは、W3C Trace Context Level 2で規定されているとおりにtraceparentヘッダーとtracestateヘッダーをMUSTパース・検証するものとします。W3C Trace Context propagatorは、同じヘッダーを使って有効なtraceparentの値をMUST伝搬するものとします。W3C Trace Context propagatorは、値が空の場合はtracestateヘッダーを省略してもよいものとしつつ、それ以外は有効なtracestateをMUST伝搬するものとします。

トレースコンテキストをキャリアに注入・抽出する際、SpanContextから以下のフィールドが伝搬されます。

  • TraceID(16バイト)
  • SpanID(8バイト)
  • TraceFlags(8ビット)
  • TraceState(文字列。空の場合を除く)

B3 Requirements

B3には単一ヘッダーとマルチヘッダーの2つの符号化があります。また、デバッグ用トレースフラグや、リクエストの両側でIDを共有できることなど、OpenTelemetryに直接対応しないセマンティクスも持っています。OpenTelemetryとZipkinの実装間の互換性を最大化するため、B3のコンテキスト伝搬について以下の指針が定められています。

B3 Extract

B3を抽出する際、propagatorは、

  • 単一ヘッダーとマルチヘッダーの両方の形式で符号化されたB3の抽出をMUST試みるものとします。単一ヘッダー方式はマルチヘッダー方式より優先されます。
  • デバッグ用トレースフラグを受信した場合、それをMUST保持し、後続のリクエストにMUST伝搬するものとします。さらに、OpenTelemetryの実装は、デバッグフラグが設定されている場合にサンプル済みトレースフラグをMUST設定するものとします。
  • サーバー側のspanのIDとしてX-B3-SpanIdをMUST NOT再利用するものとします。

B3 Inject

B3を注入する際、propagatorは、

  • デフォルトで単一ヘッダー形式を使ってB3をMUST注入するものとします。
  • デフォルトの注入形式をB3マルチヘッダーに変更する設定をMUST提供するものとします。
  • OpenTelemetryはリクエストの両側で同じIDを再利用することをサポートしないため、X-B3-ParentSpanIdをMUST NOT伝搬するものとします。

Fields

Fieldsは、設定された形式に対応するヘッダー名、すなわち注入操作で使われるヘッダーをMUST返すものとします。

Configuration

OptionExtract OrderInject FormatSpecification
B3 SingleSingle, MultiSingleLink
B3 MultiSingle, MultiMultiLink