トレーシングAPI

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

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

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

トレーシングAPIは、以下の主要なコンポーネントから構成されます。

  • TracerProviderはAPIのエントリーポイントです。Tracerへのアクセスを提供します。
  • TracerSpanの作成を担います。
  • Spanは、1つの操作をトレースするためのAPIです。

データ型

言語やプラットフォームによってデータの表現方法は異なりますが、本節ではこのAPIに関する汎用的な要件をいくつか定義します。

時刻

OpenTelemetryは、最大でナノ秒(ns)精度までの時刻値を扱えます。これらの値の表現方法は言語に固有です。

タイムスタンプ

タイムスタンプとは、UNIXエポックからの経過時間です。

  • 最小精度はミリ秒です。
  • 最大精度はナノ秒です。

期間

期間とは、2つのイベント間の経過時間です。

  • 最小精度はミリ秒です。
  • 最大精度はナノ秒です。

TracerProvider

TracerTracerProviderを使って取得できます。

このAPIの実装において、TracerProviderは何らかの設定を保持するステートフルなオブジェクトであることが期待されます。

通常、TracerProviderは中央の一箇所からアクセスされることが期待されます。したがって、APIはグローバルなデフォルトのTracerProviderを設定・登録およびアクセスする方法をSHOULD提供するものとします。

いかなるグローバルなTracerProviderがあるかにかかわらず、一部のアプリケーションは複数のTracerProviderインスタンスを使いたい、あるいは使わざるを得ない場合があります。例えばTracerProviderインスタンス(そしてそれに応じて、そこから取得されるTracer)ごとに異なる設定(SpanProcessorなど)を持ちたい場合や、依存性注入フレームワークを使う際に簡単だからという理由があります。したがって、TracerProviderの実装は、任意の数のTracerProviderインスタンスの作成をSHOULD許容するものとします。

TracerProviderの操作

TracerProviderは以下の関数をMUST提供するものとします。

  • Tracerの取得

Tracerの取得

このAPIは以下のパラメータをMUST受け付けるものとします。

  • name(必須): この名前は、Instrumentation Scope、例えばInstrumentation Libraryio.opentelemetry.contrib.mongodbなど)、パッケージ、モジュール、クラス名を一意に識別すべきです(SHOULD)。アプリケーションやライブラリに組み込みのOpenTelemetry計装がある場合、Instrumented libraryInstrumentation libraryは同じライブラリを指すことがあります。このシナリオでは、nameはそのライブラリまたはアプリケーション内のモジュール名やコンポーネント名を表します。無効な名前(nullまたは空文字列)が指定された場合、nullを返したり例外をスローしたりするのではなく、フォールバックとして動作するTracer実装をMUST返すものとし、そのnameプロパティはの文字列に設定すべきであり(SHOULD)、指定された値が無効であることを報告するメッセージをログに記録すべきです(SHOULD)。OpenTelemetry APIを実装するライブラリは、「名前付き」機能をサポートしない場合(例えばオブザーバビリティに関連しない実装の場合)、この名前を無視してすべての呼び出しに対してデフォルトのインスタンスを返しても構いません。アプリケーション所有者がこのライブラリによって生成されるテレメトリーを抑制するようSDKを設定している場合、TracerProviderはここでno-opのTracerを返すこともあります。
  • version(任意): そのスコープにバージョンがある場合(例えばライブラリのバージョン)、Instrumentation Scopeのバージョンを指定します。値の例: 1.0.0
  • [1.4.0以降] schema_url(任意): 発行されるテレメトリーに記録すべきSchema URLを指定します。
  • [1.13.0以降] attributes(任意): 発行されるテレメトリーに関連付けるInstrumentation Scopeの属性を指定します。

identical(同一)という用語をTracerに適用した場合、すべてのパラメータが等しいインスタンスを表します。distinct(別個)という用語をTracerに適用した場合、少なくとも1つのパラメータの値が異なるインスタンスを表します。

実装は、設定変更を反映させるために、ユーザーに同一のIDでTracerを再度取得することをMUST NOT要求するものとします。これは、古い設定での動作を許容するか、新しい設定が以前に返されたTracerにも適用されるようにすることで実現できます。

注: これは例えば、可変な設定をTracerProviderに保存し、Tracer実装オブジェクトが取得元のTracerProviderへの参照を持つことで実装できます。設定を(特定のtracerを無効化する場合のように)tracerごとに保存する必要がある場合、tracerは自身のIDでTracerProvider内のマップを検索できます。あるいは、TracerProviderがすべての返却済みTracerのレジストリを保持し、設定が変わった際にそれらの設定を能動的に更新することもできます。

コンテキストとの相互作用

本節は、Contextと相互作用するトレーシングAPI内のすべての操作を定義します。

