この記事は英語の原文を日本語に翻訳したものです。原文: https://opentelemetry.io/docs/specs/semconv/http/http-spans/
翻訳元: open-telemetry/semantic-conventions v1.44.0(コミット e10a930)
HTTPスパンに関するセマンティック規約
ステータス: Stable(特に断りがない限り)。
この文書では、HTTPクライアントとサーバーのスパンに関するセマンティック規約を定義します。 これらは、HTTPとHTTPSの両方のスキーム、および1.1、2、SPDYなどさまざまなHTTPバージョンで使用できます。
[!IMPORTANT] この文書のv1.20.0 以前のバージョンを使っている既存のHTTP計装は、次に従うべきです。
- HTTPセマンティック規約が安定版として宣言されるまで、デフォルトで発行するHTTPまたはネットワーキング規約のバージョンを変更してはなりません(SHOULD NOT) (HTTPの安定化には、HTTP計装で併せて使われる、ネットワーキング規約の中核部分の安定化も含まれます)。 規約には、属性、メトリクス名、スパン名、計測単位などが含まれますが、これらに限定されません。
- 既存のメジャーバージョンにおいて、カテゴリー別の値をカンマ区切りで列挙するリストとして環境変数
OTEL_SEMCONV_STABILITY_OPT_INを導入すべきです(SHOULD) (例: http、databases、messaging)。値の一覧は次のとおりです。
http- 新しい安定版のHTTP・ネットワーキング規約を発行し、それまで計装が発行していた古い実験的なHTTP・ネットワーキング規約の発行を停止します。http/dup- 古い規約と安定版の規約の両方を発行し、円滑な移行を可能にします。- これらの値がいずれも指定されていない場合のデフォルトの動作は、その計装がそれまで発行していた古い実験的なHTTP・ネットワーキング規約のバージョンをそのまま発行し続けることです。
- 注記: 両方の値が指定されている場合、
http/dupはhttpよりも優先されます。- 両方の規約セットを発行し始めてから少なくとも6か月間は、既存のメジャーバージョンを(少なくともセキュリティパッチの適用という形で)維持すべきです(SHOULD)。
- 次のメジャーバージョンでは、この環境変数を削除すべきです(SHOULD)。
名前
HTTPスパンは、スパン名に関する全体的なガイドラインに従わなければなりません(MUST)。
(低カーディナリティの)target が利用可能な場合、HTTPスパン名は {method} {target} にすべきです(SHOULD)。
(低カーディナリティの){target} が利用できない場合、HTTPスパン名は {method} にすべきです(SHOULD)。
({method} と {target} のプレースホルダーの正確な定義は以下を参照してください。)
{method} は、計装に既知の元のメソッドを表す場合は {http.request.method} でなければなりません(MUST)。
それ以外の場合({http.request.method} が _OTHER に設定されている場合)、{method} は HTTP でなければなりません(MUST)。
{target} は、次のいずれかであるべきです(SHOULD)。
- HTTPサーバースパンの場合は
http.route - 有効かつ利用可能な場合、HTTPクライアントスパンの場合は
url.template()
- その他の値は、スパン開始時またはそれ以降のカスタムフックによって提供されてもかまいません(MAY)。
計装は、{target} としてURIパスをデフォルトで使用してはなりません(MUST NOT)。
ステータス
Span Statusは、HTTPステータスコードが1xx、2xx、3xxの範囲であった場合は未設定のままにしなければなりません(MUST)。
ただし、別のエラー(例えば、レスポンスボディの受信時のネットワークエラーや、最大リダイレクト数を超えた3xxコードなど)があった場合は、ステータスを Error に設定しなければなりません(MUST)。
[!NOTE]
HTTPステータスコードがエラーに分類されるかどうかは、文脈に依存します。 例えば、404「Not Found」ステータスコードは、アプリケーションがそのリソースが利用可能であることを期待していた場合はエラーを示します。 しかし、アプリケーションが単にそのリソースの存在を確認しているだけの場合はエラーではありません。
特定のリクエストについて追加のコンテキストを持つ計装は、そのコンテキストを使ってスパンステータスをより正確に設定してもかまいません(MAY)。 追加のコンテキストを持たない計装は、この節のガイドラインに従わなければなりません(MUST)。
4xx範囲のHTTPステータスコードについては、SpanKind.SERVER の場合はスパンステータスを未設定のままにしなければならず(MUST)、SpanKind.CLIENT の場合は Error に設定すべきです(SHOULD)。
5xx範囲のHTTPステータスコード、およびクライアントが解釈に失敗したその他のコードについては、スパンステータスを Error に設定すべきです(SHOULD)。
理由が http.response.status_code から推測できる場合は、スパンステータスの説明を設定しないでください。
クライアントまたはサーバーがリクエスト・レスポンスを完全に送信・受信できなかった場合、HTTPリクエストは失敗することがあります。
計装がそのようなエラーを検知した場合、スパンステータスを Error に設定すべきであり(SHOULD)、error.type 属性を設定すべきです(SHOULD)。
HTTPクライアント計装が、(コンテキストのキャンセルやアボートシグナルなどによって)呼び出し元によって意図的にリクエストがキャンセルされたことを検知できる場合、そのキャンセルはエラーとして扱うべきではありません(SHOULD NOT)。すなわち、スパンステータスは未設定のままにすべきであり(SHOULD)、error.type は設定するべきではありません(SHOULD NOT)。
ステータス: Development - スパンステータスの記録に関する一般的な考慮事項については、エラーの記録の文書を参照してください。
HTTPクライアントスパン
Status:
このスパンは、送信されるHTTPリクエストを表します。
計装においてHTTPクライアントスパンを実装する方法は2つあります。
計装は、ワイヤー越しにHTTPリクエストを送信する各試行についてHTTPスパンを作成すべきです(SHOULD)。 リクエストが再送信される場合、再送信の試行はHTTP再送信の仕様に従わなければなりません(MUST)。 この場合、計装はそれを包含する論理的なHTTPクライアントスパンを(追加で)発行すべきではありません(SHOULD NOT)。
何らかの理由で送信の試行ごとにスパンを発行できない場合(例えば、計装対象のライブラリがそれを可能にするフックを提供していない場合)、計装は、HTTPクライアントの最上位の操作についてHTTPスパンを作成してもかまいません(MAY)。 この場合、
url.fullは、リクエストの実行時に発生しうるHTTPリダイレクトより前の、元々リクエストされた絶対URLでなければなりません(MUST)。
Span name: スパン名の節を参照してください。
Span kind は CLIENT でなければなりません(MUST)。
Span status: スパンステータスの節を参照してください。
Attributes:
| Key | Stability | Requirement Level | Value Type | Description | Example Values |
|---|---|---|---|---|---|
http.request.method | Required | string | HTTPリクエストメソッド。[1] | GET; POST; HEAD | |
server.address | Required | string | 利用可能であればリバースDNSルックアップなしのサーバードメイン名。それ以外の場合はIPアドレスまたはUNIXドメインソケット名。[2] | example.com; 10.1.2.80; /tmp/my.sock | |
server.port | Required | int | サーバーのポート番号。[3] | 80; 8080; 443 | |
url.full | Required | string | RFC3986に従って記述されたネットワークリソースの絶対URL。[4] | https://www.foo.bar/search?q=OpenTelemetry#SemConv; //localhost | |
error.type | Conditionally Required リクエストがエラーで終了した場合。 | string | 操作が終了したエラーのクラスを記述します。[5] | timeout; java.net.UnknownHostException; server_certificate_invalid; 500 | |
http.request.method_original | Conditionally Required [6] | string | クライアントがリクエスト行で送信した元のHTTPメソッド。 | GeT; ACL; foo | |
http.response.status_code | Conditionally Required 送受信された場合に限る。 | int | HTTPレスポンスステータスコード。 | 200 | |
network.protocol.name | Conditionally Required [7] | string | OSIアプリケーション層またはそれに相当する非OSI層。[8] | http; spdy | |
http.request.resend_count | Recommended リクエストが再試行された場合に限る。 | int | リクエストの再送信試行の(理由を問わない、リダイレクトを含む)序数。[9] | 3 | |
network.peer.address | Recommended | string | ネットワーク接続のピアアドレス。IPアドレスまたはUNIXドメインソケット名。 | 10.1.2.80; /tmp/my.sock | |
network.peer.port | Recommended network.peer.address が設定されている場合。 | int | ネットワーク接続のピアポート番号。 | 65123 | |
network.protocol.version | Recommended | string | ネットワーク通信で使用されているプロトコルの実際のバージョン。[10] | 1.0; 1.1; 2; 3 | |
http.request.body.size | Opt-In | int | リクエストのペイロードボディのバイト数。これはヘッダーを除いて転送されたバイト数であり、多くの場合(常にではありませんが)Content-Lengthヘッダーとして存在します。転送エンコーディングを使用するリクエストの場合、これは圧縮後のサイズであるべきです。 | 3495 | |
http.request.header.<key> | Opt-In | string[] | HTTPリクエストヘッダー。<key> は正規化されたHTTPヘッダー名(小文字)で、値はそのヘッダーの値。[11] | ["application/json"]; ["1.2.3.4", "1.2.3.5"] | |
http.request.size | Opt-In | int | リクエストの総バイト数。これは、リクエスト行(HTTP/1.1)、フレーミング(HTTP/2およびHTTP/3)、ヘッダー、リクエストボディ(あれば)を含む、ワイヤー越しに送信された総バイト数であるべきです。 | 1437 | |
http.response.body.size | Opt-In | int | レスポンスのペイロードボディのバイト数。これはヘッダーを除いて転送されたバイト数であり、多くの場合(常にではありませんが)Content-Lengthヘッダーとして存在します。転送エンコーディングを使用するリクエストの場合、これは圧縮後のサイズであるべきです。 | 3495 | |
http.response.header.<key> | Opt-In | string[] | HTTPレスポンスヘッダー。<key> は正規化されたHTTPヘッダー名(小文字)で、値はそのヘッダーの値。[12] | ["application/json"]; ["abc", "def"] | |
http.response.size | Opt-In | int | レスポンスの総バイト数。これは、ステータス行(HTTP/1.1)、フレーミング(HTTP/2およびHTTP/3)、ヘッダー、レスポンスボディとトレーラー(あれば)を含む、ワイヤー越しに送信された総バイト数であるべきです。 | 1437 | |
network.transport | Opt-In | string | OSIトランスポート層またはプロセス間通信方式。[13] | tcp; udp | |
url.scheme | Opt-In | string | 使用されたプロトコルを識別するURIスキームコンポーネント。 | http; https | |
url.template | Opt-In | string | 絶対パス参照の低カーディナリティなテンプレート。[14] | /users/{id}; /users/:id; /users?id={id} | |
user_agent.original | Opt-In | string | クライアントが送信したHTTP User-Agentヘッダーの値。 | CERN-LineMode/2.15 libwww/2.17b3; Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Mobile/15E148 Safari/604.1; YourApp/1.0.0 grpc-java-okhttp/1.27.2 | |
user_agent.synthetic.type | Opt-In | string | 合成トラフィックのカテゴリー(テストやボットなど)を指定します。[15] | bot; test |
[1] http.request.method: HTTPリクエストメソッドの値は、計装に「既知」であるべきです(SHOULD)。
デフォルトでは、この規約はRFC9110に列挙されているメソッド、RFC5789で定義されたPATCHメソッド、httpbis-safe-method-w-bodyで定義されたQUERYメソッドを「既知の」メソッドとして定義します。
HTTPリクエストメソッドが計装に既知でない場合、http.request.method 属性を _OTHER に設定しなければなりません(MUST)。
HTTP計装が有効なHTTPリクエストメソッドを _OTHER に変換してしまう可能性がある場合、既知のHTTPメソッドの一覧を上書きする方法を提供しなければなりません(MUST)。
この上書きが環境変数を介して行われる場合、その環境変数は OTEL_INSTRUMENTATION_HTTP_KNOWN_METHODS という名前でなければならず(MUST)、大文字小文字を区別する既知のHTTPメソッドをカンマ区切りのリストとしてサポートしなければなりません(MUST)。
この上書きが宣言的設定を介して行われる場合、
.instrumentation/development.general.http.client や .instrumentation/development.general.http.server の下にある known_methods プロパティ(最小要素数0の、大文字小文字を区別する文字列の配列)でその一覧を設定可能にしなければなりません(MUST)。
いずれの場合も、この一覧は既知のメソッドのデフォルトの完全な上書きでなければならず(MUST)、デフォルトに追加する既知のメソッドの一覧ではありません。
HTTPメソッド名は大文字小文字を区別し、http.request.method 属性の値は既知のHTTPメソッド名に正確に一致しなければなりません(MUST)。
HTTPメソッドを大文字小文字を区別しないものとして扱う特定のWebフレームワーク向けの計装は、正規化された等価な値を設定すべきです(SHOULD)。
そのようなトレーシング計装は、http.request.method_original にも元の値を設定しなければなりません(MUST)。
[2] server.address: HTTP/1.1において、リクエストターゲットがabsolute-formで渡される場合、server.address はリクエストターゲットのホストコンポーネントと一致すべきです(SHOULD)。
その他のすべての場合、server.address はHTTP/1.1における Host ヘッダーのホストコンポーネント、またはHTTP/2およびHTTP/3における :authority 疑似ヘッダーと一致すべきです(SHOULD)。
[3] server.port: HTTP/1.1において、リクエストターゲットがabsolute-formで渡される場合、server.port はリクエストターゲットのポートコンポーネントと一致すべきです(SHOULD)。
その他のすべての場合、server.port はHTTP/1.1における Host ヘッダーのポートコンポーネント、またはHTTP/2およびHTTP/3における :authority 疑似ヘッダーと一致すべきです(SHOULD)。
[4] url.full: ネットワーク呼び出しの場合、URLは通常 scheme://host[:port][path][?query][#fragment] の形式を取ります。フラグメントはHTTPで送信されませんが、既知であれば、それでも含めるべきです(SHOULD)。
url.full は、https://username:password@www.example.com/ の形式でURL経由で渡される資格情報を含んではなりません(MUST NOT)。
そのような場合、ユーザー名とパスワードは伏字にすべきであり(SHOULD)、属性の値は https://REDACTED:REDACTED@www.example.com/ にすべきです(SHOULD)。
url.full は、利用可能な(または再構築できる)場合、絶対URLを捉えるべきです(SHOULD)。
url.full に含まれる機密情報は、計装がそれを識別できる場合、除去されるべきです(SHOULD)。
次のキーに対応するクエリ文字列の値は、デフォルトで伏字にされ、値
REDACTED に置き換えられるべきです(SHOULD)。
この一覧は今後変更される可能性があります。
クエリパラメーターのキーと機密情報の一覧との照合は、大文字小文字を区別すべきです(SHOULD)。
計装は、宣言的設定を介してこの一覧を上書きする方法を提供してもかまいません(MAY)。
その場合、
.instrumentation/development.general.sanitization.url の下にある sensitive_query_parameters プロパティ(最小要素数0の、大文字小文字を区別する文字列の配列)を使うべきです(SHOULD)。
この一覧は、デフォルトの機密なクエリパラメーターキーの完全な上書きであり、デフォルトに追加するキーの一覧ではありません。
クエリ文字列の値が伏字にされる場合でも、クエリ文字列のキーは保持されるべきです(SHOULD)。例えば
https://www.example.com/path?color=blue&sig=REDACTED のようになります。
[5] error.type: レスポンスステータスコードの送受信前にエラーでリクエストが失敗した場合、error.type は例外の型(該当する場合はその完全修飾クラス名)またはコンポーネント固有の低カーディナリティなエラー識別子に設定すべきです(SHOULD)。
レスポンスステータスコードが送受信され、かつそのステータスがHTTPスパンステータスの定義に従ってエラーを示す場合、error.type はステータスコード番号(文字列として表現)、(発生していれば)例外の型、またはコンポーネント固有のエラー識別子に設定すべきです(SHOULD)。
error.type の値は予測可能であるべきであり(SHOULD)、低カーディナリティであるべきです(SHOULD)。
計装は、報告するエラーの一覧を文書化すべきです(SHOULD)。
1つの計装ライブラリ内での error.type のカーディナリティは低くあるべきですが(SHOULD)、複数の計装ライブラリやアプリケーションからのデータを集約するテレメトリーの利用者は、追加のフィルターが適用されないクエリ時には error.type が高カーディナリティになることを想定しておくべきです。
リクエストが正常に完了した場合、計装は error.type を設定するべきではありません(SHOULD NOT)。
[6] http.request.method_original: http.request.method と異なる場合に限ります。
[7] network.protocol.name: http ではなく、かつ network.protocol.version が設定されている場合。
[8] network.protocol.name: 値は小文字に正規化すべきです(SHOULD)。
[9] http.request.resend_count: 再送信数は、(リダイレクト、認可失敗、503 Server Unavailable、ネットワークの問題、その他いずれかの理由による)クライアントによるHTTPリクエストの再送信ごとに更新すべきです(SHOULD)。
[10] network.protocol.version: プロトコルバージョンが(例えばALPNを使って)ネゴシエーションされる場合、この属性はネゴシエーションされたバージョンに設定すべきです(SHOULD)。実際のプロトコルバージョンが不明な場合、この属性は設定するべきではありません(SHOULD NOT)。
[11] http.request.header.<key>: 計装は、どのヘッダーを取得するかについて明示的な設定を要求すべきです(SHOULD)。
すべてのリクエストヘッダーを含めることはセキュリティリスクになりえます。明示的な設定によって、機密情報の漏洩を避けられます。
User-Agent ヘッダーは、既に user_agent.original 属性に取得されています。
推奨されませんが、ユーザーはそれらも取得するように計装を明示的に設定してもかまいません(MAY)。
属性の値は、HTTPライブラリがヘッダーへのアクセスを提供する方法に応じて、複数のヘッダー値からなる文字列の配列、またはカンマ結合された文字列を1つだけ含む配列のいずれかでなければなりません(MUST)。
例:
- ヘッダー
Content-Type: application/jsonは、値["application/json"]を持つhttp.request.header.content-type属性として記録すべきです(SHOULD)。 - ヘッダー
X-Forwarded-For: 1.2.3.4, 1.2.3.5は、HTTPライブラリに応じて、値["1.2.3.4", "1.2.3.5"]または["1.2.3.4, 1.2.3.5"]を持つhttp.request.header.x-forwarded-for属性として記録すべきです(SHOULD)。
[12] http.response.header.<key>: 計装は、どのヘッダーを取得するかについて明示的な設定を要求すべきです(SHOULD)。
すべてのレスポンスヘッダーを含めることはセキュリティリスクになりえます。明示的な設定によって、機密情報の漏洩を避けられます。
推奨されませんが、ユーザーはそれらを取得するように計装を明示的に設定してもかまいません(MAY)。
属性の値は、HTTPライブラリがヘッダーへのアクセスを提供する方法に応じて、複数のヘッダー値からなる文字列の配列、またはカンマ結合された文字列を1つだけ含む配列のいずれかでなければなりません(MUST)。
例:
- ヘッダー
Content-Type: application/jsonは、値["application/json"]を持つhttp.request.response.content-type属性として記録すべきです(SHOULD)。 - ヘッダー
My-custom-header: abc, defは、HTTPライブラリに応じて、値["abc", "def"]または["abc, def"]を持つhttp.response.header.my-custom-header属性として記録すべきです(SHOULD)。
[13] network.transport: HTTP/1.0、HTTP/1.1、HTTP/2 では一般に tcp です。HTTP/3 では一般に udp です。その他の実装も存在しえます。
[14] url.template: url.template は低カーディナリティでなければなりません(MUST)。通常HTTPクライアントでは利用できませんが、アプリケーションや専用のHTTP計装が知っている場合があります。
[15] user_agent.synthetic.type: この属性は、user_agent.original 属性の内容から導出されてもかまいません(MAY)。この属性を設定するコンポーネントは、合成ボットトラフィックまたはテストトラフィックとみなすものを判断する責任を負います。この属性は自己識別のために設定することもできますし、合成リクエストの結果として生成されたと検知されたテレメトリーに設定することもできます。この属性は、正規のクライアントトラフィックとボットまたはテストによって生成された合成トラフィックを区別するのに役立ちます。
次の属性は、サンプリング判断に重要となりうるため、(いずれかが提供される場合)スパン作成時点で提供すべきです(SHOULD)。
error.type には、次のよく知られた値の一覧があります。いずれかが該当する場合はその値を使用しなければならず(MUST)、それ以外の場合は独自の値を使ってもかまいません(MAY)。
| Value | Description | Stability |
|---|---|---|
_OTHER | 計装がカスタム値を定義していない場合に使用されるフォールバックのエラー値。 |
http.request.method には、次のよく知られた値の一覧があります。いずれかが該当する場合はその値を使用しなければならず(MUST)、それ以外の場合は独自の値を使ってもかまいません(MAY)。
| Value | Description | Stability |
|---|---|---|
_OTHER | 計装が事前に知らないHTTPメソッド。 | |
CONNECT | CONNECTメソッド。 | |
DELETE | DELETEメソッド。 | |
GET | GETメソッド。 | |
HEAD | HEADメソッド。 | |
OPTIONS | OPTIONSメソッド。 | |
PATCH | PATCHメソッド。 | |
POST | POSTメソッド。 | |
PUT | PUTメソッド。 | |
QUERY | QUERYメソッド。 | |
TRACE | TRACEメソッド。 |
network.transport には、次のよく知られた値の一覧があります。いずれかが該当する場合はその値を使用しなければならず(MUST)、それ以外の場合は独自の値を使ってもかまいません(MAY)。
| Value | Description | Stability |
|---|---|---|
pipe | 名前付きまたは無名のパイプ。 | |
quic | QUIC | |
tcp | TCP | |
udp | UDP | |
unix | UNIXドメインソケット |
user_agent.synthetic.type には、次のよく知られた値の一覧があります。いずれかが該当する場合はその値を使用しなければならず(MUST)、それ以外の場合は独自の値を使ってもかまいません(MAY)。
| Value | Description | Stability |
|---|---|---|
bot | ボットによるソース。 | |
test | テストによる合成ソース。 |
HTTPクライアントスパンの期間
守るべき最小限の制約がいくつかあります。
- HTTPクライアントスパンは、最初のリクエストバイトが送信される前のいずれかの時点で開始すべきです(SHOULD)。これには接続時間が含まれる場合もあれば含まれない場合もあります。
- HTTPクライアントスパンは、HTTPレスポンスヘッダーが完全に読み取られた(または読み取りに失敗した)後のいずれかの時点で終了すべきです(SHOULD)。これにはレスポンスボディの読み取りが含まれる場合もあれば含まれない場合もあります。
アプリケーションコードがHTTPレスポンスを完全に読み取らない可能性があり(かつHTTPクライアントライブラリが後で非同期にHTTPレスポンスをクリーンアップする必要がある可能性がある)場合、HTTPクライアントスパンをこのクリーンアップフェーズで終了すべきではなく(SHOULD NOT)、代わりにHTTPレスポンスヘッダーが完全に読み取られた(または読み取りに失敗した)後のいずれかの時点で終了すべきです(SHOULD)。 これによって、HTTPリクエストを行ったアプリケーションコードともはや直接結び付いていない時点で、スパンが後から非同期に終了してしまうことを避けられます。
これに関連する混乱の可能性があるため、HTTPクライアントライブラリの計装は、HTTPクライアントスパンの終了に関する自身の振る舞いを文書化すべきです(SHOULD)。
HTTPリクエストの再試行とリダイレクト
再試行とリダイレクトによって、複数の物理的なHTTPリクエストが送信されます。 HTTPクライアントライブラリが同じAPI呼び出しを満たすために複数のHTTPリクエストを送信する場合、そのリクエストは再送信されたことになります。 これは、リダイレクトの追跡、認可の課題、503 Server Unavailable、ネットワークの問題、その他いずれかの理由によって発生する可能性があります。
HTTPリクエストが再送信されるたびに、http.request.resend_count 属性を各繰り返しのスパンに追加し、リクエスト再送信試行の序数に設定すべきです(SHOULD)。
詳細については、次の例を参照してください。
HTTPサーバー
HTTPサーバーの計装がサーバー情報をどのように取得することが推奨されているかを理解するには、次の節を読んでください。
HTTPサーバーの定義
HTTPリクエストは、リバースプロキシなどの中継者を経由して、特定のHTTPアプリケーションにルーティングされることがあります。 同じドメイン名に送信されたHTTPリクエストは、ポート、パス、ヘッダー、その他のパラメーターに応じて、複数のアプリケーションによって処理されることがあります。
例えば、同じWebアプリケーションの異なるバージョンが、リバースプロキシの背後で独立したアプリケーションとして並行して動作し、リバースプロキシがリクエストパスに基づいてどちらか一方にリクエストをルーティングすることがあります。
異なるHTTPサーバーアプリケーションのインスタンスが同じ物理ホスト上で動作し、同じIPアドレスを共有しつつ、異なるTCP/UDPポートをリッスンすることがあります。
特定のアプリケーションにリクエストをルーティングするために、リバースプロキシは通常、HTTP Hostヘッダーを変更し、クライアントが提供した元の値を実際にプロキシされたサーバー名に置き換えます。
この動作はリバースプロキシの設定に依存します。
場合によっては、特定のアプリケーションにリクエストをルーティングする際に Host ヘッダーが使われず、その内容が不正なものになりやすいことがあります。
HTTPサーバーフレームワークとその計装は、リクエストが経由するHTTPインフラストラクチャや中継者について限られた知識しか持ちません。
一般的なケースでは、リクエストターゲットやヘッダーなどのHTTPリクエストのプロパティしか使って server.* 属性を設定できません。
server.address と server.port 属性の設定
HTTPサーバーの文脈において、server.address と server.port 属性は、元のホスト名とポートを捉えます。
これらは可能な限り、クライアント側とサーバー側で同じものであることを意図しています。
HTTPサーバーの計装は、server.address と server.port 属性の設定にベストエフォートで取り組むべきであり(SHOULD)、次の中で最初に該当するものを使って決定すべきです(SHOULD)。
- リバースプロキシによって
Forwarded#host、X-Forwarded-Host、または類似のヘッダーで渡される可能性のある元のホスト。 - HTTP/2またはHTTP/3の場合の
:authority疑似ヘッダー Hostヘッダー
[!NOTE]
Hostと:authorityヘッダーには、サーバーのホストとポート番号が含まれます。Forwardedヘッダーのhost識別子やX-Forwarded-Hostヘッダーについても同様です。 計装は、対応するヘッダーの値を解析してserver.addressとserver.portの両方の属性を設定すべきです(SHOULD)。
アプリケーション開発者は、SpanProcessorを使って server.* 属性の不正確な可能性のある値を上書きしてもかまいません(MAY)。また、適用可能なリソース属性を使って非公開のホスト情報を取得してもかまいません(MAY)。
シンプルなクライアント・サーバーの例

