TraceStateの取り扱い
この記事は英語の原文を日本語に翻訳したものです。原文: https://opentelemetry.io/docs/specs/otel/trace/tracestate-handling/
翻訳元: open-telemetry/opentelemetry-specification v1.60.0(コミット 29ae8c7)
ステータス: Development
TraceContext仕様に合わせて、このセクションではRFC5234のAugmented Backus-Naur Form(ABNF)記法を使い、同文書内のDIGIT規則も含めます。
OTelエコシステムの一部であるTraceStateの値を設定する場合、それらはすべてotキーを使った単一のエントリに含めなければならず(MUST)、その値はセミコロンで区切られたキーと値のペアのリストにします。例えば以下のとおりです。
ot=p:8;r:62ot=foo:bar;k1:13
TraceContext仕様は、混在するトレーシング環境において、テナント固有の値にtenant@という接頭辞を付けることで、各「テナント」がそれぞれ独自のtracestateエントリを使えるようにする仕組みをサポートしています。OpenTelemetryはこの構文を認識しますが、マルチテナントのtracestateに対する解釈は規定していません。
このリストは、以下のように形式的に定義できます。
list = list-member *( ";" list-member )
list-member = key ":" value
リスト全体の長さは、TraceState value sectionで定義されているとおり256文字を超えてはならず(MUST NOT)、使われるキーは一意でなければなりません(MUST)。
計装ライブラリとクライアントはこのエントリを使ってはならず(MUST NOT)、代わりに自身のエントリを使わなければなりません(MUST)。
Key
キーは、OTelの関心事を記述する識別子です。単純な例としてはp、ts、s1などがあります。
キーは、以下のように形式的に定義できます。
key = lcalpha *(lcalpha / DIGIT )
lcalpha = %x61-7A ; a-z
OTelの関心事によって使われる具体的なキーは、本仕様書の一部として定義されなければならず(MUST)、したがって本仕様書自体で定義されていないキーを使うことは禁止されています。
Value
値は不透明な文字列です。最大長は規定されていませんが、キーと値のリスト全体が256文字を超えてはならない(MUST NOT)ため、短い値を使うことが推奨されます。
値は、以下のように形式的に定義できます。
value = *(chr)
chr = ucalpha / lcalpha / DIGIT / "." / "_" / "-"
ucalpha = %x41-5A ; A-Z
lcalpha = %x61-7A ; a-z
Setting values
他のOTelの関心事に属する既存の値を保持するため、値を設定する場合はTraceState内のotエントリを更新するか、そこに追加しなければなりません(MUST)。例えば、ある関心事Kがk1:13を設定したい場合は以下のようになります。
ot=p:8;r:62はot=p:8;r:62;k1:13になります。ot=p:8;k1:7;r:62はot=p:8;r:62;k1:13になります。順序を保持することは必須ではありません。
値の設定によってotエントリ全体が256文字の上限を超えてしまう場合、SDKはその操作を中止し、利用者にエラーを通知することが推奨されます。例えば以下のとおりです。
traceState, ok := SetTraceStateValue(traceState, value)
if ok {
// Successfully set the specified value, traceState was updated.
} else {
// traceState was not updated.
}
Predefined OpenTelemetry sub-keys
以下の値はOpenTelemetryによって定義されています。
Sampling threshold value th
OpenTelemetryのTraceStateサブキーthは、実効サンプリング確率を伝えるサンプリング閾値を定義します。thサブフィールドの有効な値は、1桁から14桁の小文字16進数字です。
hexdigit = DIGIT ; a-f
OpenTelemetryのTraceState thの値から閾値をデコードするには、まず値を末尾に0を追加して14桁に拡張します。次に、その14桁の値を56ビットの符号なし16進数として解釈し、拒否閾値を得ます。
OpenTelemetryは、56ビットのトレースランダム性の値を56ビットの拒否閾値と比較する形で一貫したサンプリングを定義します。ランダム性の値が拒否閾値より小さい場合、そのスパンはサンプリングされません。
閾値0は、どのスパンも拒否されないこと、つまり100%サンプリングに対応することを示します。例えば、以下のTraceStateの値は100%サンプリングのトレースを示します。
tracestate: ot=th:0
拒否閾値からサンプリング確率を計算するには、識別可能な56ビットの値の個数である2^56に等しい定数MaxAdjustedCountを定義します。サンプリング確率は以下のように定義されます。
Probability = (MaxAdjustedCount - Threshold) / MaxAdjustedCount
閾値は確率から以下のように計算できます。
Threshold = MaxAdjustedCount * (1 - Probability)
サンプリングにおいて、_調整済みカウント(adjusted count)_という用語は、サンプリングされたテレメトリー項目1つが表す実効的な項目数を指します。あるスパンの調整済みカウントは、そのサンプリング確率の逆数であり、以下のように閾値から導出できます。
AdjustedCount = MaxAdjustedCount / (MaxAdjustedCount - Threshold)
例えば、以下はOpenTelemetryのサンプリング閾値の値を含むW3C TraceStateの値です。
tracestate: ot=th:c
これは以下のように25%のサンプリング確率に対応します。
- 16進数値
cは56ビット分のc0000000000000に拡張されます。 - 拒否閾値は
0xc0000000000000 / 0x100000000000000であり、これは75%です。 - サンプリング確率は25%です。
Explicit randomness value rv
OpenTelemetryのTraceStateサブキーrvは、_明示的ランダム性値(explicit randomness value)_と呼ばれる、ランダム性の代替の源を定義します。rvの値は、正確に14桁の小文字16進数字でなければなりません(MUST)。
明示的ランダム性値は、TraceIDからランダム性を抽出する代わりに使われることを意図しており、そのためW3C Trace Context Level 2がTraceIDについて推奨するのと同じビット数を含みます。
小文字の16進数字が指定されているのは、サンプリング閾値と、(traceparentヘッダーに現れる)TraceID、あるいは(tracestateヘッダーに現れる)明示的ランダム性値との間で、直接の字句比較ができるようにするためです。
明示的ランダム性値は、変更されることなくスパンコンテキストを通じて伝搬されることを意図しています。明示的ランダム性値を使って行われたサンプリング判断がシグナル間で一貫するように、明示的ランダム性値は、いったん新しいTraceIDに関連付けられた後は、OpenTelemetryのTraceStateから消去したり変更したりすべきではありません(SHOULD NOT)。
例えば、以下はOpenTelemetryの明示的ランダム性値を含むW3C TraceStateの値です。
tracestate: ot=rv:6e6d1a75832a2f
これは、符号なし整数値として0x6e6d1a75832a2fという明示的ランダム性値に対応します。このランダム性値は、TraceIDの下位56ビットの代わりに使われることを意図しています。 この例では、56ビットの分数(すなわち0x6e6d1a75832a2f / 0x100000000000000 = 43.1%)は、56.9%から100%までの確率(すなわち拒否閾値0x6e6d1a75832a2fから0まで)で一貫した正のサンプリング判断を行うことを裏付けており、これは明示的ランダム性値を持たない、6e6d1a75832a2fで終わる16進数のTraceIDの場合と同じです。