このAPIは、Contextインスタンスと相互作用するために以下の機能をMUST提供するものとします。

  • ContextインスタンスからSpanを取り出す
  • SpanContextインスタンスと組み合わせ、新しいContextインスタンスを作成する

上記の機能が必要な理由は、APIの利用者が、トレーシングAPIの実装が使うContext Keyへアクセスすべきではない(SHOULD NOT)ためです。

言語が暗黙的に伝搬されるContextをサポートする場合(こちらを参照)、APIは以下の機能もSHOULD提供するものとします。

  • 暗黙のコンテキストから現在アクティブなspanを取得する。これは、暗黙のコンテキストを取得し、そこからSpanを取り出すことと同等です。
  • 現在アクティブなspanを新しいコンテキストへ設定し、それを暗黙のコンテキストとする。これは、現在の暗黙のコンテキストの値をSpanと組み合わせて新しいコンテキストを作成し、それを現在の暗黙のコンテキストとすることと同等です。

上記のすべての機能はコンテキストAPIのみを操作するものであり、traceモジュール上の静的メソッド、あるいはtraceモジュール内のクラスの静的メソッドとして公開してもかまいません(MAY)。この機能は、可能であればAPI内で完全に実装されるべきです(SHOULD)。

Tracer

tracerはSpanの作成を担います。

Tracerは通常、設定の責務を負うべきではないことに注意してください。これは代わりにTracerProviderの責務であるべきです。

Tracerの操作

Tracerは以下を行う関数をMUST提供するものとします。

Tracerは以下を行う関数をSHOULD提供するものとします。

Enabled

ユーザーがSpanを作成する際に計算コストの高い操作を行うことを避けられるようにするため、TracerはこのEnabled APIをSHOULD提供するものとします。

このAPIには現在必須のパラメータはありません。将来パラメータが追加される可能性があるため、APIはパラメータを追加できる形でMUST構造化されるものとします。

このAPIは言語にとってイディオマティックなブール型をMUST返すものとします。返り値がtrueの場合、指定された引数に対してTracerが有効であることを意味し、falseの場合は指定された引数に対してTracerが無効であることを意味します。

返される値は常に静的ではなく、時間とともに変化することがあります。このAPIは、計装作者が最新の応答を得るために新しいSpanを作成するたびにこのAPIを呼び出す必要があるとドキュメント化されるべきです(SHOULD)。

SpanContext

SpanContextは、分散コンテキストと一緒にシリアライズし伝搬しなければならないSpanの部分を表します。SpanContextはイミュータブルです。

OpenTelemetryのSpanContext表現は、W3C TraceContext仕様に準拠しています。これには2つの識別子(TraceIdSpanId)、共通のTraceFlags、そしてシステム固有のTraceStateの値の集合が含まれます。

TraceId 有効なトレース識別子は、少なくとも1つの非ゼロバイトを含む16バイトの配列です。

SpanId 有効なスパン識別子は、少なくとも1つの非ゼロバイトを含む8バイトの配列です。

TraceFlagsはトレースに関する詳細を含みます。TraceStateの値とは異なり、TraceFlagsはすべてのトレースに存在します。この仕様書の現バージョンは2つのフラグをサポートします。

TraceStateは、トレーシングシステム固有のトレース識別データをキーと値のペアのリストとして運びます。TraceStateにより、複数のトレーシングシステムが同一トレースに参加できます。これはW3C Trace Context仕様で完全に記述されています。TraceStateにおけるOpenTelemetry固有の値については、TraceState Handlingドキュメントを参照してください。

IsRemoteは、SpanContextが他所から受信されたものか、ローカルで生成されたものかを示すブール値です。IsRemoteを参照してください。

APIはSpanContextを作成するメソッドをMUST実装するものとします。これらのメソッドはSpanContextを作成する唯一の方法であるべきです(SHOULD)。この機能はAPI内でMUST完全に実装されるものとし、オーバーライド可能であるべきではありません(SHOULD NOT)。

TraceIdとSpanIdの取得

APIは、以下の形式でTraceIdSpanIdの取得をMUST許容するものとします。

  • Hex - 小文字の16進エンコードされたTraceId(結果は32文字の小文字16進文字列でなければなりません)またはSpanId(結果は16文字の小文字16進文字列でなければなりません)を返します。
  • Binary - TraceId(結果は16バイトの配列でなければなりません)またはSpanId(結果は8バイトの配列でなければなりません)のバイナリ表現を返します。

APIは、それらが内部でどのように保存されているかについての詳細を公開すべきではありません(SHOULD NOT)。

IsValid

SpanContextが非ゼロのTraceIDと非ゼロのSpanIDを持つ場合にtrueを返すブール値を返す、IsValidと呼ばれるAPIがMUST提供されるものとします。

IsRemote