リバースプロキシを使ったクライアント・サーバーの例

HTTPサーバースパン
Status:
このスパンは、受信するHTTPリクエストを表します。
Span name: スパン名の節を参照してください。
Span kind は SERVER でなければなりません(MUST)。
Span status: スパンステータスの節を参照してください。
Attributes:
| Key | Stability | Requirement Level | Value Type | Description | Example Values |
|---|---|---|---|---|---|
http.request.method | Required | string | HTTPリクエストメソッド。[1] | GET; POST; HEAD | |
url.path | Required | string | URIパスコンポーネント。[2] | /search | |
url.scheme | Required | string | 使用されたプロトコルを識別するURIスキームコンポーネント。[3] | http; https | |
error.type | Conditionally Required リクエストがエラーで終了した場合。 | string | 操作が終了したエラーのクラスを記述します。[4] | timeout; java.net.UnknownHostException; server_certificate_invalid; 500 | |
http.request.method_original | Conditionally Required [5] | string | クライアントがリクエスト行で送信した元のHTTPメソッド。 | GeT; ACL; foo | |
http.response.status_code | Conditionally Required 送受信された場合に限る。 | int | HTTPレスポンスステータスコード。 | 200 | |
http.route | Conditionally Required 利用可能な場合に限る | string | リクエストにマッチしたルートテンプレート。これは低カーディナリティでなければならず(MUST)、すべての静的パスセグメントを含め、動的パスセグメントはプレースホルダーで表現しなければなりません(MUST)。[6] | /users/:userID?; my-controller/my-action/{id?} | |
network.protocol.name | Conditionally Required [7] | string | OSIアプリケーション層またはそれに相当する非OSI層。[8] | http; spdy | |
server.port | Conditionally Required 利用可能かつ server.address が設定されている場合。 | int | リクエストを受信したローカルHTTPサーバーのポート。[9] | 80; 8080; 443 | |
url.query | Conditionally Required 送受信された場合に限る。 | string | URIクエリコンポーネント。[10] | q=OpenTelemetry | |
client.address | Recommended | string | クライアントアドレス。利用可能であればリバースDNSルックアップなしのドメイン名。それ以外の場合はIPアドレスまたはUNIXドメインソケット名。[11] | 83.164.160.102 | |
network.peer.address | Recommended | string | ネットワーク接続のピアアドレス。IPアドレスまたはUNIXドメインソケット名。 | 10.1.2.80; /tmp/my.sock | |
network.peer.port | Recommended network.peer.address が設定されている場合。 | int | ネットワーク接続のピアポート番号。 | 65123 | |
network.protocol.version | Recommended | string | ネットワーク通信で使用されているプロトコルの実際のバージョン。[12] | 1.0; 1.1; 2; 3 | |
server.address | Recommended | string | リクエストを受信したローカルHTTPサーバーの名前。[13] | example.com; 10.1.2.80; /tmp/my.sock | |
user_agent.original | Recommended | string | クライアントが送信したHTTP User-Agentヘッダーの値。 | CERN-LineMode/2.15 libwww/2.17b3; Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Mobile/15E148 Safari/604.1; YourApp/1.0.0 grpc-java-okhttp/1.27.2 | |
client.port | Opt-In | int | client.address に取得されたクライアントのポート。[14] | 65123 | |
http.request.body.size | Opt-In | int | リクエストのペイロードボディのバイト数。これはヘッダーを除いて転送されたバイト数であり、多くの場合(常にではありませんが)Content-Lengthヘッダーとして存在します。転送エンコーディングを使用するリクエストの場合、これは圧縮後のサイズであるべきです。 | 3495 | |
http.request.header.<key> | Opt-In | string[] | HTTPリクエストヘッダー。<key> は正規化されたHTTPヘッダー名(小文字)で、値はそのヘッダーの値。[15] | ["application/json"]; ["1.2.3.4", "1.2.3.5"] | |
http.request.size | Opt-In | int | リクエストの総バイト数。これは、リクエスト行(HTTP/1.1)、フレーミング(HTTP/2およびHTTP/3)、ヘッダー、リクエストボディ(あれば)を含む、ワイヤー越しに送信された総バイト数であるべきです。 | 1437 | |
http.response.body.size | Opt-In | int | レスポンスのペイロードボディのバイト数。これはヘッダーを除いて転送されたバイト数であり、多くの場合(常にではありませんが)Content-Lengthヘッダーとして存在します。転送エンコーディングを使用するリクエストの場合、これは圧縮後のサイズであるべきです。 | 3495 | |
http.response.header.<key> | Opt-In | string[] | HTTPレスポンスヘッダー。<key> は正規化されたHTTPヘッダー名(小文字)で、値はそのヘッダーの値。[16] | ["application/json"]; ["abc", "def"] | |
http.response.size | Opt-In | int | レスポンスの総バイト数。これは、ステータス行(HTTP/1.1)、フレーミング(HTTP/2およびHTTP/3)、ヘッダー、レスポンスボディとトレーラー(あれば)を含む、ワイヤー越しに送信された総バイト数であるべきです。 | 1437 | |
network.local.address | Opt-In | string | ローカルソケットアドレス。マルチIPホストの場合に有用です。 | 10.1.2.80; /tmp/my.sock | |
network.local.port | Opt-In | int | ローカルソケットポート。マルチポートホストの場合に有用です。 | 65123 | |
network.transport | Opt-In | string | OSIトランスポート層またはプロセス間通信方式。[17] | tcp; udp | |
user_agent.synthetic.type | Opt-In | string | 合成トラフィックのカテゴリー(テストやボットなど)を指定します。[18] | bot; test |
[1] http.request.method: HTTPリクエストメソッドの値は、計装に「既知」であるべきです(SHOULD)。
デフォルトでは、この規約はRFC9110に列挙されているメソッド、RFC5789で定義されたPATCHメソッド、httpbis-safe-method-w-bodyで定義されたQUERYメソッドを「既知の」メソッドとして定義します。
HTTPリクエストメソッドが計装に既知でない場合、http.request.method 属性を _OTHER に設定しなければなりません(MUST)。
HTTP計装が有効なHTTPリクエストメソッドを _OTHER に変換してしまう可能性がある場合、既知のHTTPメソッドの一覧を上書きする方法を提供しなければなりません(MUST)。
この上書きが環境変数を介して行われる場合、その環境変数は OTEL_INSTRUMENTATION_HTTP_KNOWN_METHODS という名前でなければならず(MUST)、大文字小文字を区別する既知のHTTPメソッドをカンマ区切りのリストとしてサポートしなければなりません(MUST)。
この上書きが宣言的設定を介して行われる場合、
.instrumentation/development.general.http.client や .instrumentation/development.general.http.server の下にある known_methods プロパティ(最小要素数0の、大文字小文字を区別する文字列の配列)でその一覧を設定可能にしなければなりません(MUST)。
いずれの場合も、この一覧は既知のメソッドのデフォルトの完全な上書きでなければならず(MUST)、デフォルトに追加する既知のメソッドの一覧ではありません。
HTTPメソッド名は大文字小文字を区別し、http.request.method 属性の値は既知のHTTPメソッド名に正確に一致しなければなりません(MUST)。
HTTPメソッドを大文字小文字を区別しないものとして扱う特定のWebフレームワーク向けの計装は、正規化された等価な値を設定すべきです(SHOULD)。
そのようなトレーシング計装は、http.request.method_original にも元の値を設定しなければなりません(MUST)。
[2] url.path: url.path に含まれる機密情報は、計装がそれを識別できる場合、除去されるべきです(SHOULD)。
[3] url.scheme: 既知の場合(例えばForwarded#proto、X-Forwarded-Proto、または類似のヘッダーから)、元のクライアントリクエストのスキームです。それ以外の場合、直近のピアリクエストのスキームです。
[4] error.type: レスポンスステータスコードの送受信前にエラーでリクエストが失敗した場合、error.type は例外の型(該当する場合はその完全修飾クラス名)またはコンポーネント固有の低カーディナリティなエラー識別子に設定すべきです(SHOULD)。
レスポンスステータスコードが送受信され、かつそのステータスがHTTPスパンステータスの定義に従ってエラーを示す場合、error.type はステータスコード番号(文字列として表現)、(発生していれば)例外の型、またはコンポーネント固有のエラー識別子に設定すべきです(SHOULD)。
error.type の値は予測可能であるべきであり(SHOULD)、低カーディナリティであるべきです(SHOULD)。
計装は、報告するエラーの一覧を文書化すべきです(SHOULD)。
1つの計装ライブラリ内での error.type のカーディナリティは低くあるべきですが(SHOULD)、複数の計装ライブラリやアプリケーションからのデータを集約するテレメトリーの利用者は、追加のフィルターが適用されないクエリ時には error.type が高カーディナリティになることを想定しておくべきです。
リクエストが正常に完了した場合、計装は error.type を設定するべきではありません(SHOULD NOT)。
[5] http.request.method_original: http.request.method と異なる場合に限ります。
[6] http.route: HTTPサーバーフレームワークがこれをサポートしない場合、設定してはなりません(MUST NOT)。route属性は低カーディナリティであるべきであり、URIパスはそれに代わることができないためです。
アプリケーションルートがあれば、それを含めるべきです(SHOULD)(アプリケーションルートを参照)。
静的パスセグメントとは、固定された低カーディナリティな値を持つ、ルートテンプレートの一部です。
これには、/users/ のようなリテラル文字列や、{controller} や {action} のような、有限かつ事前定義された値の集合に制約されたプレースホルダーが含まれます。
動的パスセグメントとは、静的パスセグメントのような事前定義された一覧に制約されない、高カーディナリティになりうる値のプレースホルダーです。
計装は、対応するWebフレームワークが提供するルーティング情報を使用すべきです(SHOULD)。 最も精度の高いルーティング情報のソースを選択すべきであり(SHOULD)、カスタムのルートフォーマットをサポートしてもかまいません(MAY)。 計装は、使用しているフォーマットとルート文字列を取得するために使用しているAPIを文書化すべきです(SHOULD)。
[7] network.protocol.name: http ではなく、かつ network.protocol.version が設定されている場合。
[8] network.protocol.name: 値は小文字に正規化すべきです(SHOULD)。
[9] server.port: server.address と server.port 属性の設定を参照してください。
[10] url.query: url.query に含まれる機密情報は、計装がそれを識別できる場合、除去されるべきです(SHOULD)。
次のキーに対応するクエリ文字列の値は、デフォルトで伏字にされ、値
REDACTED に置き換えられるべきです(SHOULD)。
この一覧は今後変更される可能性があります。
クエリパラメーターのキーと機密情報の一覧との照合は、大文字小文字を区別すべきです(SHOULD)。
計装は、宣言的設定を介してこの一覧を上書きする方法を提供してもかまいません(MAY)。
その場合、.instrumentation/development.general.sanitization.url の下にある sensitive_query_parameters プロパティ(最小要素数0の、大文字小文字を区別する文字列の配列)を使うべきです(SHOULD)。
この一覧は、デフォルトの機密なクエリパラメーターキーの完全な上書きであり、デフォルトに追加するキーの一覧ではありません。
クエリ文字列の値が伏字にされる場合でも、クエリ文字列のキーは保持されるべきです(SHOULD)。例えば
q=OpenTelemetry&sig=REDACTED のようになります。
[11] client.address: 既知の場合(例えばForwarded#for、X-Forwarded-For、または類似のヘッダーから)、すべてのプロキシの背後にある元のクライアントのIPアドレスです。それ以外の場合、直近のクライアントピアのアドレスです。
[12] network.protocol.version: プロトコルバージョンが(例えばALPNを使って)ネゴシエーションされる場合、この属性はネゴシエーションされたバージョンに設定すべきです(SHOULD)。実際のプロトコルバージョンが不明な場合、この属性は設定するべきではありません(SHOULD NOT)。
[13] server.address: server.address と server.port 属性の設定を参照してください。
[14] client.port: サーバー側から観測し、かつ中継者(例えばプロキシ)を経由して通信している場合、client.port は、利用可能であれば、その中継者の背後にあるクライアントポートを表すべきです(SHOULD)。
[15] http.request.header.<key>: 計装は、どのヘッダーを取得するかについて明示的な設定を要求すべきです(SHOULD)。
すべてのリクエストヘッダーを含めることはセキュリティリスクになりえます。明示的な設定によって、機密情報の漏洩を避けられます。
User-Agent ヘッダーは、既に user_agent.original 属性に取得されています。
推奨されませんが、ユーザーはそれらも取得するように計装を明示的に設定してもかまいません(MAY)。
属性の値は、HTTPライブラリがヘッダーへのアクセスを提供する方法に応じて、複数のヘッダー値からなる文字列の配列、またはカンマ結合された文字列を1つだけ含む配列のいずれかでなければなりません(MUST)。
例:
- ヘッダー
Content-Type: application/jsonは、値["application/json"]を持つhttp.request.header.content-type属性として記録すべきです(SHOULD)。 - ヘッダー
X-Forwarded-For: 1.2.3.4, 1.2.3.5は、HTTPライブラリに応じて、値["1.2.3.4", "1.2.3.5"]または["1.2.3.4, 1.2.3.5"]を持つhttp.request.header.x-forwarded-for属性として記録すべきです(SHOULD)。
[16] http.response.header.<key>: 計装は、どのヘッダーを取得するかについて明示的な設定を要求すべきです(SHOULD)。
すべてのレスポンスヘッダーを含めることはセキュリティリスクになりえます。明示的な設定によって、機密情報の漏洩を避けられます。
推奨されませんが、ユーザーはそれらを取得するように計装を明示的に設定してもかまいません(MAY)。
属性の値は、HTTPライブラリがヘッダーへのアクセスを提供する方法に応じて、複数のヘッダー値からなる文字列の配列、またはカンマ結合された文字列を1つだけ含む配列のいずれかでなければなりません(MUST)。
例:
- ヘッダー
Content-Type: application/jsonは、値["application/json"]を持つhttp.request.response.content-type属性として記録すべきです(SHOULD)。 - ヘッダー
My-custom-header: abc, defは、HTTPライブラリに応じて、値["abc", "def"]または["abc, def"]を持つhttp.response.header.my-custom-header属性として記録すべきです(SHOULD)。
[17] network.transport: HTTP/1.0、HTTP/1.1、HTTP/2 では一般に tcp です。HTTP/3 では一般に udp です。その他の実装も存在しえます。
[18] user_agent.synthetic.type: この属性は、user_agent.original 属性の内容から導出されてもかまいません(MAY)。この属性を設定するコンポーネントは、合成ボットトラフィックまたはテストトラフィックとみなすものを判断する責任を負います。この属性は自己識別のために設定することもできますし、合成リクエストの結果として生成されたと検知されたテレメトリーに設定することもできます。この属性は、正規のクライアントトラフィックとボットまたはテストによって生成された合成トラフィックを区別するのに役立ちます。
次の属性は、サンプリング判断に重要となりうるため、(いずれかが提供される場合)スパン作成時点で提供すべきです(SHOULD)。
client.addresshttp.request.header.<key>http.request.methodserver.addressserver.porturl.pathurl.queryurl.schemeuser_agent.original
error.type には、次のよく知られた値の一覧があります。いずれかが該当する場合はその値を使用しなければならず(MUST)、それ以外の場合は独自の値を使ってもかまいません(MAY)。
| Value | Description | Stability |
|---|---|---|
_OTHER | 計装がカスタム値を定義していない場合に使用されるフォールバックのエラー値。 |
http.request.method には、次のよく知られた値の一覧があります。いずれかが該当する場合はその値を使用しなければならず(MUST)、それ以外の場合は独自の値を使ってもかまいません(MAY)。
| Value | Description | Stability |
|---|---|---|
_OTHER | 計装が事前に知らないHTTPメソッド。 | |
CONNECT | CONNECTメソッド。 | |
DELETE | DELETEメソッド。 | |
GET | GETメソッド。 | |
HEAD | HEADメソッド。 | |
OPTIONS | OPTIONSメソッド。 | |
PATCH | PATCHメソッド。 | |
POST | POSTメソッド。 | |
PUT | PUTメソッド。 | |
QUERY | QUERYメソッド。 | |
TRACE | TRACEメソッド。 |
network.transport には、次のよく知られた値の一覧があります。いずれかが該当する場合はその値を使用しなければならず(MUST)、それ以外の場合は独自の値を使ってもかまいません(MAY)。
| Value | Description | Stability |
|---|---|---|
pipe | 名前付きまたは無名のパイプ。 | |
quic | QUIC | |
tcp | TCP | |
udp | UDP | |
unix | UNIXドメインソケット |
user_agent.synthetic.type には、次のよく知られた値の一覧があります。いずれかが該当する場合はその値を使用しなければならず(MUST)、それ以外の場合は独自の値を使ってもかまいません(MAY)。
| Value | Description | Stability |
|---|---|---|
bot | ボットによるソース。 | |
test | テストによる合成ソース。 |
http.route は、既に利用可能な場合、その場合に限り、スパン作成時点で提供しなければなりません(MUST)。
スパン開始後に利用可能になった場合、計装はスパン終了前のいずれかの時点でこれを設定しなければなりません(MUST)。
例
HTTPクライアント・サーバーの例
例として、IP 192.0.2.4のホストから https://example.com:8080/webshop/articles/4?s=1&t=2 へのブラウザリクエストが発行された場合、クライアント側では次のようなスパンになります。
Span name: GET
| Attribute name | Value |
|---|---|
http.request.method | "GET" |
network.protocol.version | "1.1" |
url.full | "https://example.com:8080/webshop/articles/4?s=1&t=2" |
server.address | example.com |
server.port | 8080 |
network.peer.address | "192.0.2.5" |
network.peer.port | 8080 |
http.response.status_code | 200 |
対応するサーバースパンは、次のようになります。
Span name: GET /webshop/articles/:article_id.
| Attribute name | Value |
|---|---|
http.request.method | "GET" |
network.protocol.version | "1.1" |
url.path | "/webshop/articles/4" |
url.query | "s=1&t=2" |
server.address | "example.com" |
server.port | 8080 |
url.scheme | "https" |
http.route | "/webshop/articles/:article_id" |
http.response.status_code | 200 |
client.address | "192.0.2.4" |
network.peer.address | "192.0.2.5"(クライアントはプロキシを経由している) |
user_agent.original | "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0" |
HTTPクライアントの再試行の例
インバウンドリクエストによって開始されたトレースが存在する場合の再試行の例:
request (SERVER, trace=t1, span=s1)
|
-- GET / - 500 (CLIENT, trace=t1, span=s2)
| |
| --- server (SERVER, trace=t1, span=s3)
|
-- GET / - 500 (CLIENT, trace=t1, span=s4, http.request.resend_count=1)
| |
| --- server (SERVER, trace=t1, span=s5)
|
-- GET / - 200 (CLIENT, trace=t1, span=s6, http.request.resend_count=2)
|
--- server (SERVER, trace=t1, span=s7)
トレースが事前に開始されていない場合の再試行の例:
GET / - 500 (CLIENT, trace=t1, span=s1)
|
--- server (SERVER, trace=t1, span=s2)
GET / - 500 (CLIENT, trace=t2, span=s1, http.request.resend_count=1)
|
--- server (SERVER, trace=t2, span=s2)
GET / - 200 (CLIENT, trace=t3, span=s1, http.request.resend_count=2)
|
--- server (SERVER, trace=t3, span=s1)
HTTPクライアントの認可再試行の例
インバウンドリクエストによって開始されたトレースが存在する場合の再試行の例:
request (SERVER, trace=t1, span=s1)
|
-- GET /hello - 401 (CLIENT, trace=t1, span=s2)
| |
| --- server (SERVER, trace=t1, span=s3)
|
-- GET /hello - 200 (CLIENT, trace=t1, span=s4, http.request.resend_count=1)
|
--- server (SERVER, trace=t1, span=s5)
トレースが事前に開始されていない場合の再試行の例:
GET /hello - 401 (CLIENT, trace=t1, span=s1)
|
--- server (SERVER, trace=t1, span=s2)
GET /hello - 200 (CLIENT, trace=t2, span=s1, http.request.resend_count=1)
|
--- server (SERVER, trace=t2, span=s2)
HTTPクライアントのリダイレクトの例
インバウンドリクエストによって開始されたトレースが存在する場合のリダイレクトの例:
request (SERVER, trace=t1, span=s1)
|
-- GET / - 302 (CLIENT, trace=t1, span=s2)
| |
| --- server (SERVER, trace=t1, span=s3)
|
-- GET /hello - 200 (CLIENT, trace=t1, span=s4, http.request.resend_count=1)
|
--- server (SERVER, trace=t1, span=s5)
トレースが事前に開始されていない場合のリダイレクトの例:
GET / - 302 (CLIENT, trace=t1, span=s1)
|
--- server (SERVER, trace=t1, span=s2)
GET /hello - 200 (CLIENT, trace=t2, span=s1, http.request.resend_count=1)
|
--- server (SERVER, trace=t2, span=s2)
HTTPクライアント呼び出しの例: DNSエラー
例として、ユーザーが https://does-not-exist-123.com をリクエストした場合、クライアント側では次のようなスパンになります。
| Attribute name | Value |
|---|---|
http.request.method | "GET" |
network.protocol.version | "1.1" |
url.full | "https://does-not-exist-123.com" |
server.address | "does-not-exist-123.com" |
error.type | "java.net.UnknownHostException" |
HTTPクライアント呼び出しの例: サーバー内部エラー
例として、ユーザーが https://example.com をリクエストし、サーバーが500を返した場合、クライアント側では次のようなスパンになります。
| Attribute name | Value |
|---|---|
http.request.method | "GET" |
network.protocol.version | "1.1" |
url.full | "https://example.com" |
server.address | "example.com" |
http.response.status_code | 500 |
error.type | "500" |
HTTPサーバー呼び出しの例: レスポンスボディの送信前に接続が切断された場合
例として、ユーザーがボディ付きの POST リクエストを https://example.com:8080/uploads/4 に送信した場合、サーバー側では次のようなスパンになります。
Span name: POST /uploads/:document_id.
| Attribute name | Value |
|---|---|
http.request.method | "POST" |
url.path | "/uploads/4" |
url.scheme | "https" |
http.route | "/uploads/:document_id" |
http.response.status_code | 201 |
error.type | WebSocketDisconnect |