SpanContextがリモートの親から伝搬されたものである場合にtrueを返すブール値を返す、IsRemoteと呼ばれるAPIがMUST提供されるものとします。Propagators APIを通じてSpanContextを抽出する際、IsRemoteはMUST trueを返すものとし、一方で子スパンのSpanContextについてはfalseをMUST返すものとします。

TraceState

TraceStateSpanContextの一部であり、文字列のキーと値のペアのイミュータブルなリストとして表現され、W3C Trace Context仕様によって正式に定義されています。トレーシングAPIはTraceStateに対して、少なくとも以下の操作をMUST提供するものとします。

  • 指定されたキーの値を取得する
  • 新しいキーと値のペアを追加する
  • 指定されたキーの既存の値を更新する
  • キーと値のペアを削除する

これらの操作は、W3C Trace Context仕様に記述されたルールにMUST従うものとします。すべての変更操作は、変更を適用した新しいTraceStateをMUST返すものとします。TraceStateは、常にW3C Trace Context仕様で指定されたルールに従って有効でなければなりません(MUST)。すべての変更操作は、入力パラメータをMUST検証するものとします。無効な値が渡された場合、その操作は無効なデータを含むTraceStateをMUST NOT返すものとし、一般的なエラー処理のガイドラインにMUST従うものとします。

SpanContextはイミュータブルであるため、新しいTraceStateSpanContextを更新することはできないことに注意してください。このような変更は、SpanContextの伝搬テレメトリーデータのエクスポートの直前にのみ意味を持ちます。いずれの場合も、PropagatorSpanExporterは、ワイヤーへシリアライズする前に変更済みのTraceStateのコピーを作成することがあります。

Span

Spanは、トレース内の単一の操作を表します。Spanは入れ子にしてトレースツリーを形成できます。各トレースにはルートスパンが含まれ、通常は操作全体を記述し、任意でそのサブ操作に対応する1つ以上のサブスパンを持ちます。

Spanは以下をカプセル化します。

  • スパン名
  • Spanを一意に識別するイミュータブルなSpanContext
  • SpanSpanContext、またはnullの形式による親スパン
  • SpanKind
  • 開始タイムスタンプ
  • 終了タイムスタンプ
  • Attributes
  • 他のSpanへのLinkのリスト
  • タイムスタンプ付きのEventのリスト
  • Status

スパン名は、Spanが表す作業を簡潔に識別します。例えばRPCメソッド名、関数名、より大きな計算の中のサブタスクやステージの名前などです。スパン名は、人間が読みやすい形を保ちつつ、個々のSpanインスタンスではなく(統計的に)興味深いSpanのクラスを識別する、最も一般的な文字列であるべきです(SHOULD)。つまり、“get_user"は妥当な名前ですが、“314159"がユーザーIDである"get_user/314159"は、高いカーディナリティのため良い名前ではありません。人間が読みやすいことよりも一般性がSHOULD優先されるものとします。

例えば、ある仮想的なアカウント情報を取得するエンドポイントの、想定されるスパン名を示します。

スパン名指針
get一般的すぎる
get_account/42具体的すぎる
get_accountよい。account_id=42はSpanの属性として良い形になる
get_account/{accountId}これもよい(「HTTPルート」を使っている)

Spanの開始と終了のタイムスタンプは、操作の実時間の経過を反映します。

例えば、あるspanがリクエスト・レスポンスのサイクル(HTTPやRPCなど)を表す場合、そのspanは最初のサブ操作の開始時刻に対応する開始時刻を持ち、最後のサブ操作が完了した時点の終了時刻を持つべきです。これには以下が含まれます。

  • リクエストからのデータの受信
  • データの解析(バイナリやJSON形式からなど)
  • ミドルウェアや追加の処理ロジック
  • ビジネスロジック
  • レスポンスの構築
  • レスポンスの送信

より詳細なオブザーバビリティが必要なサブ操作を表現するために、子スパン(場合によってはイベント)が作成される場合があります。子スパンは対応するサブ操作のタイミングを計測すべきであり、追加の属性を追加してもかまいません。

Spanの開始時刻は、span作成時の現在時刻にSHOULD設定されるものとします。Spanが作成された後は、その名前を変更したり、Attributeを設定したり、Eventを追加したり、Statusを設定したりできるべきです(SHOULD)。これらは、Spanの終了時刻が設定された後にMUST NOT変更されるものとします。

Spanはプロセス内で情報を伝搬するために使われることを意図していません。誤用を防ぐため、実装はSpanContext以外のSpanの属性へのアクセスをSHOULD NOT提供するものとします。

ベンダーはSpanインターフェースを実装してベンダー固有のロジックを実現してもかまいません(MAY)。しかし、代替の実装は、呼び出し元が直接Spanを作成することをMUST NOT許容するものとします。すべてのSpanTracerを介してMUST作成されるものとします。

Span作成

Tracerを使う以外に、Spanを作成するAPIはMUST NOT存在するものとします。

暗黙のContext伝搬をサポートする言語では、Spanの作成は、デフォルトで新しく作成されたSpan現在のContext内のアクティブなSpanとしてMUST NOT設定するものとしますが、この機能は追加で別の操作として提供してもかまいません(MAY)。

このAPIは以下のパラメータをMUST受け付けるものとします。

  • スパン名。これは必須パラメータです。

  • Context、または新しいSpanがルートSpanであるべきことを示す指示。APIは、デフォルトの動作として現在のContextを暗黙的に親として使うオプションを持ってもかまいません(MAY)。このAPIは、親としてSpanSpanContextをMUST NOT受け付けるものとし、完全なContextのみを受け付けるものとします。

    Spanのセマンティックな親は、コンテキストからの親スパンの決定に記述されたルールに従ってMUST決定されるものとします。

  • SpanKind。指定されない場合のデフォルトはSpanKind.Internalです。

  • Attributes。加えて、これらの属性はサンプリングの説明に記載の通り、サンプリング判断に使われることがあります。指定されない場合は空のコレクションが想定されます。

    APIのドキュメントは、後からSetAttributeを呼び出すよりもspan作成時に属性を追加することが好ましいとMUST述べるものとします。SamplerはSpan作成時に既に存在する情報のみを考慮できるためです。

  • Link - Linkの順序付きシーケンス。APIの定義を参照。

  • 開始タイムスタンプ。デフォルトは現在時刻です。この引数は、span作成時刻が既に過去のものである場合にのみSHOULD設定されるものとします。APIがSpanの論理的な開始の時点で呼び出される場合、APIユーザーはこの引数を明示的にMUST NOT設定するものとします。

各スパンは0個か1個の親スパンと、0個以上の子スパンを持ち、これらは因果関係のある操作を表します。関連するスパンの木がトレースを構成します。親を持たないスパンはルートスパンと呼ばれます。各トレースには単一のルートスパンが含まれ、これはトレース内の他のすべてのスパンの共通の祖先です。実装は、ルートスパンとしてSpanを作成するオプションをMUST提供するものとし、作成される各ルートスパンに対して新しいTraceIdをMUST生成するものとします。親を持つSpanについては、TraceIdは親と同じでなければなりません(MUST)。また、子スパンはデフォルトで親のすべてのTraceStateの値をMUST継承するものとします。

Spanは、別のプロセスで作成されたSpanの子である場合、リモートの親を持つと言われます。各propagatorのデシリアライズは、親のSpanContextに対してIsRemoteをtrueに設定しなければならず(MUST)、これによりSpan作成時に親がリモートかどうかを認識できます。

作成されたすべてのspanは、MUST終了もされるものとします。これはユーザーの責務です。ユーザーがspanを終了させ忘れた場合、API実装はメモリやその他のリソース(例えば、すべてのspanを反復する定期的な処理のためのCPU時間を含む)をリークする場合があります(MAY)。

コンテキストからの親スパンの決定

新しいSpanContextから作成される場合、そのContextには現在アクティブなインスタンスを表すSpanが含まれることがあり、これが親として使われます。ContextSpanが含まれない場合、新しく作成されるSpanはルートスパンになります。

SpanContextContextに直接アクティブとして設定することはできませんが、Spanへのラッピングによって設定できます。例えば、コンテキストの抽出を行うPropagatorがこれを必要とすることがあります。

リンクの指定

Span作成時、ユーザーは他のSpanへのリンクを記録できなければなりません(MUST)。リンクされるSpanは同一トレースのものでも、異なるトレースのものでもかまいません – linksを参照。Span作成時に追加されたLinkは、サンプリング判断のためにSamplerによって考慮されることがあります。

Spanの操作

SpanSpanContextを取得する関数とIsRecordingを除き、以下のいずれもSpanが終了した後には呼び出せません。

Get Context

Spanインターフェースは以下をMUST提供するものとします。

  • 指定されたSpanSpanContextを返すAPI。返された値は、Spanが終了した後でも使用できます。返された値は、Spanのライフタイム全体を通じてMUST同一であるものとします。これはGetContextと呼んでもかまいません(MAY)。

IsRecording

Spanは、SetAttributesAddEventSetStatusなどの関数を通じて提供されたデータが何らかの形(例えばメモリ内)で捕捉される場合に記録中(IsRecordingtrueを返す)です。Spanが記録中でない場合(IsRecordingfalseを返す)、このデータはすぐに破棄されます。データの設定や追加をさらに試みても記録されず、spanは実質的にno-opになります。

このフラグは、トレース全体がサンプリングされていない場合でもtrueになることがあります。これにより、バックエンドへ送信せずに個々のSpanに関する情報を記録・処理できます。このシナリオの例としては、SLA/SLOのレイテンシーチャートの処理・構築のためにすべての受信リクエストの記録と処理を行いつつ、そのうちの一部(サンプリングされたspan)だけをバックエンドへ送信する、といったケースが考えられます。SDK設計のサンプリングの節も参照してください。

Spanが終了した後は、それは記録中でなくなるべきであり(SHOULD)、IsRecordingは常にfalseをSHOULD返すものとします。この唯一知られている例外は、ローカルな状態を保持せず、spanの終了後にIsRecordingの値を変更できないストリーミング形式のAPI実装です。

IsRecordingはパラメータをSHOULD NOT取るものとします。

このフラグは、spanが確実に記録されない場合にSpanの属性やイベントの計算コストの高い処理を避けるために使われるべきです(SHOULD)。子spanの記録は、このフラグの値(通常はSpanContext上のTraceFlagssampledフラグに基づく)とは独立して決定されることに注意してください。

APIの利用者は、コードを計装する際にのみIsRecordingプロパティにアクセスすべきであり、コンテキストのpropagator内で使う場合を除きSampledFlagにアクセスすべきではありません。

Set Attributes

Spanは、それに関連付けられたAttributesを設定する能力をMUST持つものとします。

Spanインターフェースは以下をMUST提供するものとします。

  • 属性のプロパティが引数として渡される、単一のAttributeを設定するAPI。これはSetAttributeと呼んでもかまいません(MAY)。余分なメモリ確保を避けるため、実装によっては可能な値の型ごとに個別のAPIを提供することがあります。

Spanインターフェースは以下をMAY提供するものとします。

  • Attributesが単一のメソッド呼び出しで渡され、複数のAttributesを一度に設定するAPI。

既存の属性と同じキーで属性を設定した場合、既存の属性の値をSHOULD上書きするものとします。

OpenTelemetryプロジェクトが、規定された意味を持つ“標準属性”を文書化していることに注意してください。

SamplerはSpan作成時に既に存在する情報のみを考慮できることに注意してください。後から行われる変更(新規または変更された属性を含む)は、そのSamplerの判断を変えることはできません。

Add Events

Spanは、イベントを追加する能力をMUST持つものとします。イベントには、それがSpanに追加された瞬間の時刻が関連付けられます。

Eventは構造的に以下のプロパティによって定義されます。

  • イベントの名前
  • イベントのタイムスタンプ。イベントが追加された時刻、またはユーザーによって指定されたカスタムのタイムスタンプ
  • イベントをさらに記述する、0個以上のAttributes

Spanインターフェースは以下をMUST提供するものとします。

  • Eventのプロパティが引数として渡される、単一のEventを記録するAPI。これはAddEventと呼んでもかまいません(MAY)。このAPIは、イベントの名前、任意のAttributes、イベントが発生した時刻を指定するための任意のTimestampを、個々のパラメータとして、あるいはそれらをカプセル化したイミュータブルなオブジェクトとして、言語にとって最も適切な形で受け取ります。ユーザーがカスタムのタイムスタンプを提供しない場合、実装はこのAPIが呼び出された時刻をイベントに自動的に設定します。

イベントは、記録された順序をSHOULD保持するものとします。これは通常イベントのタイムスタンプの順序と一致しますが、カスタムのタイムスタンプを使うことでイベントが順序通りでない形で記録されることもあります。

コンシューマーは、ユーザーがイベントやspanの開始・終了に対してカスタムのタイムスタンプを提供した場合、イベントのタイムスタンプがspanの開始前や終了後になる可能性があることに注意すべきです。提供されたタイムスタンプが範囲外である場合、この仕様書は正規化を要求しません。

OpenTelemetryプロジェクトが、規定された意味を持つ“標準的なイベント名とキー”を文書化していることに注意してください。

RecordExceptionは、例外イベントを記録するためのAddEventの特殊な変種であることに注意してください。

Spanは、作成後にそれに関連付けられたLinkを追加する能力をMUST持つものとします - Linksを参照。Span作成後に追加されたLinkは、Samplerによって考慮されない場合があります。

Set Status

SpanStatusを設定します。これが使われた場合、デフォルトのSpanステータスであるUnsetを上書きします。

Statusは構造的に以下のプロパティによって定義されます。

  • StatusCode。以下に列挙する値のいずれか。
  • Statusを説明するメッセージを提供する任意のDescriptionDescriptionErrorStatusCode値とのみMUST併用されるものとします。空のDescriptionは、指定されていない場合と等価です。

注: OTLPプロトコルの定義では、Descriptionプロパティをmessageと呼んでいます。

StatusCodeは以下のいずれかの値です。

  • Unset
    • デフォルトのステータス。
  • Ok
    • 操作がアプリケーション開発者やオペレーターによって、正常に完了したと検証されたことを示します。
  • Error
    • 操作にエラーが含まれることを示します。

これらの値はOk > Error > Unsetという全順序を形成します。つまり、StatusCode=OkStatusを設定すると、それ以前あるいはそれ以降にStatusCode=ErrorStatusCode=UnsetでspanのStatusを設定しようとした試みを上書きします。より具体的なルールは以下を参照してください。

Spanインターフェースは以下をMUST提供するものとします。

  • Statusを設定するAPI。これはSetStatusとSHOULD呼ばれるものとします。このAPIは、StatusCodeと任意のDescriptionを、個々のパラメータとして、あるいはそれらをカプセル化したイミュータブルなオブジェクトとして、言語にとって最も適切な形で受け取ります。StatusCodeOkUnsetの値の場合、DescriptionはMUST無視されるものとします。

ステータスコードは、以下の状況を除いてSHOULD未設定のままとするものとします。

Unset値を設定しようとする試みはSHOULD無視されるものとします。

Instrumentation LibraryによってステータスがErrorに設定される場合、Descriptionはドキュメント化され予測可能であるべきです(SHOULD)。ステータスコードは、セマンティック規約で定義されたルールに従ってのみErrorに設定されるべきです。セマンティック規約が対象としない操作については、Instrumentation Libraryは、可能なDescriptionの値とその意味を含む、独自の規約を公開すべきです(SHOULD)。

一般に、Instrumentation Libraryは、明示的にそう設定するよう構成されていない限り、ステータスコードをOkに設定すべきではありません(SHOULD NOT)。Instrumentation Libraryは、上記のようにエラーがない限りステータスコードをUnsetのままにすべきです(SHOULD)。

アプリケーション開発者やオペレーターは、ステータスコードをOkに設定してもかまいません(MAY)。

spanのステータスがOkに設定された場合、それは最終的なものとみなされるべきであり(SHOULD)、それ以降のいかなる変更の試みも無視されるべきです(SHOULD)。

分析ツールは、Okステータスに応じて、そうでなければ生成していたであろうエラーを抑制すべきです(SHOULD)。例えば、404のような煩雑なエラーを抑制するためです。

最後の呼び出しの値のみが記録され、実装は以前の呼び出しを自由に無視できます。

UpdateName

Spanの名前を更新します。この更新を受けて、Span名に基づくいかなるサンプリングの振る舞いも実装に依存します。

SamplerはSpan作成時に既に存在する情報のみを考慮できることに注意してください。更新されたspan名を含む、後から行われる変更は、そのSamplerの判断を変えることはできません。

名前更新の代替としては、最終的なSpan名がわかった時点で、過去の明示的なタイムスタンプを指定してSpanを開始する遅延Span作成、あるいは望ましい名前を持つSpanを子Spanとして報告する、といった方法があります。

必須パラメータ:

  • 新しいスパン名Span開始時に渡された値を置き換えます。

End

このspanが記述する操作が、現時点(または任意で指定された時点)で終了したことを通知します。

実装は、Endへのその後のすべての呼び出しと、その他のいかなるSpanメソッドの呼び出しもSHOULD無視するものとします。つまり、Spanは終了することで記録中でなくなります(Tracerがイベントをストリーミングしており、Spanに関連する可変な状態を持たない場合には例外があるかもしれません)。

言語のSIGは、Pythonにおけるwithステートメントのような言語固有の機能をサポートするために、spanを終了させるEnd以外のメソッドをAPIに提供してもかまいません(MAY)。しかし、そうしたメソッドのすべてのAPI実装は、内部でEndメソッドをMUST呼び出すものとし、そうすることがドキュメント化されなければなりません(MUST)。

Endは子スパンに対していかなる影響もMUST NOT持たないものとします。それらはまだ実行中である可能性があり、後で終了できます。

Endは、それがアクティブになっているいかなるContextにおいても、そのSpanをMUST NOT非アクティブ化しないものとします。終了したspanを、それが含まれるContextを介して親として使用することは、依然として可能でなければなりません(MUST)。また、SpanをContextに入れるための仕組みはすべて、Spanが終了した後もMUST動作し続けるものとします。

パラメータ:

  • (任意)終了タイムスタンプを明示的に設定するためのタイムスタンプ。省略された場合、これは現在時刻を渡した場合と同等にMUST扱われるものとします。

この操作は、本番アプリケーションの「ホットパス」で呼び出されることを想定してください。即座にとは言わないまでも、高速に完了するよう設計する必要があります。この操作自体は、呼び出し元のスレッドでブロッキングI/OをMUST NOT実行しないものとします。使用されるロックは最小限にとどめる必要があり、可能であれば完全に排除すべきです(SHOULD)。この操作から呼び出される一部の下流のSpanProcessorやそれに続くSpanExporterは、テスト、概念実証、デバッグのために使われるものであり、それら自体が本番用途向けに設計されていない場合があります。それらは、この要件と推奨の範囲には含まれません。

Record Exception

例外の記録を助けるため、その言語が例外を使う場合、言語はSHOULD RecordExceptionメソッドを提供するものとします。これはAddEventの特殊な変種であり、ここで指定されていない事柄についてはAddEventと同じ要件が適用されます。

このメソッドのシグネチャは各言語によって決められ、必要に応じてオーバーロードしてもかまいません(MAY)。このメソッドは、exceptionsドキュメントに概説された規約に従って、例外をEventとしてMUST記録するものとします。必須の引数は、例外オブジェクトのみを超えないべきです(SHOULD)。

RecordExceptionが提供される場合、そのメソッドは追加のイベント属性を提供するための任意のパラメータをMUST受け付けるものとします(これはAddEventメソッドと同じ方法で行うべきです(SHOULD))。同じ名前を持つ属性がメソッドによって既に生成される場合、追加された属性が優先されます。

注: RecordExceptionは、追加の例外固有のパラメータを持ち、他のすべてのパラメータが(例外セマンティック規約からのデフォルト値を持つため)任意であるAddEventの変種と見なせます。

Spanのライフタイム

Spanのライフタイムは、開始と終了のタイムスタンプをSpanオブジェクトに記録するプロセスを表します。

  • 開始時刻は、Spanが作成されたときに記録されます。
  • 終了時刻は、操作が終了したときに記録される必要があります。

開始・終了時刻、およびEventのタイムスタンプは、対応するAPIが呼び出された時刻にMUST記録されるものとします。

SpanContextのSpanへのラッピング

APIは、Spanインターフェースを実装するオブジェクトでSpanContextをラップする操作をMUST提供するものとします。これは、プロセス内でのSpanの伝搬などの操作において、SpanContextSpanとして公開するために行われます。

この操作をサポートするために新しい型が必要な場合、可能であればそれを公開すべきではありません(SHOULD NOT)(例えばSpanインターフェースの型を持つ何かを返す関数のみを公開することによって)。新しい型を公開する必要がある場合、それはNonRecordingSpanとSHOULD命名されるものとします。

振る舞いは以下のように定義されます。

  • GetContextはラップされたSpanContextをMUST返すものとします。
  • IsRecordingは、イベント、属性、その他の要素が記録されていない、つまり破棄されていることを示すためfalseをMUST返すものとします。

Spanの残りの機能はno-op操作としてMUST定義されるものとします。注: これにはEndも含まれます。したがって一般的なルールの例外として、そのようなSpanを終了させることは必須ではなく(有用でもありません)。

この機能はAPI内でMUST完全に実装されるものとし、オーバーライド可能であるべきではありません(SHOULD NOT)。

SpanKind

SpanKindは、親子関係やspanリンクによって関連付けられたSpan間の関係を明確にします。SpanKindは、分析中にトレーシングシステムにとって有用な2つの独立したプロパティを記述します。

  1. spanがリモートサービスへの発信呼び出し(CLIENTおよびPRODUCERスパン)を表すか、外部から開始された受信リクエストの処理(SERVERおよびCONSUMERスパン)を表すか。
  2. Spanがリクエスト・レスポンス操作(CLIENTおよびSERVERスパン)を表すか、遅延実行(PRODUCERおよびCONSUMERスパン)を表すか。

SpanKindが意味を持つようにするため、呼び出し元は単一のSpanが2つ以上の目的を果たさないようにSHOULD配慮するものとします。例えば、サーバー側のspanは、発信するリモートプロシージャコールを記述するために使うべきではありません(SHOULD NOT)。簡単な指針として、計装はリモートの発信呼び出しに対してSpanContextを注入する前に新しいSpanを作成すべきです。

注: 機能を提供する様々なコンポーネントがどのように構築・計装されているかによっては、CLIENTスパンが同じくCLIENTスパンである子を持つことや、PRODUCERスパンがCLIENTスパンであるローカルな子を持つことがあります。

特定の技術に対するセマンティック規約は、それらが定義する各spanについて種別を文書化すべきです(SHOULD)。

例えば、データベースクライアントのセマンティック規約は、データベース呼び出しを記述するためにCLIENTのspan種別を使うことを推奨しています。データベースクライアントがサーバーとHTTP経由で通信する場合、HTTP計装(有効な場合)は、論理的なデータベースCLIENT操作の範囲内で実行される個々のHTTP呼び出しを追跡するために、入れ子になったCLIENTスパンを作成します。

以下は、SpanKindとして可能な値です。

  • SERVERは、そのspanがクライアントがレスポンスを待っている間のリモートリクエストのサーバー側処理を対象としていることを示します。

  • CLIENTは、そのspanがクライアントがレスポンスを待っているリモートサービスへのリクエストを記述していることを示します。CLIENTスパンのコンテキストが伝搬されると、CLIENTスパンは通常リモートのSERVERスパンの親になります。

  • PRODUCERは、そのspanがローカルまたはリモートの操作の開始やスケジューリングを記述していることを示します。この開始側のspanは、対応するCONSUMERスパンが開始する前であっても、それより先に終了することがよくあります。

    バッチ処理を伴うメッセージングのシナリオでは、個々のメッセージをトレースするために、メッセージごとに新しいPRODUCERスパンを作成する必要があります。

  • CONSUMERは、そのspanが、プロデューサーが結果を待たない形で開始された操作の処理を表していることを示します。

  • INTERNAL デフォルト値。リモートの親や子を持つ操作とは異なり、そのspanがアプリケーション内部の操作を表していることを示します。

これらの種別の解釈を以下にまとめます。

SpanKind呼び出しの方向コミュニケーションの形式
CLIENT発信リクエスト・レスポンス
SERVER受信リクエスト・レスポンス
PRODUCER発信遅延実行
CONSUMER受信遅延実行
INTERNAL

ユーザーは、他のSpanContextへのリンクを記録する能力をMUST持つものとします。リンクされるSpanContextは、同一トレースのものでも、異なるトレースのものでもかまいません – Links between spansを参照。

Linkは構造的に以下のプロパティによって定義されます。

  • リンク先のSpanSpanContext
  • リンクをさらに記述する、0個以上のAttributes

APIは以下をMUST提供するものとします。

  • Linkのプロパティが引数として渡される、単一のLinkを記録するAPI。これはAddLinkと呼んでもかまいません(MAY)。このAPIは、リンク先のSpanSpanContextと任意のAttributesを、個々のパラメータとして、あるいはそれらをカプセル化したイミュータブルなオブジェクトとして、言語にとって最も適切な形で受け取ります。実装は、属性の集合かTraceStateのいずれかが空でない限り、空のTraceIdSpanId(すべてゼロ)を持つSpanContextを含むリンクをSHOULD記録するものとします。

Spanインターフェースは以下をMAY提供するものとします。

  • Linkが単一のメソッド呼び出しで渡され、複数のLinkを一度に追加するAPI。

SpanはLinkが設定された順序をSHOULD保持するものとします。

APIのドキュメントは、span作成時に利用可能なコンテキストについては、後からAddLinkを呼び出すよりもspan作成時にリンクを追加することが好ましいとMUST述べるものとします。ヘッドサンプリングの判断は、span作成時に存在する情報のみを考慮できるためです。

並行性の要件

並行実行をサポートする言語について、トレーシングAPIは特定の保証と安全性を提供します。すべてのAPI関数が並行して呼び出すことに対して安全というわけではありません。

TracerProvider - すべてのメソッドは、実装がデフォルトで並行使用に対して安全である必要があるとMUSTドキュメント化されるものとします。

Tracer - すべてのメソッドは、実装がデフォルトで並行使用に対して安全である必要があるとMUSTドキュメント化されるものとします。

Span - すべてのメソッドは、実装がデフォルトで並行使用に対して安全である必要があるとMUSTドキュメント化されるものとします。

Event - Eventはイミュータブルであり、デフォルトで並行使用に対してMUST安全であるものとします。

Link - Linkはイミュータブルであり、デフォルトで並行使用に対してSHOULD安全であるものとします。

含まれるPropagator

propagatorがどのように配布されるかについては、Propagators Distributionを参照してください。

SDKが存在しない場合のAPIの振る舞い

一般に、SDKがインストールされていない場合、Trace APIは「no-op」なAPIです。これは、TracerやSpanに対する操作は副作用を持たず、何も行わないべきであることを意味します。しかし、この一般的なルールには1つ重要な例外があり、それはSpanContextの伝搬に関連するものです。APIは、(明示的に与えられたか暗黙の現在のものかにかかわらず)親Context内のSpanContextを持つ非記録のSpanをMUST返すものとします。親Context内のSpanが既に非記録である場合、新しいSpanをインスタンス化せずに直接それをSHOULD返すものとします。親ContextSpanが含まれない場合、代わりに空の非記録Spanが(すなわち、すべてゼロのSpanおよびTrace ID、空のTracestate、サンプリングされていないTraceFlagsを持つSpanContextを持つものが)MUST返されるものとします。これは、設定されたPropagatorによって提供されたSpanContextがすべての子spanへ伝搬され、最終的にInjectにも伝わりますが、新しいSpanContextは作成されないことを意味します。