From 98544399afa65fc9e39882ddb9b7ade2f5577338 Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Thu, 27 Jun 2024 16:20:07 -0700 Subject: [PATCH 01/12] Add .NET HTTP connection spans --- docs/attributes-registry/dns.md | 7 +- docs/dotnet/dotnet-connection-traces.md | 399 +++++++++++++++++++++ model/registry/dns.yaml | 5 + model/trace/dotnet/dotnet-connections.yaml | 87 +++++ 4 files changed, 495 insertions(+), 3 deletions(-) create mode 100644 docs/dotnet/dotnet-connection-traces.md create mode 100644 model/trace/dotnet/dotnet-connections.yaml diff --git a/docs/attributes-registry/dns.md b/docs/attributes-registry/dns.md index 6345d59240..f4d37f8331 100644 --- a/docs/attributes-registry/dns.md +++ b/docs/attributes-registry/dns.md @@ -10,8 +10,9 @@ This document defines the shared attributes used to report a DNS query. -| Attribute | Type | Description | Examples | Stability | -| ------------------- | ------ | --------------------------- | ------------------------------------- | ---------------------------------------------------------------- | -| `dns.question.name` | string | The name being queried. [1] | `www.example.com`; `opentelemetry.io` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| Attribute | Type | Description | Examples | Stability | +| ------------------- | -------- | -------------------------------------------- | --------------------------------------------------------- | ---------------------------------------------------------------- | +| `dns.answer` | string[] | The list of resolved IPv4 or IPv6 addresses. | `["10.0.0.1", "2001:0db8:85a3:0000:0000:8a2e:0370:7334"]` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `dns.question.name` | string | The name being queried. [1] | `www.example.com`; `opentelemetry.io` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | **[1]:** If the name field contains non-printable characters (below 32 or above 126), those characters should be represented as escaped base 10 integers (\DDD). Back slashes and quotes should be escaped. Tabs, carriage returns, and line feeds should be converted to \t, \r, and \n respectively. diff --git a/docs/dotnet/dotnet-connection-traces.md b/docs/dotnet/dotnet-connection-traces.md new file mode 100644 index 0000000000..732ca33c9c --- /dev/null +++ b/docs/dotnet/dotnet-connection-traces.md @@ -0,0 +1,399 @@ + + +# Semantic Conventions for HTTP client connection spans emitted by .NET + +**Status**: [Experimental][DocumentStatus] + +This article defines semantic conventions for HTTP client connections, DNS and TLS spans emitted by .NET. + + + +* [HTTP client connection](#http-connection) +* [HTTP connection setup](#http-connection-setup) +* [Socket connection setup](#socket-connection-setup) +* [DNS](#dns) +* [TLS](#tls) +* [Examples](#examples) + + + +## Overview + +.NET reports spans related to HTTP connection establishment and its stages starting from .NET 9. +Application developers are encouraged to enable corresponding instrumentation in development and test environments. + +Enabling connection-level details in production may result in increased telemetry consumption and reduce performance. + +While such spans represent low-level details, connection lifetime is usually measured in minutes, therefore in common case +when application is under the load and connections are established for every request, the rate of connection-related spans +is expected to be much smaller than the rate of HTTP client spans. + +## HTTP client connection + +HTTP connection span describes the lifetime of the HTTP connection. TODO - after it's created or from the initiation time? +HTTP connection duration is also reported as [`http.client.connection.duration` metric](/dotnet/dotnet-http-metrics.md#metric-httpclientconnectionduration). + +Client HTTP request spans SHOULD have links to this connection span (when it is reported). + +Span name SHOULD be `http connection {address}:{server.port}`. +The `{address}` SHOULD be `server.address` when it's available and `network.peer.address` otherwise. + +Span kind SHOULD be `CLIENT` + +Corresponding `Activity.OperationName` is `System.Net.Http.Connections.Connection`, `ActivitySource` name - `System.Net.Http.Connections`. +Span added in .NET Core 9. + + + + + + + + +| Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | +|---|---|---|---|---|---| +| [`error.type`](/docs/attributes-registry/error.md) | string | Describes a class of error the operation ended with. [1] | `timeout`; `java.net.UnknownHostException`; `server_certificate_invalid`; `500` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`network.peer.address`](/docs/attributes-registry/network.md) | string | Peer address of the network connection - IP address or Unix domain socket name. | `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`network.protocol.version`](/docs/attributes-registry/network.md) | string | The actual version of the protocol used for network communication. [2] | `1.1`; `2` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`server.address`](/docs/attributes-registry/server.md) | string | Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. [3] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`server.port`](/docs/attributes-registry/server.md) | int | Server port number. [4] | `80`; `8080`; `443` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`url.scheme`](/docs/attributes-registry/url.md) | string | The [URI scheme](https://www.rfc-editor.org/rfc/rfc3986#section-3.1) component identifying the used protocol. | `https`; `ftp`; `telnet` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | + +**[1]:** The `error.type` SHOULD be predictable, and SHOULD have low cardinality. + +When `error.type` is set to a type (e.g., an exception type), its +canonical class name identifying the type within the artifact SHOULD be used. + +Instrumentations SHOULD document the list of errors they report. + +The cardinality of `error.type` within one instrumentation library SHOULD be low. +Telemetry consumers that aggregate data from multiple instrumentation libraries and applications +should be prepared for `error.type` to have high cardinality at query time when no +additional filters are applied. + +If the operation has completed successfully, instrumentations SHOULD NOT set `error.type`. + +If a specific domain defines its own set of error identifiers (such as HTTP or gRPC status codes), +it's RECOMMENDED to: + +* Use a domain-specific attribute +* Set `error.type` to capture all errors, regardless of whether they are defined within the domain-specific set or not. + +**[2]:** If protocol version is subject to negotiation (for example using [ALPN](https://www.rfc-editor.org/rfc/rfc7301.html)), this attribute SHOULD be set to the negotiated version. If the actual protocol version is not known, this attribute SHOULD NOT be set. + +**[3]:** When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available. + +**[4]:** When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available. + + + +`error.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. + +| Value | Description | Stability | +|---|---|---| +| `_OTHER` | A fallback error value to be used when the instrumentation doesn't define a custom value. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | + + + + + + + + +## HTTP connection setup + +The span describes the establishment of the HTTP connection. It includes the time it takes +to resolve the DNS, establish the socket connection, and perform the TLS handshake. + +It's different from `dotnet.http.connection` span, which describes the lifetime of the HTTP connection. + +Client HTTP request spans SHOULD have links to this connection span (when it is reported). + +Span name SHOULD be `http connection_setup {address}:{server.port}`. +The `{address}` SHOULD be `server.address` when it's available and `network.peer.address` otherwise. + +Span kind SHOULD be `CLIENT`. + +Corresponding `Activity.OperationName` is `System.Net.Http.Connections.ConnectionSetup`, `ActivitySource` name - `System.Net.Http.Connections` TODO - should be different than connection? +Added in .NET Core 9. + + + + + + + + +| Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | +|---|---|---|---|---|---| +| [`error.type`](/docs/attributes-registry/error.md) | string | Describes a class of error the operation ended with. [1] | `timeout`; `java.net.UnknownHostException`; `server_certificate_invalid`; `500` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`network.peer.address`](/docs/attributes-registry/network.md) | string | Peer address of the network connection - IP address or Unix domain socket name. | `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`network.protocol.version`](/docs/attributes-registry/network.md) | string | The actual version of the protocol used for network communication. [2] | `1.1`; `2` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`server.address`](/docs/attributes-registry/server.md) | string | Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. [3] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`server.port`](/docs/attributes-registry/server.md) | int | Server port number. [4] | `80`; `8080`; `443` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`url.scheme`](/docs/attributes-registry/url.md) | string | The [URI scheme](https://www.rfc-editor.org/rfc/rfc3986#section-3.1) component identifying the used protocol. | `https`; `ftp`; `telnet` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | + +**[1]:** The `error.type` SHOULD be predictable, and SHOULD have low cardinality. + +When `error.type` is set to a type (e.g., an exception type), its +canonical class name identifying the type within the artifact SHOULD be used. + +Instrumentations SHOULD document the list of errors they report. + +The cardinality of `error.type` within one instrumentation library SHOULD be low. +Telemetry consumers that aggregate data from multiple instrumentation libraries and applications +should be prepared for `error.type` to have high cardinality at query time when no +additional filters are applied. + +If the operation has completed successfully, instrumentations SHOULD NOT set `error.type`. + +If a specific domain defines its own set of error identifiers (such as HTTP or gRPC status codes), +it's RECOMMENDED to: + +* Use a domain-specific attribute +* Set `error.type` to capture all errors, regardless of whether they are defined within the domain-specific set or not. + +**[2]:** If protocol version is subject to negotiation (for example using [ALPN](https://www.rfc-editor.org/rfc/rfc7301.html)), this attribute SHOULD be set to the negotiated version. If the actual protocol version is not known, this attribute SHOULD NOT be set. + +**[3]:** When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available. + +**[4]:** When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available. + + + +`error.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. + +| Value | Description | Stability | +|---|---|---| +| `_OTHER` | A fallback error value to be used when the instrumentation doesn't define a custom value. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | + + + + + + + + +## Socket connection setup + +The span describes the establishment of the socket connection. +It's different from `dotnet.http.connection_setup` span, which covers the DNS and TLS handshake duration in addition to socket connection setup. + +Span name SHOULD be `socket connection_setup {network.peer.address}:{network.peer.port}`. +Span kind SHOULD be `CLIENT`. + +Corresponding `Activity.OperationName` is `System.Net.Sockets.ConnectionSetup`, `ActivitySource` name - `System.Net.Sockets`. +Added in .NET Core 9. + + + + + + + + +| Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | +|---|---|---|---|---|---| +| [`error.type`](/docs/attributes-registry/error.md) | string | Describes a class of error the operation ended with. [1] | `timeout`; `java.net.UnknownHostException`; `server_certificate_invalid`; `500` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`network.peer.address`](/docs/attributes-registry/network.md) | string | Peer address of the network connection - IP address or Unix domain socket name. | `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`network.protocol.version`](/docs/attributes-registry/network.md) | string | The actual version of the protocol used for network communication. [2] | `1.1`; `2` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`network.transport`](/docs/attributes-registry/network.md) | string | [OSI transport layer](https://osi-model.com/transport-layer/) or [inter-process communication method](https://wikipedia.org/wiki/Inter-process_communication). [3] | `tcp`; `udp` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`network.type`](/docs/attributes-registry/network.md) | string | [OSI network layer](https://osi-model.com/network-layer/) or non-OSI equivalent. [4] | `ipv4`; `ipv6` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | + +**[1]:** The `error.type` SHOULD be predictable, and SHOULD have low cardinality. + +When `error.type` is set to a type (e.g., an exception type), its +canonical class name identifying the type within the artifact SHOULD be used. + +Instrumentations SHOULD document the list of errors they report. + +The cardinality of `error.type` within one instrumentation library SHOULD be low. +Telemetry consumers that aggregate data from multiple instrumentation libraries and applications +should be prepared for `error.type` to have high cardinality at query time when no +additional filters are applied. + +If the operation has completed successfully, instrumentations SHOULD NOT set `error.type`. + +If a specific domain defines its own set of error identifiers (such as HTTP or gRPC status codes), +it's RECOMMENDED to: + +* Use a domain-specific attribute +* Set `error.type` to capture all errors, regardless of whether they are defined within the domain-specific set or not. + +**[2]:** If protocol version is subject to negotiation (for example using [ALPN](https://www.rfc-editor.org/rfc/rfc7301.html)), this attribute SHOULD be set to the negotiated version. If the actual protocol version is not known, this attribute SHOULD NOT be set. + +**[3]:** The value SHOULD be normalized to lowercase. + +Consider always setting the transport when setting a port number, since +a port number is ambiguous without knowing the transport. For example +different processes could be listening on TCP port 12345 and UDP port 12345. + +**[4]:** The value SHOULD be normalized to lowercase. + + + +`error.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. + +| Value | Description | Stability | +|---|---|---| +| `_OTHER` | A fallback error value to be used when the instrumentation doesn't define a custom value. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | + + +`network.transport` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. + +| Value | Description | Stability | +|---|---|---| +| `pipe` | Named or anonymous pipe. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| `tcp` | TCP | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| `udp` | UDP | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| `unix` | Unix domain socket | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | + + +`network.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. + +| Value | Description | Stability | +|---|---|---| +| `ipv4` | IPv4 | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| `ipv6` | IPv6 | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | + + + + + + + + +## DNS + +The span describes DNS lookup duration and outcome. + +DNS lookup duration is also reported by [`dns.lookup.duration` metric](/docs/dotnet/dotnet-dns-metrics.md#metric-dnslookupduration). + +Span name SHOULD be `DNS {dns.question.name}`. +Span kind SHOULD be `CLIENT` + +Corresponding `Activity.OperationName` is `System.Net.NameResolution.DnsLookup`, `ActivitySource` name - `System.Net.NameResolution`. +Added in .NET Core 9 + + + + + + + + +| Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | +|---|---|---|---|---|---| +| [`dns.answer`](/docs/attributes-registry/dns.md) | string[] | The list of resolved IPv4 or IPv6 addresses. | `["10.0.0.1", "2001:0db8:85a3:0000:0000:8a2e:0370:7334"]` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`dns.question.name`](/docs/attributes-registry/dns.md) | string | The name being queried. [1] | `www.example.com`; `opentelemetry.io` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`error.type`](/docs/attributes-registry/error.md) | string | Describes a class of error the operation ended with. [2] | `timeout`; `java.net.UnknownHostException`; `server_certificate_invalid`; `500` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | + +**[1]:** If the name field contains non-printable characters (below 32 or above 126), those characters should be represented as escaped base 10 integers (\DDD). Back slashes and quotes should be escaped. Tabs, carriage returns, and line feeds should be converted to \t, \r, and \n respectively. + +**[2]:** The `error.type` SHOULD be predictable, and SHOULD have low cardinality. + +When `error.type` is set to a type (e.g., an exception type), its +canonical class name identifying the type within the artifact SHOULD be used. + +Instrumentations SHOULD document the list of errors they report. + +The cardinality of `error.type` within one instrumentation library SHOULD be low. +Telemetry consumers that aggregate data from multiple instrumentation libraries and applications +should be prepared for `error.type` to have high cardinality at query time when no +additional filters are applied. + +If the operation has completed successfully, instrumentations SHOULD NOT set `error.type`. + +If a specific domain defines its own set of error identifiers (such as HTTP or gRPC status codes), +it's RECOMMENDED to: + +* Use a domain-specific attribute +* Set `error.type` to capture all errors, regardless of whether they are defined within the domain-specific set or not. + + + +`error.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. + +| Value | Description | Stability | +|---|---|---| +| `_OTHER` | A fallback error value to be used when the instrumentation doesn't define a custom value. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | + + + + + + + + +## TLS + +The span describes TLS handshake. + +Span name SHOULD be `TLS {dns.question.name}`. // TODO - decide on TLS! +Span kind SHOULD be `CLIENT` + +Corresponding `Activity.OperationName` is `System.Net.Security.TlsHandshake`, `ActivitySource` name - `System.Net.Security`. +Added in .NET Core 9. + + + + + + + + +| Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | +|---|---|---|---|---|---| +| [`error.type`](/docs/attributes-registry/error.md) | string | Describes a class of error the operation ended with. [1] | `timeout`; `java.net.UnknownHostException`; `server_certificate_invalid`; `500` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`tls.client.server_name`](/docs/attributes-registry/tls.md) | string | Also called an SNI, this tells the server which hostname to which the client is attempting to connect to. | `opentelemetry.io` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`tls.protocol.name`](/docs/attributes-registry/tls.md) | string | Normalized lowercase protocol name parsed from original string of the negotiated [SSL/TLS protocol version](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_version.html#RETURN-VALUES) | `ssl`; `tls` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`tls.protocol.version`](/docs/attributes-registry/tls.md) | string | Numeric part of the version parsed from the original string of the negotiated [SSL/TLS protocol version](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_version.html#RETURN-VALUES) | `1.2`; `3` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | + +**[1]:** The `error.type` SHOULD be predictable, and SHOULD have low cardinality. + +When `error.type` is set to a type (e.g., an exception type), its +canonical class name identifying the type within the artifact SHOULD be used. + +Instrumentations SHOULD document the list of errors they report. + +The cardinality of `error.type` within one instrumentation library SHOULD be low. +Telemetry consumers that aggregate data from multiple instrumentation libraries and applications +should be prepared for `error.type` to have high cardinality at query time when no +additional filters are applied. + +If the operation has completed successfully, instrumentations SHOULD NOT set `error.type`. + +If a specific domain defines its own set of error identifiers (such as HTTP or gRPC status codes), +it's RECOMMENDED to: + +* Use a domain-specific attribute +* Set `error.type` to capture all errors, regardless of whether they are defined within the domain-specific set or not. + + + +`error.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. + +| Value | Description | Stability | +|---|---|---| +| `_OTHER` | A fallback error value to be used when the instrumentation doesn't define a custom value. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | + + +`tls.protocol.name` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. + +| Value | Description | Stability | +|---|---|---| +| `ssl` | ssl | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `tls` | tls | ![Experimental](https://img.shields.io/badge/-experimental-blue) | + + + + + + + + +## Examples + +[DocumentStatus]: https://opentelemetry.io/docs/specs/otel/document-status diff --git a/model/registry/dns.yaml b/model/registry/dns.yaml index d4042c4add..9b328d1075 100644 --- a/model/registry/dns.yaml +++ b/model/registry/dns.yaml @@ -16,3 +16,8 @@ groups: as escaped base 10 integers (\DDD). Back slashes and quotes should be escaped. Tabs, carriage returns, and line feeds should be converted to \t, \r, and \n respectively. + - id: answer + type: string[] + stability: experimental + brief: The list of resolved IPv4 or IPv6 addresses. + examples: ["10.0.0.1", "2001:0db8:85a3:0000:0000:8a2e:0370:7334"] diff --git a/model/trace/dotnet/dotnet-connections.yaml b/model/trace/dotnet/dotnet-connections.yaml new file mode 100644 index 0000000000..cb2eca5a2f --- /dev/null +++ b/model/trace/dotnet/dotnet-connections.yaml @@ -0,0 +1,87 @@ +groups: + - id: dotnet.http.connection + type: span + span_kind: client + brief: 'The span is emitted by .NET runtime and describes the lifetime of the HTTP connection.' + note: | + HTTP connection duration is also reported by + [`http.client.connection.duration` metric](/dotnet/dotnet-http-metrics.md#metric-httpclientconnectionduration). + + `Activity.OperationName`: `System.Net.Http.Connections.Connection` + `ActivitySource` name: `System.Net.Http.Connections` + Added in: .NET Core 9 + attributes: + - ref: network.protocol.version + - ref: network.peer.address + - ref: server.address + - ref: server.port + - ref: error.type + - ref: url.scheme + + - id: dotnet.http.connection_setup + type: span + span_kind: client + brief: > + The span is emitted by .NET runtime and describes the establishment of the HTTP connection. It includes + the time it takes to resolve the DNS, establish the socket connection, and perform the TLS handshake. + + It's different from `dotnet.http.connection` span, which describes the lifetime of the HTTP connection. + note: | + `Activity.OperationName`: `System.Net.Http.Connections.ConnectionSetup` + `ActivitySource` name: `System.Net.Http.Connections` TODO - should be different than connection? + Added in: .NET Core 9 + attributes: + - ref: network.protocol.version + - ref: network.peer.address + - ref: server.address + - ref: server.port + - ref: error.type + - ref: url.scheme + + - id: dotnet.socket.connection_setup + type: span + span_kind: client + brief: > + The span is emitted by .NET runtime and describes the establishment of the socket connection. + note: | + `Activity.OperationName`: `System.Net.Sockets.ConnectionSetup` + `ActivitySource` name: `System.Net.Sockets` + Added in: .NET Core 9 + attributes: + - ref: network.protocol.version + - ref: network.peer.address + - ref: network.transport + - ref: network.type + - ref: error.type + + - id: dotnet.dns.lookup + type: span + span_kind: client + brief: > + The span is emitted by .NET runtime and describes DNS lookup. + note: | + DNS lookup duration is also reported by + [`dns.lookup.duration` metric](/docs/dotnet/dotnet-dns-metrics.md#metric-dnslookupduration). + + `Activity.OperationName`: `System.Net.NameResolution.DnsLookup` + `ActivitySource` name: `System.Net.NameResolution` + Added in: .NET Core 9 + attributes: + - ref: dns.question.name + - ref: dns.answer + - ref: error.type + + - id: dotnet.tls.handshake + type: span + span_kind: client + brief: > + The span is emitted by .NET runtime and describes TLS handshake. + note: | + `Activity.OperationName`: `System.Net.Security.TlsHandshake` + `ActivitySource` name: `System.Net.Security` + Added in: .NET Core 9 + attributes: + - ref: tls.protocol.name + - ref: tls.protocol.version + - ref: tls.client.server_name + - ref: error.type \ No newline at end of file From 1f3e393edaeb7e04dc9ebd4bffb55e9586928664 Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Thu, 27 Jun 2024 19:57:50 -0700 Subject: [PATCH 02/12] up --- docs/dotnet/dotnet-connection-traces.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/dotnet/dotnet-connection-traces.md b/docs/dotnet/dotnet-connection-traces.md index 732ca33c9c..de725aa6e8 100644 --- a/docs/dotnet/dotnet-connection-traces.md +++ b/docs/dotnet/dotnet-connection-traces.md @@ -24,11 +24,11 @@ This article defines semantic conventions for HTTP client connections, DNS and T .NET reports spans related to HTTP connection establishment and its stages starting from .NET 9. Application developers are encouraged to enable corresponding instrumentation in development and test environments. -Enabling connection-level details in production may result in increased telemetry consumption and reduce performance. +Enabling connection-level details in production may result in increased telemetry volume and reduced performance. While such spans represent low-level details, connection lifetime is usually measured in minutes, therefore in common case -when application is under the load and connections are established for every request, the rate of connection-related spans -is expected to be much smaller than the rate of HTTP client spans. +when application is under the load and connections are not established for every request, the rate of connection-related spans +is expected to be much lower than the rate of HTTP client spans. ## HTTP client connection From e772a63a5b8dd3fce6a673d473583b01320526bb Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Tue, 2 Jul 2024 17:59:16 -0700 Subject: [PATCH 03/12] add wait-for-connection and examples --- docs/dotnet/dotnet-connection-traces.md | 177 ++++++++++++++++----- model/trace/dotnet/dotnet-connections.yaml | 23 +-- 2 files changed, 155 insertions(+), 45 deletions(-) diff --git a/docs/dotnet/dotnet-connection-traces.md b/docs/dotnet/dotnet-connection-traces.md index de725aa6e8..47b84ecff6 100644 --- a/docs/dotnet/dotnet-connection-traces.md +++ b/docs/dotnet/dotnet-connection-traces.md @@ -2,50 +2,62 @@ linkTitle: HTTP client and server ---> -# Semantic Conventions for HTTP client connection spans emitted by .NET +# Semantic Conventions for HTTP client spans emitted by .NET **Status**: [Experimental][DocumentStatus] -This article defines semantic conventions for HTTP client connections, DNS and TLS spans emitted by .NET. +This article defines semantic conventions for HTTP client, DNS and TLS spans emitted by .NET. -* [HTTP client connection](#http-connection) -* [HTTP connection setup](#http-connection-setup) -* [Socket connection setup](#socket-connection-setup) -* [DNS](#dns) -* [TLS](#tls) -* [Examples](#examples) +- [HTTP Request: wait for connection](#http-request-wait-for-connection) +- [HTTP connection setup](#http-connection-setup) +- [Socket connection setup](#socket-connection-setup) +- [DNS](#dns) +- [TLS](#tls) +- [Examples](#examples) + - [HTTP request was performed on a connection that was immediately available](#http-request-was-performed-on-a-connection-that-was-immediately-available) + - [HTTP request that has to wait for existing connection to become available](#http-request-that-has-to-wait-for-existing-connection-to-become-available) + - [HTTP request has to wait for connection setup](#http-request-has-to-wait-for-connection-setup) + - [HTTP request has to wait for connection setup and other requests on that connection to complete](#http-request-has-to-wait-for-connection-setup-and-other-requests-on-that-connection-to-complete) -## Overview +.NET `HttpClient` reports HTTP client spans according to [HTTP Semantic Conventions](/docs/http/http-spans.md#http-client). -.NET reports spans related to HTTP connection establishment and its stages starting from .NET 9. -Application developers are encouraged to enable corresponding instrumentation in development and test environments. +TODO: we might need to describe some .NET specifics. Leaving it out for now. -Enabling connection-level details in production may result in increased telemetry volume and reduced performance. +In addition to HTTP request spans, `HttpClient` reports spans describing HTTP connection establishment and its stages. While such spans represent low-level details, connection lifetime is usually measured in minutes, therefore in common case -when application is under the load and connections are not established for every request, the rate of connection-related spans -is expected to be much lower than the rate of HTTP client spans. +when application is under the load, the rate of connection-related spans is expected to be much lower than the rate of HTTP client spans. -## HTTP client connection +Application developers are encouraged to enable corresponding instrumentation in development or test environments. Using connection-level +instrumentation in production should be done with caution as it increases the volume of reported telemetry and has performance overhead that +depends on the application. -HTTP connection span describes the lifetime of the HTTP connection. TODO - after it's created or from the initiation time? -HTTP connection duration is also reported as [`http.client.connection.duration` metric](/dotnet/dotnet-http-metrics.md#metric-httpclientconnectionduration). +## HTTP Request: wait for connection -Client HTTP request spans SHOULD have links to this connection span (when it is reported). +The span describes the time it takes for the HTTP request to obtain a connection from the connection pool. +The span is reported only if there is no connection that's readily available. It's reported as a child of HTTP client span. -Span name SHOULD be `http connection {address}:{server.port}`. -The `{address}` SHOULD be `server.address` when it's available and `network.peer.address` otherwise. +The span ends when the connection is obtained - it could happen when an existing connection becomes available or once +a new connection is established, so the time wait-for-connection span tracks is different than one describing [*HTTP connection setup*](#http-connection-setup). -Span kind SHOULD be `CLIENT` +If a new connection was created to serve the request and the corresponding [*HTTP connection setup*](#http-connection-setup) was reported, the instrumentation adds the +link to the *HTTP connection setup* on the *Wait for connection* span. + +Span name SHOULD be `wait_for_connection {server.address}:{server.port}`. -Corresponding `Activity.OperationName` is `System.Net.Http.Connections.Connection`, `ActivitySource` name - `System.Net.Http.Connections`. +Span kind SHOULD be `INTERNAL` + +Corresponding `Activity.OperationName` is `System.Net.Http.TODO.`, `ActivitySource` name - `System.Net.Http.TODO`. Span added in .NET Core 9. - +The time it takes to get a connection from the pool is also reported by the +[`http.client.request.time_in_queue` metric](/docs/dotnet/dotnet-http-metrics.md#metric-httpclientrequesttime_in_queue). + + @@ -54,11 +66,11 @@ Span added in .NET Core 9. | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| -| [`error.type`](/docs/attributes-registry/error.md) | string | Describes a class of error the operation ended with. [1] | `timeout`; `java.net.UnknownHostException`; `server_certificate_invalid`; `500` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`network.peer.address`](/docs/attributes-registry/network.md) | string | Peer address of the network connection - IP address or Unix domain socket name. | `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`network.protocol.version`](/docs/attributes-registry/network.md) | string | The actual version of the protocol used for network communication. [2] | `1.1`; `2` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`server.address`](/docs/attributes-registry/server.md) | string | Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. [3] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`server.port`](/docs/attributes-registry/server.md) | int | Server port number. [4] | `80`; `8080`; `443` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`error.type`](/docs/attributes-registry/error.md) | string | Describes a class of error the operation ended with. [1] | `System.OperationCanceledException` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`http.request.method`](/docs/attributes-registry/http.md) | string | HTTP request method. [2] | `GET`; `POST`; `HEAD` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`network.protocol.version`](/docs/attributes-registry/network.md) | string | The actual version of the protocol used for network communication. [3] | `1.1`; `2` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`server.address`](/docs/attributes-registry/server.md) | string | Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. [4] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`server.port`](/docs/attributes-registry/server.md) | int | Server port number. [5] | `80`; `8080`; `443` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`url.scheme`](/docs/attributes-registry/url.md) | string | The [URI scheme](https://www.rfc-editor.org/rfc/rfc3986#section-3.1) component identifying the used protocol. | `https`; `ftp`; `telnet` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | **[1]:** The `error.type` SHOULD be predictable, and SHOULD have low cardinality. @@ -81,11 +93,26 @@ it's RECOMMENDED to: * Use a domain-specific attribute * Set `error.type` to capture all errors, regardless of whether they are defined within the domain-specific set or not. -**[2]:** If protocol version is subject to negotiation (for example using [ALPN](https://www.rfc-editor.org/rfc/rfc7301.html)), this attribute SHOULD be set to the negotiated version. If the actual protocol version is not known, this attribute SHOULD NOT be set. +**[2]:** HTTP request method value SHOULD be "known" to the instrumentation. +By default, this convention defines "known" methods as the ones listed in [RFC9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-methods) +and the PATCH method defined in [RFC5789](https://www.rfc-editor.org/rfc/rfc5789.html). -**[3]:** When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available. +If the HTTP request method is not known to instrumentation, it MUST set the `http.request.method` attribute to `_OTHER`. -**[4]:** When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available. +If the HTTP instrumentation could end up converting valid HTTP request methods to `_OTHER`, then it MUST provide a way to override +the list of known HTTP methods. If this override is done via environment variable, then the environment variable MUST be named +OTEL_INSTRUMENTATION_HTTP_KNOWN_METHODS and support a comma-separated list of case-sensitive known HTTP methods +(this list MUST be a full override of the default known method, it is not a list of known methods in addition to the defaults). + +HTTP method names are case-sensitive and `http.request.method` attribute value MUST match a known HTTP method name exactly. +Instrumentations for specific web frameworks that consider HTTP methods to be case insensitive, SHOULD populate a canonical equivalent. +Tracing instrumentations that do so, MUST also set `http.request.method_original` to the original value. + +**[3]:** If protocol version is subject to negotiation (for example using [ALPN](https://www.rfc-editor.org/rfc/rfc7301.html)), this attribute SHOULD be set to the negotiated version. If the actual protocol version is not known, this attribute SHOULD NOT be set. + +**[4]:** When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available. + +**[5]:** When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available. @@ -96,6 +123,22 @@ it's RECOMMENDED to: | `_OTHER` | A fallback error value to be used when the instrumentation doesn't define a custom value. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +`http.request.method` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. + +| Value | Description | Stability | +|---|---|---| +| `_OTHER` | Any HTTP method that the instrumentation has no prior knowledge of. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| `CONNECT` | CONNECT method. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| `DELETE` | DELETE method. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| `GET` | GET method. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| `HEAD` | HEAD method. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| `OPTIONS` | OPTIONS method. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| `PATCH` | PATCH method. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| `POST` | POST method. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| `PUT` | PUT method. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| `TRACE` | TRACE method. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | + + @@ -107,11 +150,8 @@ it's RECOMMENDED to: The span describes the establishment of the HTTP connection. It includes the time it takes to resolve the DNS, establish the socket connection, and perform the TLS handshake. -It's different from `dotnet.http.connection` span, which describes the lifetime of the HTTP connection. -Client HTTP request spans SHOULD have links to this connection span (when it is reported). - -Span name SHOULD be `http connection_setup {address}:{server.port}`. +Span name SHOULD be `HTTP connection_setup {address}:{server.port}`. The `{address}` SHOULD be `server.address` when it's available and `network.peer.address` otherwise. Span kind SHOULD be `CLIENT`. @@ -179,7 +219,9 @@ it's RECOMMENDED to: ## Socket connection setup The span describes the establishment of the socket connection. -It's different from `dotnet.http.connection_setup` span, which covers the DNS and TLS handshake duration in addition to socket connection setup. +It's different from [*HTTP connection setup*](#http-connection-setup) span, which covers the DNS and TLS handshake duration in addition to socket connection setup. + +When *Socket connection setup* span is reported along with *HTTP connection setup* span, the socket span becomes a child of HTTP connection setup. Span name SHOULD be `socket connection_setup {network.peer.address}:{network.peer.port}`. Span kind SHOULD be `CLIENT`. @@ -271,6 +313,9 @@ The span describes DNS lookup duration and outcome. DNS lookup duration is also reported by [`dns.lookup.duration` metric](/docs/dotnet/dotnet-dns-metrics.md#metric-dnslookupduration). +When *DNS* span is reported along with *HTTP connection setup* and *Socket connection setup* span, the *DNS* span becomes a child of *HTTP connection setup* +and a sibling of *Socket connection setup*. + Span name SHOULD be `DNS {dns.question.name}`. Span kind SHOULD be `CLIENT` @@ -334,6 +379,9 @@ The span describes TLS handshake. Span name SHOULD be `TLS {dns.question.name}`. // TODO - decide on TLS! Span kind SHOULD be `CLIENT` +When *TLS* span is reported along with *HTTP connection setup* and *Socket connection setup* span, the *DNS* span becomes a child of *HTTP connection setup* +and a sibling of *Socket connection setup*. + Corresponding `Activity.OperationName` is `System.Net.Security.TlsHandshake`, `ActivitySource` name - `System.Net.Security`. Added in .NET Core 9. @@ -396,4 +444,61 @@ it's RECOMMENDED to: ## Examples +### HTTP request was performed on a connection that was immediately available + +If connection is immediately available for the request, `HttpClient` creates one span for HTTP request. + +``` +<------------------ GET / (CLIENT, trace=t1, span=s1) ---------------------------> +``` + +### HTTP request that has to wait for existing connection to become available + +If connection was not immediately available for the request, `HttpClient` creates span for HTTP request and +*Wait for connection* span. In this example, the existing connection became available, so no additional spans +related to connection setup were reported. + +``` +<------------------ GET / (CLIENT, trace=t1, span=s1) ---------------------------> +<-- wait_for_connection host:port (INTERNAL, trace=t1, span=s2) --> +``` + +### HTTP request has to wait for connection setup + +If connection was not immediately available for the request, `HttpClient` creates span for HTTP request and +*Wait for connection* span. In this example, a new connection was created and the request was executed on it immediately after +connection was created. There was no cached DNS record for the host. + +``` +<----------------------- GET / (trace=t1, span=s1) --------------------------------> +<-- wait_for_connection (trace=t1, span=s2, link_to=t2,s3) --> + + +<--------- HTTP connection_setup (trace=t2, span=s3) --------> +<--- DNS ---> + <---- socket connection_setup ----> + <--- TLS ---> +``` + +### HTTP request has to wait for connection setup and other requests on that connection to complete + +If connection was not immediately available for the request, `HttpClient` creates span for HTTP request and +*Wait for connection* span. In this example, request was performed on a new connection, but before this connection +became available for this request, other requests were performed on it. + +``` + <--------------------- GET / (trace=t1, span=s1) ------------------------------> + <---- wait_for_connection (trace=t1, span=s2, link_to=t2,s3) ----> + + +<--- HTTP connection_setup - (trace=t2, span=s3) ---> +<-- DNS --> + <-- socket connection_setup --> + <-- TLS --> +``` + +The *HTTP connection_setup* has started before this request, it also ended much earlier than +*Wait for connection* span, indicating that there is a queue of requests and high demand for +connections in the pool. + [DocumentStatus]: https://opentelemetry.io/docs/specs/otel/document-status diff --git a/model/trace/dotnet/dotnet-connections.yaml b/model/trace/dotnet/dotnet-connections.yaml index cb2eca5a2f..2baca88cca 100644 --- a/model/trace/dotnet/dotnet-connections.yaml +++ b/model/trace/dotnet/dotnet-connections.yaml @@ -1,22 +1,27 @@ groups: - - id: dotnet.http.connection + - id: dotnet.http.request.wait_for_connection type: span - span_kind: client - brief: 'The span is emitted by .NET runtime and describes the lifetime of the HTTP connection.' + span_kind: internal + brief: 'The span is emitted by .NET runtime and describes the time it takes for HTTP request to obtain a connection to run on.' note: | - HTTP connection duration is also reported by - [`http.client.connection.duration` metric](/dotnet/dotnet-http-metrics.md#metric-httpclientconnectionduration). + The span is reported only if there are no connections that are readily available to perform the request. + The span ends when the connection is obtained - it could happen if an existing connection became available or + a new connection was established, so the time wait-for-connection span tracks is different than `dotnet.http.connection_setup`. + + The time it takes to get a connection from the pool is also reported by the + [`http.client.request.time_in_queue` metric](/docs/dotnet/dotnet-http-metrics.md#metric-httpclientrequesttime_in_queue). - `Activity.OperationName`: `System.Net.Http.Connections.Connection` - `ActivitySource` name: `System.Net.Http.Connections` + `Activity.OperationName`: `System.Net.Http.WaitForConnection` + `ActivitySource` name: `"System.Net.Http` # TODO - should it be different from HTTP requests so that users can opt-in independently? Added in: .NET Core 9 attributes: + - ref: http.request.method - ref: network.protocol.version - - ref: network.peer.address - ref: server.address - ref: server.port - - ref: error.type - ref: url.scheme + - ref: error.type + examples: ["System.OperationCanceledException"] - id: dotnet.http.connection_setup type: span From 9d0a866b99f470759d16b4946fd56ec457c492fe Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Fri, 5 Jul 2024 20:50:53 -0700 Subject: [PATCH 04/12] clean up and review --- docs/attributes-registry/dns.md | 2 +- ...ion-traces.md => dotnet-network-traces.md} | 303 ++++++------------ model/registry/dns.yaml | 2 +- model/trace/dotnet/dotnet-connections.yaml | 92 ------ model/trace/dotnet/dotnet-network.yaml | 116 +++++++ 5 files changed, 217 insertions(+), 298 deletions(-) rename docs/dotnet/{dotnet-connection-traces.md => dotnet-network-traces.md} (52%) delete mode 100644 model/trace/dotnet/dotnet-connections.yaml create mode 100644 model/trace/dotnet/dotnet-network.yaml diff --git a/docs/attributes-registry/dns.md b/docs/attributes-registry/dns.md index f4d37f8331..18de006b70 100644 --- a/docs/attributes-registry/dns.md +++ b/docs/attributes-registry/dns.md @@ -12,7 +12,7 @@ This document defines the shared attributes used to report a DNS query. | Attribute | Type | Description | Examples | Stability | | ------------------- | -------- | -------------------------------------------- | --------------------------------------------------------- | ---------------------------------------------------------------- | -| `dns.answer` | string[] | The list of resolved IPv4 or IPv6 addresses. | `["10.0.0.1", "2001:0db8:85a3:0000:0000:8a2e:0370:7334"]` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| `dns.answers` | string[] | The list of resolved IPv4 or IPv6 addresses. | `["10.0.0.1", "2001:0db8:85a3:0000:0000:8a2e:0370:7334"]` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | `dns.question.name` | string | The name being queried. [1] | `www.example.com`; `opentelemetry.io` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | **[1]:** If the name field contains non-printable characters (below 32 or above 126), those characters should be represented as escaped base 10 integers (\DDD). Back slashes and quotes should be escaped. Tabs, carriage returns, and line feeds should be converted to \t, \r, and \n respectively. diff --git a/docs/dotnet/dotnet-connection-traces.md b/docs/dotnet/dotnet-network-traces.md similarity index 52% rename from docs/dotnet/dotnet-connection-traces.md rename to docs/dotnet/dotnet-network-traces.md index 47b84ecff6..0637823ee5 100644 --- a/docs/dotnet/dotnet-connection-traces.md +++ b/docs/dotnet/dotnet-network-traces.md @@ -2,7 +2,7 @@ linkTitle: HTTP client and server ---> -# Semantic Conventions for HTTP client spans emitted by .NET +# Semantic Conventions for network spans emitted by .NET **Status**: [Experimental][DocumentStatus] @@ -10,22 +10,20 @@ This article defines semantic conventions for HTTP client, DNS and TLS spans emi -- [HTTP Request: wait for connection](#http-request-wait-for-connection) +- [HTTP client request](#http-client-request-wait-for-connection) +- [HTTP client request: wait for connection](#http-client-request-wait-for-connection) - [HTTP connection setup](#http-connection-setup) -- [Socket connection setup](#socket-connection-setup) +- [Socket connect](#socket-connect) - [DNS](#dns) - [TLS](#tls) - [Examples](#examples) - [HTTP request was performed on a connection that was immediately available](#http-request-was-performed-on-a-connection-that-was-immediately-available) - - [HTTP request that has to wait for existing connection to become available](#http-request-that-has-to-wait-for-existing-connection-to-become-available) - [HTTP request has to wait for connection setup](#http-request-has-to-wait-for-connection-setup) - [HTTP request has to wait for connection setup and other requests on that connection to complete](#http-request-has-to-wait-for-connection-setup-and-other-requests-on-that-connection-to-complete) -.NET `HttpClient` reports HTTP client spans according to [HTTP Semantic Conventions](/docs/http/http-spans.md#http-client). - -TODO: we might need to describe some .NET specifics. Leaving it out for now. +.NET `HttpClient` reports HTTP client request spans according to [HTTP Semantic Conventions](/docs/http/http-spans.md#http-client). In addition to HTTP request spans, `HttpClient` reports spans describing HTTP connection establishment and its stages. @@ -33,19 +31,31 @@ While such spans represent low-level details, connection lifetime is usually mea when application is under the load, the rate of connection-related spans is expected to be much lower than the rate of HTTP client spans. Application developers are encouraged to enable corresponding instrumentation in development or test environments. Using connection-level -instrumentation in production should be done with caution as it increases the volume of reported telemetry and has performance overhead that +instrumentation in production should be done after appropriate validation as it increases the volume of reported telemetry and has performance overhead that depends on the application. -## HTTP Request: wait for connection +## HTTP client request + +.NET `HttpClient` reports client request spans according to [HTTP Client Semantic Conventions](/docs/http/http-spans.md#http-client) with the following +specific details: + +- `network.protocol.name`, `network.peer.port`, and `http.request.resend_count` are not reported +- `url.full` is redacted by default - query parameter values are replaced with `*`. Redaction can be disabled by setting `AppContext` switch `System.Net.Http.DisableQueryRedaction` to `true`. +- all attributes are reported after `Activity` is started, none are provided at creation time. + +Corresponding `Activity.OperationName` is `System.Net.Http.HttpRequestOut`, `ActivitySource` name - `System.Net.Http`. +Span with HTTP semantics was added in .NET Core 9. + +## HTTP client request: wait for connection The span describes the time it takes for the HTTP request to obtain a connection from the connection pool. -The span is reported only if there is no connection that's readily available. It's reported as a child of HTTP client span. +The span is reported only if there is no connection that's readily available. It's reported as a child of *HTTP client request* span. The span ends when the connection is obtained - it could happen when an existing connection becomes available or once -a new connection is established, so the time wait-for-connection span tracks is different than one describing [*HTTP connection setup*](#http-connection-setup). +a new connection is established, so the duration of *Wait For Connection* span is different from duration of the [*HTTP connection setup*](#http-connection-setup) span. If a new connection was created to serve the request and the corresponding [*HTTP connection setup*](#http-connection-setup) was reported, the instrumentation adds the -link to the *HTTP connection setup* on the *Wait for connection* span. +link to the *HTTP connection setup* from the *Wait for connection* span. Span name SHOULD be `wait_for_connection {server.address}:{server.port}`. @@ -66,55 +76,7 @@ The time it takes to get a connection from the pool is also reported by the | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| -| [`error.type`](/docs/attributes-registry/error.md) | string | Describes a class of error the operation ended with. [1] | `System.OperationCanceledException` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`http.request.method`](/docs/attributes-registry/http.md) | string | HTTP request method. [2] | `GET`; `POST`; `HEAD` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`network.protocol.version`](/docs/attributes-registry/network.md) | string | The actual version of the protocol used for network communication. [3] | `1.1`; `2` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`server.address`](/docs/attributes-registry/server.md) | string | Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. [4] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`server.port`](/docs/attributes-registry/server.md) | int | Server port number. [5] | `80`; `8080`; `443` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`url.scheme`](/docs/attributes-registry/url.md) | string | The [URI scheme](https://www.rfc-editor.org/rfc/rfc3986#section-3.1) component identifying the used protocol. | `https`; `ftp`; `telnet` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | - -**[1]:** The `error.type` SHOULD be predictable, and SHOULD have low cardinality. - -When `error.type` is set to a type (e.g., an exception type), its -canonical class name identifying the type within the artifact SHOULD be used. - -Instrumentations SHOULD document the list of errors they report. - -The cardinality of `error.type` within one instrumentation library SHOULD be low. -Telemetry consumers that aggregate data from multiple instrumentation libraries and applications -should be prepared for `error.type` to have high cardinality at query time when no -additional filters are applied. - -If the operation has completed successfully, instrumentations SHOULD NOT set `error.type`. - -If a specific domain defines its own set of error identifiers (such as HTTP or gRPC status codes), -it's RECOMMENDED to: - -* Use a domain-specific attribute -* Set `error.type` to capture all errors, regardless of whether they are defined within the domain-specific set or not. - -**[2]:** HTTP request method value SHOULD be "known" to the instrumentation. -By default, this convention defines "known" methods as the ones listed in [RFC9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-methods) -and the PATCH method defined in [RFC5789](https://www.rfc-editor.org/rfc/rfc5789.html). - -If the HTTP request method is not known to instrumentation, it MUST set the `http.request.method` attribute to `_OTHER`. - -If the HTTP instrumentation could end up converting valid HTTP request methods to `_OTHER`, then it MUST provide a way to override -the list of known HTTP methods. If this override is done via environment variable, then the environment variable MUST be named -OTEL_INSTRUMENTATION_HTTP_KNOWN_METHODS and support a comma-separated list of case-sensitive known HTTP methods -(this list MUST be a full override of the default known method, it is not a list of known methods in addition to the defaults). - -HTTP method names are case-sensitive and `http.request.method` attribute value MUST match a known HTTP method name exactly. -Instrumentations for specific web frameworks that consider HTTP methods to be case insensitive, SHOULD populate a canonical equivalent. -Tracing instrumentations that do so, MUST also set `http.request.method_original` to the original value. - -**[3]:** If protocol version is subject to negotiation (for example using [ALPN](https://www.rfc-editor.org/rfc/rfc7301.html)), this attribute SHOULD be set to the negotiated version. If the actual protocol version is not known, this attribute SHOULD NOT be set. - -**[4]:** When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available. - -**[5]:** When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available. - - +| [`error.type`](/docs/attributes-registry/error.md) | string | The full name of exception type. | `System.OperationCanceledException` | `Conditionally Required` if and only if an error has occurred. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | `error.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. @@ -123,22 +85,6 @@ Tracing instrumentations that do so, MUST also set `http.request.method_original | `_OTHER` | A fallback error value to be used when the instrumentation doesn't define a custom value. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -`http.request.method` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. - -| Value | Description | Stability | -|---|---|---| -| `_OTHER` | Any HTTP method that the instrumentation has no prior knowledge of. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| `CONNECT` | CONNECT method. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| `DELETE` | DELETE method. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| `GET` | GET method. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| `HEAD` | HEAD method. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| `OPTIONS` | OPTIONS method. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| `PATCH` | PATCH method. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| `POST` | POST method. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| `PUT` | PUT method. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| `TRACE` | TRACE method. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | - - @@ -168,38 +114,18 @@ Added in .NET Core 9. | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| -| [`error.type`](/docs/attributes-registry/error.md) | string | Describes a class of error the operation ended with. [1] | `timeout`; `java.net.UnknownHostException`; `server_certificate_invalid`; `500` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`error.type`](/docs/attributes-registry/error.md) | string | The full name of exception type. | `System.OperationCanceledException`; `System.Net.Sockets.SocketException` | `Conditionally Required` if and only if an error has occurred. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`network.peer.address`](/docs/attributes-registry/network.md) | string | Peer address of the network connection - IP address or Unix domain socket name. | `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`network.protocol.version`](/docs/attributes-registry/network.md) | string | The actual version of the protocol used for network communication. [2] | `1.1`; `2` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`server.address`](/docs/attributes-registry/server.md) | string | Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. [3] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`server.port`](/docs/attributes-registry/server.md) | int | Server port number. [4] | `80`; `8080`; `443` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`network.protocol.version`](/docs/attributes-registry/network.md) | string | The actual version of the protocol used for network communication. [1] | `1.1`; `2` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`server.address`](/docs/attributes-registry/server.md) | string | Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. [2] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`server.port`](/docs/attributes-registry/server.md) | int | Server port number. [3] | `80`; `8080`; `443` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`url.scheme`](/docs/attributes-registry/url.md) | string | The [URI scheme](https://www.rfc-editor.org/rfc/rfc3986#section-3.1) component identifying the used protocol. | `https`; `ftp`; `telnet` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -**[1]:** The `error.type` SHOULD be predictable, and SHOULD have low cardinality. - -When `error.type` is set to a type (e.g., an exception type), its -canonical class name identifying the type within the artifact SHOULD be used. - -Instrumentations SHOULD document the list of errors they report. - -The cardinality of `error.type` within one instrumentation library SHOULD be low. -Telemetry consumers that aggregate data from multiple instrumentation libraries and applications -should be prepared for `error.type` to have high cardinality at query time when no -additional filters are applied. - -If the operation has completed successfully, instrumentations SHOULD NOT set `error.type`. - -If a specific domain defines its own set of error identifiers (such as HTTP or gRPC status codes), -it's RECOMMENDED to: +**[1]:** If protocol version is subject to negotiation (for example using [ALPN](https://www.rfc-editor.org/rfc/rfc7301.html)), this attribute SHOULD be set to the negotiated version. If the actual protocol version is not known, this attribute SHOULD NOT be set. -* Use a domain-specific attribute -* Set `error.type` to capture all errors, regardless of whether they are defined within the domain-specific set or not. +**[2]:** When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available. -**[2]:** If protocol version is subject to negotiation (for example using [ALPN](https://www.rfc-editor.org/rfc/rfc7301.html)), this attribute SHOULD be set to the negotiated version. If the actual protocol version is not known, this attribute SHOULD NOT be set. - -**[3]:** When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available. - -**[4]:** When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available. +**[3]:** When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available. @@ -216,20 +142,20 @@ it's RECOMMENDED to: -## Socket connection setup +## Socket connect The span describes the establishment of the socket connection. -It's different from [*HTTP connection setup*](#http-connection-setup) span, which covers the DNS and TLS handshake duration in addition to socket connection setup. +It's different from [*HTTP connection setup*](#http-connection-setup) span, which also covers the DNS lookup and TLS handshake. -When *Socket connection setup* span is reported along with *HTTP connection setup* span, the socket span becomes a child of HTTP connection setup. +When *Socket connect* span is reported along with *HTTP connection setup* span, the socket span becomes a child of HTTP connection setup. -Span name SHOULD be `socket connection_setup {network.peer.address}:{network.peer.port}`. +Span name SHOULD be `socket connect {network.peer.address}:{network.peer.port}`. Span kind SHOULD be `CLIENT`. Corresponding `Activity.OperationName` is `System.Net.Sockets.ConnectionSetup`, `ActivitySource` name - `System.Net.Sockets`. Added in .NET Core 9. - + @@ -238,41 +164,41 @@ Added in .NET Core 9. | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| -| [`error.type`](/docs/attributes-registry/error.md) | string | Describes a class of error the operation ended with. [1] | `timeout`; `java.net.UnknownHostException`; `server_certificate_invalid`; `500` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`error.type`](/docs/attributes-registry/error.md) | string | Socket error code. [1] | `connection_refused`; `address_not_available` | `Conditionally Required` if and only if an error has occurred. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`network.peer.address`](/docs/attributes-registry/network.md) | string | Peer address of the network connection - IP address or Unix domain socket name. | `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`network.protocol.version`](/docs/attributes-registry/network.md) | string | The actual version of the protocol used for network communication. [2] | `1.1`; `2` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`network.transport`](/docs/attributes-registry/network.md) | string | [OSI transport layer](https://osi-model.com/transport-layer/) or [inter-process communication method](https://wikipedia.org/wiki/Inter-process_communication). [3] | `tcp`; `udp` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`network.type`](/docs/attributes-registry/network.md) | string | [OSI network layer](https://osi-model.com/network-layer/) or non-OSI equivalent. [4] | `ipv4`; `ipv6` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | - -**[1]:** The `error.type` SHOULD be predictable, and SHOULD have low cardinality. - -When `error.type` is set to a type (e.g., an exception type), its -canonical class name identifying the type within the artifact SHOULD be used. - -Instrumentations SHOULD document the list of errors they report. - -The cardinality of `error.type` within one instrumentation library SHOULD be low. -Telemetry consumers that aggregate data from multiple instrumentation libraries and applications -should be prepared for `error.type` to have high cardinality at query time when no -additional filters are applied. - -If the operation has completed successfully, instrumentations SHOULD NOT set `error.type`. - -If a specific domain defines its own set of error identifiers (such as HTTP or gRPC status codes), -it's RECOMMENDED to: - -* Use a domain-specific attribute -* Set `error.type` to capture all errors, regardless of whether they are defined within the domain-specific set or not. - -**[2]:** If protocol version is subject to negotiation (for example using [ALPN](https://www.rfc-editor.org/rfc/rfc7301.html)), this attribute SHOULD be set to the negotiated version. If the actual protocol version is not known, this attribute SHOULD NOT be set. - -**[3]:** The value SHOULD be normalized to lowercase. +| [`network.peer.port`](/docs/attributes-registry/network.md) | int | Peer port number of the network connection. | `65123` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`network.transport`](/docs/attributes-registry/network.md) | string | [OSI transport layer](https://osi-model.com/transport-layer/) or [inter-process communication method](https://wikipedia.org/wiki/Inter-process_communication). [2] | `tcp`; `udp` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`network.type`](/docs/attributes-registry/network.md) | string | [OSI network layer](https://osi-model.com/network-layer/) or non-OSI equivalent. [3] | `ipv4`; `ipv6` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | + +**[1]:** The following errors codes are reported: + +- `network_down` +- `address_already_in_use` +- `interrupted` +- `in_progress` +- `already_in_progress` +- `address_not_available` +- `address_family_not_supported` +- `connection_refused` +- `fault` +- `invalid_argument` +- `is_connected` +- `network_unreachable` +- `host_unreachable` +- `no_buffer_space_available` +- `timed_out` +- `access_denied` +- `protocol_type` + +See socket errors on [Windows]( https://learn.microsoft.com/windows/win32/api/winsock2/nf-winsock2-connect#return-value) and [Linux](https://man7.org/linux/man-pages/man2/connect.2.html) for more details. + +**[2]:** The value SHOULD be normalized to lowercase. Consider always setting the transport when setting a port number, since a port number is ambiguous without knowing the transport. For example different processes could be listening on TCP port 12345 and UDP port 12345. -**[4]:** The value SHOULD be normalized to lowercase. +**[3]:** The value SHOULD be normalized to lowercase. @@ -307,17 +233,22 @@ different processes could be listening on TCP port 12345 and UDP port 12345. -## DNS - -The span describes DNS lookup duration and outcome. +## DNS resolution +The span describes DNS lookups performed with one of the methods on [System.Net.Dns](https://learn.microsoft.com/dotnet/api/system.net.dns) class. DNS lookup duration is also reported by [`dns.lookup.duration` metric](/docs/dotnet/dotnet-dns-metrics.md#metric-dnslookupduration). -When *DNS* span is reported along with *HTTP connection setup* and *Socket connection setup* span, the *DNS* span becomes a child of *HTTP connection setup* -and a sibling of *Socket connection setup*. +DNS spans track logical operations rather than physical DNS calls and the actual behavior depends on the resolver implementation which could be changed in the future versions of .NET. +.NET 9 uses OS DNS resolver which may do zero or more physical lookups for one API call. + +When *DNS* span is reported along with *HTTP connection setup* and *Socket connect* span, the *DNS* span becomes a child of *HTTP connection setup* +and a sibling of *Socket connect*. + +DNS spans are reported for both lookups and reverse lookups. -Span name SHOULD be `DNS {dns.question.name}`. -Span kind SHOULD be `CLIENT` +Lookup (IP addresses from host name) span name SHOULD be `DNS lookup {dns.question.name}`. TODO? +Reverse lookup (host names from IP address) span name SHOULD be `DNS reverse lookup {dns.question.name}`. +Span kind SHOULD be `CLIENT`. Corresponding `Activity.OperationName` is `System.Net.NameResolution.DnsLookup`, `ActivitySource` name - `System.Net.NameResolution`. Added in .NET Core 9 @@ -331,31 +262,21 @@ Added in .NET Core 9 | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| -| [`dns.answer`](/docs/attributes-registry/dns.md) | string[] | The list of resolved IPv4 or IPv6 addresses. | `["10.0.0.1", "2001:0db8:85a3:0000:0000:8a2e:0370:7334"]` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`dns.question.name`](/docs/attributes-registry/dns.md) | string | The name being queried. [1] | `www.example.com`; `opentelemetry.io` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`error.type`](/docs/attributes-registry/error.md) | string | Describes a class of error the operation ended with. [2] | `timeout`; `java.net.UnknownHostException`; `server_certificate_invalid`; `500` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | - -**[1]:** If the name field contains non-printable characters (below 32 or above 126), those characters should be represented as escaped base 10 integers (\DDD). Back slashes and quotes should be escaped. Tabs, carriage returns, and line feeds should be converted to \t, \r, and \n respectively. - -**[2]:** The `error.type` SHOULD be predictable, and SHOULD have low cardinality. - -When `error.type` is set to a type (e.g., an exception type), its -canonical class name identifying the type within the artifact SHOULD be used. +| [`error.type`](/docs/attributes-registry/error.md) | string | Error code returned by the DNS resolver. [1] | `host_not_found`; `try_again` | `Conditionally Required` if and only if an error has occurred. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`dns.answers`](/docs/attributes-registry/dns.md) | string[] | List of resolved IP addresses or a single element containing domain name. | `["10.0.0.1", "2001:0db8:85a3:0000:0000:8a2e:0370:7334"]` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`dns.question.name`](/docs/attributes-registry/dns.md) | string | The domain name or IP address being queried. [2] | `www.example.com`; `opentelemetry.io` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -Instrumentations SHOULD document the list of errors they report. +**[1]:** The following errors are reported: -The cardinality of `error.type` within one instrumentation library SHOULD be low. -Telemetry consumers that aggregate data from multiple instrumentation libraries and applications -should be prepared for `error.type` to have high cardinality at query time when no -additional filters are applied. +- `host_not_found` +- `try_again` +- `no_recovery` +- `address_family_not_supported` +- the full exception type name. -If the operation has completed successfully, instrumentations SHOULD NOT set `error.type`. +See [SocketError](https://learn.microsoft.com/dotnet/api/system.net.sockets.socketerror) for more details. -If a specific domain defines its own set of error identifiers (such as HTTP or gRPC status codes), -it's RECOMMENDED to: - -* Use a domain-specific attribute -* Set `error.type` to capture all errors, regardless of whether they are defined within the domain-specific set or not. +**[2]:** If the name field contains non-printable characters (below 32 or above 126), those characters should be represented as escaped base 10 integers (\DDD). Back slashes and quotes should be escaped. Tabs, carriage returns, and line feeds should be converted to \t, \r, and \n respectively. @@ -372,15 +293,14 @@ it's RECOMMENDED to: -## TLS +## TLS handshake -The span describes TLS handshake. +The span describes TLS client or server handshake performed with [System.Net.Security.SslStream](https://learn.microsoft.com/dotnet/api/system.net.security.sslstream). -Span name SHOULD be `TLS {dns.question.name}`. // TODO - decide on TLS! -Span kind SHOULD be `CLIENT` +Span name SHOULD be `TLS client {server.address}` when authenticating on the client side and `TLS server` when authenticating the server. +Span kind SHOULD be `CLIENT` in both cases. -When *TLS* span is reported along with *HTTP connection setup* and *Socket connection setup* span, the *DNS* span becomes a child of *HTTP connection setup* -and a sibling of *Socket connection setup*. +When *TLS* span is reported for client-side authentication along with *HTTP connection setup* and *Socket connect* span, the *TLS* span becomes a child of *HTTP connection setup*. Corresponding `Activity.OperationName` is `System.Net.Security.TlsHandshake`, `ActivitySource` name - `System.Net.Security`. Added in .NET Core 9. @@ -394,30 +314,16 @@ Added in .NET Core 9. | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| -| [`error.type`](/docs/attributes-registry/error.md) | string | Describes a class of error the operation ended with. [1] | `timeout`; `java.net.UnknownHostException`; `server_certificate_invalid`; `500` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`tls.client.server_name`](/docs/attributes-registry/tls.md) | string | Also called an SNI, this tells the server which hostname to which the client is attempting to connect to. | `opentelemetry.io` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`error.type`](/docs/attributes-registry/error.md) | string | Describes a class of error the operation ended with. [1] | `TODO` | `Conditionally Required` if and only if an error has occurred. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`server.address`](/docs/attributes-registry/server.md) | string | The [server name indication (SNI)](https://en.wikipedia.org/wiki/Server_Name_Indication) used in the 'Client Hello' message during TLS handshake. [2] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Recommended` when authenticating the client. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`tls.protocol.name`](/docs/attributes-registry/tls.md) | string | Normalized lowercase protocol name parsed from original string of the negotiated [SSL/TLS protocol version](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_version.html#RETURN-VALUES) | `ssl`; `tls` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`tls.protocol.version`](/docs/attributes-registry/tls.md) | string | Numeric part of the version parsed from the original string of the negotiated [SSL/TLS protocol version](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_version.html#RETURN-VALUES) | `1.2`; `3` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -**[1]:** The `error.type` SHOULD be predictable, and SHOULD have low cardinality. - -When `error.type` is set to a type (e.g., an exception type), its -canonical class name identifying the type within the artifact SHOULD be used. - -Instrumentations SHOULD document the list of errors they report. - -The cardinality of `error.type` within one instrumentation library SHOULD be low. -Telemetry consumers that aggregate data from multiple instrumentation libraries and applications -should be prepared for `error.type` to have high cardinality at query time when no -additional filters are applied. +**[1]:** The following errors codes are reported: -If the operation has completed successfully, instrumentations SHOULD NOT set `error.type`. +TODO -If a specific domain defines its own set of error identifiers (such as HTTP or gRPC status codes), -it's RECOMMENDED to: - -* Use a domain-specific attribute -* Set `error.type` to capture all errors, regardless of whether they are defined within the domain-specific set or not. +**[2]:** When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available. @@ -452,17 +358,6 @@ If connection is immediately available for the request, `HttpClient` creates one <------------------ GET / (CLIENT, trace=t1, span=s1) ---------------------------> ``` -### HTTP request that has to wait for existing connection to become available - -If connection was not immediately available for the request, `HttpClient` creates span for HTTP request and -*Wait for connection* span. In this example, the existing connection became available, so no additional spans -related to connection setup were reported. - -``` -<------------------ GET / (CLIENT, trace=t1, span=s1) ---------------------------> -<-- wait_for_connection host:port (INTERNAL, trace=t1, span=s2) --> -``` - ### HTTP request has to wait for connection setup If connection was not immediately available for the request, `HttpClient` creates span for HTTP request and @@ -476,7 +371,7 @@ connection was created. There was no cached DNS record for the host. <--------- HTTP connection_setup (trace=t2, span=s3) --------> <--- DNS ---> - <---- socket connection_setup ----> + <--------- socket connect --------> <--- TLS ---> ``` @@ -493,7 +388,7 @@ became available for this request, other requests were performed on it. <--- HTTP connection_setup - (trace=t2, span=s3) ---> <-- DNS --> - <-- socket connection_setup --> + <------ socket connect -------> <-- TLS --> ``` diff --git a/model/registry/dns.yaml b/model/registry/dns.yaml index 9b328d1075..05388463ee 100644 --- a/model/registry/dns.yaml +++ b/model/registry/dns.yaml @@ -16,7 +16,7 @@ groups: as escaped base 10 integers (\DDD). Back slashes and quotes should be escaped. Tabs, carriage returns, and line feeds should be converted to \t, \r, and \n respectively. - - id: answer + - id: answers type: string[] stability: experimental brief: The list of resolved IPv4 or IPv6 addresses. diff --git a/model/trace/dotnet/dotnet-connections.yaml b/model/trace/dotnet/dotnet-connections.yaml deleted file mode 100644 index 2baca88cca..0000000000 --- a/model/trace/dotnet/dotnet-connections.yaml +++ /dev/null @@ -1,92 +0,0 @@ -groups: - - id: dotnet.http.request.wait_for_connection - type: span - span_kind: internal - brief: 'The span is emitted by .NET runtime and describes the time it takes for HTTP request to obtain a connection to run on.' - note: | - The span is reported only if there are no connections that are readily available to perform the request. - The span ends when the connection is obtained - it could happen if an existing connection became available or - a new connection was established, so the time wait-for-connection span tracks is different than `dotnet.http.connection_setup`. - - The time it takes to get a connection from the pool is also reported by the - [`http.client.request.time_in_queue` metric](/docs/dotnet/dotnet-http-metrics.md#metric-httpclientrequesttime_in_queue). - - `Activity.OperationName`: `System.Net.Http.WaitForConnection` - `ActivitySource` name: `"System.Net.Http` # TODO - should it be different from HTTP requests so that users can opt-in independently? - Added in: .NET Core 9 - attributes: - - ref: http.request.method - - ref: network.protocol.version - - ref: server.address - - ref: server.port - - ref: url.scheme - - ref: error.type - examples: ["System.OperationCanceledException"] - - - id: dotnet.http.connection_setup - type: span - span_kind: client - brief: > - The span is emitted by .NET runtime and describes the establishment of the HTTP connection. It includes - the time it takes to resolve the DNS, establish the socket connection, and perform the TLS handshake. - - It's different from `dotnet.http.connection` span, which describes the lifetime of the HTTP connection. - note: | - `Activity.OperationName`: `System.Net.Http.Connections.ConnectionSetup` - `ActivitySource` name: `System.Net.Http.Connections` TODO - should be different than connection? - Added in: .NET Core 9 - attributes: - - ref: network.protocol.version - - ref: network.peer.address - - ref: server.address - - ref: server.port - - ref: error.type - - ref: url.scheme - - - id: dotnet.socket.connection_setup - type: span - span_kind: client - brief: > - The span is emitted by .NET runtime and describes the establishment of the socket connection. - note: | - `Activity.OperationName`: `System.Net.Sockets.ConnectionSetup` - `ActivitySource` name: `System.Net.Sockets` - Added in: .NET Core 9 - attributes: - - ref: network.protocol.version - - ref: network.peer.address - - ref: network.transport - - ref: network.type - - ref: error.type - - - id: dotnet.dns.lookup - type: span - span_kind: client - brief: > - The span is emitted by .NET runtime and describes DNS lookup. - note: | - DNS lookup duration is also reported by - [`dns.lookup.duration` metric](/docs/dotnet/dotnet-dns-metrics.md#metric-dnslookupduration). - - `Activity.OperationName`: `System.Net.NameResolution.DnsLookup` - `ActivitySource` name: `System.Net.NameResolution` - Added in: .NET Core 9 - attributes: - - ref: dns.question.name - - ref: dns.answer - - ref: error.type - - - id: dotnet.tls.handshake - type: span - span_kind: client - brief: > - The span is emitted by .NET runtime and describes TLS handshake. - note: | - `Activity.OperationName`: `System.Net.Security.TlsHandshake` - `ActivitySource` name: `System.Net.Security` - Added in: .NET Core 9 - attributes: - - ref: tls.protocol.name - - ref: tls.protocol.version - - ref: tls.client.server_name - - ref: error.type \ No newline at end of file diff --git a/model/trace/dotnet/dotnet-network.yaml b/model/trace/dotnet/dotnet-network.yaml new file mode 100644 index 0000000000..57983f0bd7 --- /dev/null +++ b/model/trace/dotnet/dotnet-network.yaml @@ -0,0 +1,116 @@ +groups: + - id: dotnet.http.request.wait_for_connection + type: span + span_kind: internal + brief: 'The span describes the time it takes for HTTP request to obtain a connection to run on.' + attributes: + - ref: error.type + requirement_level: + conditionally_required: if and only if an error has occurred. + brief: The full name of exception type. + note: "" + examples: ["System.OperationCanceledException"] + + - id: dotnet.http.connection_setup + type: span + span_kind: client + brief: > + The span describes the establishment of the HTTP connection. It includes + the time it takes to resolve the DNS, establish the socket connection, and perform the TLS handshake. + attributes: + - ref: network.protocol.version + - ref: network.peer.address + - ref: server.address + - ref: server.port + - ref: error.type + brief: The full name of exception type. + note: "" + requirement_level: + conditionally_required: if and only if an error has occurred. + examples: ["System.OperationCanceledException", "System.Net.Sockets.SocketException"] + - ref: url.scheme + + - id: dotnet.socket.connect + type: span + span_kind: client + brief: > + The span describes the establishment of the socket connection. + attributes: + - ref: network.peer.port + - ref: network.peer.address + - ref: network.transport + - ref: network.type + - ref: error.type + brief: "Socket error code." + requirement_level: + conditionally_required: if and only if an error has occurred. + note: | + The following errors codes are reported: + + - `network_down` + - `address_already_in_use` + - `interrupted` + - `in_progress` + - `already_in_progress` + - `address_not_available` + - `address_family_not_supported` + - `connection_refused` + - `fault` + - `invalid_argument` + - `is_connected` + - `network_unreachable` + - `host_unreachable` + - `no_buffer_space_available` + - `timed_out` + - `access_denied` + - `protocol_type` + + See socket errors on [Windows]( https://learn.microsoft.com/windows/win32/api/winsock2/nf-winsock2-connect#return-value) and [Linux](https://man7.org/linux/man-pages/man2/connect.2.html) for more details. + examples: ["connection_refused", "address_not_available"] + + - id: dotnet.dns.lookup + type: span + span_kind: client + brief: > + The span describes DNS lookup. + attributes: + - ref: dns.question.name + brief: The domain name or IP address being queried. + - ref: dns.answers + brief: List of resolved IP addresses or a single element containing domain name. + - ref: error.type + brief: Error code returned by the DNS resolver. + requirement_level: + conditionally_required: if and only if an error has occurred. + note: | + The following errors are reported: + + - `host_not_found` + - `try_again` + - `no_recovery` + - `address_family_not_supported` + - the full exception type name. + + See [SocketError](https://learn.microsoft.com/dotnet/api/system.net.sockets.socketerror) for more details. + examples: ["host_not_found", "try_again" ] + + - id: dotnet.tls.handshake + type: span + span_kind: client + brief: > + The span describes TLS handshake. + attributes: + - ref: tls.protocol.name + - ref: tls.protocol.version + - ref: server.address + brief: The [server name indication (SNI)](https://en.wikipedia.org/wiki/Server_Name_Indication) used in the 'Client Hello' message during TLS handshake. + requirement_level: + recommended: when authenticating the client. + - ref: error.type + requirement_level: + conditionally_required: if and only if an error has occurred. + note: | + The following errors codes are reported: + + TODO + examples: ["TODO"] \ No newline at end of file From e1bc225745eed157bfbaa3d6a28755bbad5cea8c Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Mon, 8 Jul 2024 11:48:43 -0700 Subject: [PATCH 05/12] some of the feedback and lint --- .github/CODEOWNERS | 1 + docs/dotnet/dotnet-network-traces.md | 19 ++++++++----------- model/trace/dotnet/dotnet-network.yaml | 14 ++++++++------ 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index f7360531b8..69f53c8548 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -66,6 +66,7 @@ # .NET semantic conventions approvers /model/metrics/dotnet/ @open-telemetry/specs-semconv-approvers @open-telemetry/semconv-dotnet-approver @open-telemetry/semconv-http-approvers +/model/trace/dotnet/ @open-telemetry/specs-semconv-approvers @open-telemetry/semconv-dotnet-approver @open-telemetry/semconv-http-approvers /model/registry/aspnetcore.yaml @open-telemetry/specs-semconv-approvers @open-telemetry/semconv-dotnet-approver @open-telemetry/semconv-http-approvers /model/registry/signalr.yaml @open-telemetry/specs-semconv-approvers @open-telemetry/semconv-dotnet-approver @open-telemetry/semconv-http-approvers /docs/dotnet/ @open-telemetry/specs-semconv-approvers @open-telemetry/semconv-dotnet-approver @open-telemetry/semconv-http-approvers diff --git a/docs/dotnet/dotnet-network-traces.md b/docs/dotnet/dotnet-network-traces.md index 0637823ee5..dc8e320e7f 100644 --- a/docs/dotnet/dotnet-network-traces.md +++ b/docs/dotnet/dotnet-network-traces.md @@ -152,7 +152,7 @@ When *Socket connect* span is reported along with *HTTP connection setup* span, Span name SHOULD be `socket connect {network.peer.address}:{network.peer.port}`. Span kind SHOULD be `CLIENT`. -Corresponding `Activity.OperationName` is `System.Net.Sockets.ConnectionSetup`, `ActivitySource` name - `System.Net.Sockets`. +Corresponding `Activity.OperationName` is `System.Net.Sockets.Connect`, `ActivitySource` name - `System.Net.Sockets`. Added in .NET Core 9. @@ -190,7 +190,8 @@ Added in .NET Core 9. - `access_denied` - `protocol_type` -See socket errors on [Windows]( https://learn.microsoft.com/windows/win32/api/winsock2/nf-winsock2-connect#return-value) and [Linux](https://man7.org/linux/man-pages/man2/connect.2.html) for more details. +See socket errors on [Windows](https://learn.microsoft.com/windows/win32/api/winsock2/nf-winsock2-connect#return-value) and +[Linux](https://man7.org/linux/man-pages/man2/connect.2.html) for more details. **[2]:** The value SHOULD be normalized to lowercase. @@ -314,16 +315,12 @@ Added in .NET Core 9. | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| -| [`error.type`](/docs/attributes-registry/error.md) | string | Describes a class of error the operation ended with. [1] | `TODO` | `Conditionally Required` if and only if an error has occurred. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`server.address`](/docs/attributes-registry/server.md) | string | The [server name indication (SNI)](https://en.wikipedia.org/wiki/Server_Name_Indication) used in the 'Client Hello' message during TLS handshake. [2] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Recommended` when authenticating the client. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`tls.protocol.name`](/docs/attributes-registry/tls.md) | string | Normalized lowercase protocol name parsed from original string of the negotiated [SSL/TLS protocol version](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_version.html#RETURN-VALUES) | `ssl`; `tls` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`tls.protocol.version`](/docs/attributes-registry/tls.md) | string | Numeric part of the version parsed from the original string of the negotiated [SSL/TLS protocol version](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_version.html#RETURN-VALUES) | `1.2`; `3` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`error.type`](/docs/attributes-registry/error.md) | string | Describes a class of error the operation ended with. | `System.Net.Security.Authentication.AuthenticationException`; `System.OperationCanceledException` | `Conditionally Required` if and only if an error has occurred. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`server.address`](/docs/attributes-registry/server.md) | string | The [server name indication (SNI)](https://en.wikipedia.org/wiki/Server_Name_Indication) used in the 'Client Hello' message during TLS handshake. [1] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Recommended` when authenticating the client. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`tls.protocol.name`](/docs/attributes-registry/tls.md) | string | Normalized lowercase protocol name parsed from original string of the negotiated [SSL/TLS protocol version](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_version.html#RETURN-VALUES) | `ssl`; `tls` | `Recommended` when available | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`tls.protocol.version`](/docs/attributes-registry/tls.md) | string | Numeric part of the version parsed from the original string of the negotiated [SSL/TLS protocol version](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_version.html#RETURN-VALUES) | `1.2`; `3` | `Recommended` when available | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -**[1]:** The following errors codes are reported: - -TODO - -**[2]:** When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available. +**[1]:** When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available. diff --git a/model/trace/dotnet/dotnet-network.yaml b/model/trace/dotnet/dotnet-network.yaml index 57983f0bd7..6cda55b38a 100644 --- a/model/trace/dotnet/dotnet-network.yaml +++ b/model/trace/dotnet/dotnet-network.yaml @@ -65,7 +65,8 @@ groups: - `access_denied` - `protocol_type` - See socket errors on [Windows]( https://learn.microsoft.com/windows/win32/api/winsock2/nf-winsock2-connect#return-value) and [Linux](https://man7.org/linux/man-pages/man2/connect.2.html) for more details. + See socket errors on [Windows](https://learn.microsoft.com/windows/win32/api/winsock2/nf-winsock2-connect#return-value) and + [Linux](https://man7.org/linux/man-pages/man2/connect.2.html) for more details. examples: ["connection_refused", "address_not_available"] - id: dotnet.dns.lookup @@ -101,7 +102,11 @@ groups: The span describes TLS handshake. attributes: - ref: tls.protocol.name + requirement_level: + recommended: when available - ref: tls.protocol.version + requirement_level: + recommended: when available - ref: server.address brief: The [server name indication (SNI)](https://en.wikipedia.org/wiki/Server_Name_Indication) used in the 'Client Hello' message during TLS handshake. requirement_level: @@ -109,8 +114,5 @@ groups: - ref: error.type requirement_level: conditionally_required: if and only if an error has occurred. - note: | - The following errors codes are reported: - - TODO - examples: ["TODO"] \ No newline at end of file + note: "" + examples: ["System.Net.Security.Authentication.AuthenticationException", "System.OperationCanceledException"] From 33765441e1f4befe1de136e6630c436b2c75203f Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Mon, 8 Jul 2024 12:30:00 -0700 Subject: [PATCH 06/12] more feedback --- docs/dotnet/dotnet-network-traces.md | 40 +++++++------------------- model/trace/dotnet/dotnet-network.yaml | 9 +++--- 2 files changed, 14 insertions(+), 35 deletions(-) diff --git a/docs/dotnet/dotnet-network-traces.md b/docs/dotnet/dotnet-network-traces.md index dc8e320e7f..5940aa3f2c 100644 --- a/docs/dotnet/dotnet-network-traces.md +++ b/docs/dotnet/dotnet-network-traces.md @@ -61,7 +61,7 @@ Span name SHOULD be `wait_for_connection {server.address}:{server.port}`. Span kind SHOULD be `INTERNAL` -Corresponding `Activity.OperationName` is `System.Net.Http.TODO.`, `ActivitySource` name - `System.Net.Http.TODO`. +Corresponding `Activity.OperationName` is `System.Net.Http.ConnectionLink.WaitForConnection`, `ActivitySource` name - `System.Net.Http.ConnectionLink`. Span added in .NET Core 9. The time it takes to get a connection from the pool is also reported by the @@ -116,16 +116,13 @@ Added in .NET Core 9. |---|---|---|---|---|---| | [`error.type`](/docs/attributes-registry/error.md) | string | The full name of exception type. | `System.OperationCanceledException`; `System.Net.Sockets.SocketException` | `Conditionally Required` if and only if an error has occurred. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`network.peer.address`](/docs/attributes-registry/network.md) | string | Peer address of the network connection - IP address or Unix domain socket name. | `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`network.protocol.version`](/docs/attributes-registry/network.md) | string | The actual version of the protocol used for network communication. [1] | `1.1`; `2` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`server.address`](/docs/attributes-registry/server.md) | string | Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. [2] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`server.port`](/docs/attributes-registry/server.md) | int | Server port number. [3] | `80`; `8080`; `443` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`server.address`](/docs/attributes-registry/server.md) | string | Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. [1] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`server.port`](/docs/attributes-registry/server.md) | int | Server port number. [2] | `80`; `8080`; `443` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`url.scheme`](/docs/attributes-registry/url.md) | string | The [URI scheme](https://www.rfc-editor.org/rfc/rfc3986#section-3.1) component identifying the used protocol. | `https`; `ftp`; `telnet` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -**[1]:** If protocol version is subject to negotiation (for example using [ALPN](https://www.rfc-editor.org/rfc/rfc7301.html)), this attribute SHOULD be set to the negotiated version. If the actual protocol version is not known, this attribute SHOULD NOT be set. - -**[2]:** When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available. +**[1]:** When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available. -**[3]:** When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available. +**[2]:** When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available. @@ -167,8 +164,7 @@ Added in .NET Core 9. | [`error.type`](/docs/attributes-registry/error.md) | string | Socket error code. [1] | `connection_refused`; `address_not_available` | `Conditionally Required` if and only if an error has occurred. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`network.peer.address`](/docs/attributes-registry/network.md) | string | Peer address of the network connection - IP address or Unix domain socket name. | `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`network.peer.port`](/docs/attributes-registry/network.md) | int | Peer port number of the network connection. | `65123` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`network.transport`](/docs/attributes-registry/network.md) | string | [OSI transport layer](https://osi-model.com/transport-layer/) or [inter-process communication method](https://wikipedia.org/wiki/Inter-process_communication). [2] | `tcp`; `udp` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`network.type`](/docs/attributes-registry/network.md) | string | [OSI network layer](https://osi-model.com/network-layer/) or non-OSI equivalent. [3] | `ipv4`; `ipv6` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`network.type`](/docs/attributes-registry/network.md) | string | [OSI network layer](https://osi-model.com/network-layer/) or non-OSI equivalent. [2] | `ipv4`; `ipv6` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | **[1]:** The following errors codes are reported: @@ -195,12 +191,6 @@ See socket errors on [Windows](https://learn.microsoft.com/windows/win32/api/win **[2]:** The value SHOULD be normalized to lowercase. -Consider always setting the transport when setting a port number, since -a port number is ambiguous without knowing the transport. For example -different processes could be listening on TCP port 12345 and UDP port 12345. - -**[3]:** The value SHOULD be normalized to lowercase. - `error.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. @@ -210,16 +200,6 @@ different processes could be listening on TCP port 12345 and UDP port 12345. | `_OTHER` | A fallback error value to be used when the instrumentation doesn't define a custom value. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -`network.transport` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. - -| Value | Description | Stability | -|---|---|---| -| `pipe` | Named or anonymous pipe. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| `tcp` | TCP | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| `udp` | UDP | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| `unix` | Unix domain socket | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | - - `network.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. | Value | Description | Stability | @@ -264,8 +244,8 @@ Added in .NET Core 9 | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| | [`error.type`](/docs/attributes-registry/error.md) | string | Error code returned by the DNS resolver. [1] | `host_not_found`; `try_again` | `Conditionally Required` if and only if an error has occurred. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`dns.answers`](/docs/attributes-registry/dns.md) | string[] | List of resolved IP addresses or a single element containing domain name. | `["10.0.0.1", "2001:0db8:85a3:0000:0000:8a2e:0370:7334"]` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | -| [`dns.question.name`](/docs/attributes-registry/dns.md) | string | The domain name or IP address being queried. [2] | `www.example.com`; `opentelemetry.io` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`dns.answers`](/docs/attributes-registry/dns.md) | string[] | List of resolved IP addresses (for DNS lookup) or a single element containing domain name (for reverse lookup). | `["10.0.0.1", "2001:0db8:85a3:0000:0000:8a2e:0370:7334"]` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | +| [`dns.question.name`](/docs/attributes-registry/dns.md) | string | The domain name or an IP address being queried. [2] | `www.example.com`; `opentelemetry.io` | `Recommended` | ![Experimental](https://img.shields.io/badge/-experimental-blue) | **[1]:** The following errors are reported: @@ -273,7 +253,7 @@ Added in .NET Core 9 - `try_again` - `no_recovery` - `address_family_not_supported` -- the full exception type name. +- the full exception type name See [SocketError](https://learn.microsoft.com/dotnet/api/system.net.sockets.socketerror) for more details. @@ -316,7 +296,7 @@ Added in .NET Core 9. | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| | [`error.type`](/docs/attributes-registry/error.md) | string | Describes a class of error the operation ended with. | `System.Net.Security.Authentication.AuthenticationException`; `System.OperationCanceledException` | `Conditionally Required` if and only if an error has occurred. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`server.address`](/docs/attributes-registry/server.md) | string | The [server name indication (SNI)](https://en.wikipedia.org/wiki/Server_Name_Indication) used in the 'Client Hello' message during TLS handshake. [1] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Recommended` when authenticating the client. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`server.address`](/docs/attributes-registry/server.md) | string | The [server name indication (SNI)](https://en.wikipedia.org/wiki/Server_Name_Indication) used in the 'Client Hello' message during TLS handshake. [1] | `opentelemetry.io`; `example.com` | `Recommended` when authenticating the client. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`tls.protocol.name`](/docs/attributes-registry/tls.md) | string | Normalized lowercase protocol name parsed from original string of the negotiated [SSL/TLS protocol version](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_version.html#RETURN-VALUES) | `ssl`; `tls` | `Recommended` when available | ![Experimental](https://img.shields.io/badge/-experimental-blue) | | [`tls.protocol.version`](/docs/attributes-registry/tls.md) | string | Numeric part of the version parsed from the original string of the negotiated [SSL/TLS protocol version](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_version.html#RETURN-VALUES) | `1.2`; `3` | `Recommended` when available | ![Experimental](https://img.shields.io/badge/-experimental-blue) | diff --git a/model/trace/dotnet/dotnet-network.yaml b/model/trace/dotnet/dotnet-network.yaml index 6cda55b38a..e750e0b210 100644 --- a/model/trace/dotnet/dotnet-network.yaml +++ b/model/trace/dotnet/dotnet-network.yaml @@ -18,7 +18,6 @@ groups: The span describes the establishment of the HTTP connection. It includes the time it takes to resolve the DNS, establish the socket connection, and perform the TLS handshake. attributes: - - ref: network.protocol.version - ref: network.peer.address - ref: server.address - ref: server.port @@ -38,7 +37,6 @@ groups: attributes: - ref: network.peer.port - ref: network.peer.address - - ref: network.transport - ref: network.type - ref: error.type brief: "Socket error code." @@ -76,9 +74,9 @@ groups: The span describes DNS lookup. attributes: - ref: dns.question.name - brief: The domain name or IP address being queried. + brief: The domain name or an IP address being queried. - ref: dns.answers - brief: List of resolved IP addresses or a single element containing domain name. + brief: List of resolved IP addresses (for DNS lookup) or a single element containing domain name (for reverse lookup). - ref: error.type brief: Error code returned by the DNS resolver. requirement_level: @@ -90,7 +88,7 @@ groups: - `try_again` - `no_recovery` - `address_family_not_supported` - - the full exception type name. + - the full exception type name See [SocketError](https://learn.microsoft.com/dotnet/api/system.net.sockets.socketerror) for more details. examples: ["host_not_found", "try_again" ] @@ -111,6 +109,7 @@ groups: brief: The [server name indication (SNI)](https://en.wikipedia.org/wiki/Server_Name_Indication) used in the 'Client Hello' message during TLS handshake. requirement_level: recommended: when authenticating the client. + examples: ["opentelemetry.io", "example.com"] - ref: error.type requirement_level: conditionally_required: if and only if an error has occurred. From 1d1386831124685aef2f894e90b491ceb7a079ab Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Mon, 8 Jul 2024 12:36:38 -0700 Subject: [PATCH 07/12] more feedback --- docs/dotnet/dotnet-network-traces.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/dotnet/dotnet-network-traces.md b/docs/dotnet/dotnet-network-traces.md index 5940aa3f2c..65080bbc6a 100644 --- a/docs/dotnet/dotnet-network-traces.md +++ b/docs/dotnet/dotnet-network-traces.md @@ -14,8 +14,8 @@ This article defines semantic conventions for HTTP client, DNS and TLS spans emi - [HTTP client request: wait for connection](#http-client-request-wait-for-connection) - [HTTP connection setup](#http-connection-setup) - [Socket connect](#socket-connect) -- [DNS](#dns) -- [TLS](#tls) +- [DNS](#dns-resolution) +- [TLS](#tls-handshake) - [Examples](#examples) - [HTTP request was performed on a connection that was immediately available](#http-request-was-performed-on-a-connection-that-was-immediately-available) - [HTTP request has to wait for connection setup](#http-request-has-to-wait-for-connection-setup) @@ -102,7 +102,7 @@ The `{address}` SHOULD be `server.address` when it's available and `network.peer Span kind SHOULD be `CLIENT`. -Corresponding `Activity.OperationName` is `System.Net.Http.Connections.ConnectionSetup`, `ActivitySource` name - `System.Net.Http.Connections` TODO - should be different than connection? +Corresponding `Activity.OperationName` is `System.Net.Http.Connections.ConnectionSetup`, `ActivitySource` name - `System.Net.Http.Connections`. Added in .NET Core 9. From f0b43a4cf126e3e9c641c7f91ffd660b5cb2e109 Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Mon, 8 Jul 2024 12:48:34 -0700 Subject: [PATCH 08/12] lint --- docs/dotnet/dotnet-network-traces.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/dotnet/dotnet-network-traces.md b/docs/dotnet/dotnet-network-traces.md index 65080bbc6a..af5a5adcf6 100644 --- a/docs/dotnet/dotnet-network-traces.md +++ b/docs/dotnet/dotnet-network-traces.md @@ -14,8 +14,8 @@ This article defines semantic conventions for HTTP client, DNS and TLS spans emi - [HTTP client request: wait for connection](#http-client-request-wait-for-connection) - [HTTP connection setup](#http-connection-setup) - [Socket connect](#socket-connect) -- [DNS](#dns-resolution) -- [TLS](#tls-handshake) +- [DNS resolution](#dns-resolution) +- [TLS handshake](#tls-handshake) - [Examples](#examples) - [HTTP request was performed on a connection that was immediately available](#http-request-was-performed-on-a-connection-that-was-immediately-available) - [HTTP request has to wait for connection setup](#http-request-has-to-wait-for-connection-setup) @@ -96,7 +96,6 @@ The time it takes to get a connection from the pool is also reported by the The span describes the establishment of the HTTP connection. It includes the time it takes to resolve the DNS, establish the socket connection, and perform the TLS handshake. - Span name SHOULD be `HTTP connection_setup {address}:{server.port}`. The `{address}` SHOULD be `server.address` when it's available and `network.peer.address` otherwise. From b0b10c0b7525d0d9d6f3aa45b163b95463238ed8 Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Mon, 8 Jul 2024 13:32:31 -0700 Subject: [PATCH 09/12] changelog --- .chloggen/1192.yaml | 7 +++++++ docs/dotnet/dotnet-network-traces.md | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 .chloggen/1192.yaml diff --git a/.chloggen/1192.yaml b/.chloggen/1192.yaml new file mode 100644 index 0000000000..d5d7e3fe71 --- /dev/null +++ b/.chloggen/1192.yaml @@ -0,0 +1,7 @@ +change_type: enhancement +component: dotnet +note: > + Define .NET-specific network spans for DNS resolution, TLS handshake, + and socket connections, along with HTTP-level spans to (optionally) record + relationships between HTTP requests and connections. +issues: [ 1192 ] diff --git a/docs/dotnet/dotnet-network-traces.md b/docs/dotnet/dotnet-network-traces.md index af5a5adcf6..9dbba07af8 100644 --- a/docs/dotnet/dotnet-network-traces.md +++ b/docs/dotnet/dotnet-network-traces.md @@ -10,7 +10,7 @@ This article defines semantic conventions for HTTP client, DNS and TLS spans emi -- [HTTP client request](#http-client-request-wait-for-connection) +- [HTTP client request](#http-client-request) - [HTTP client request: wait for connection](#http-client-request-wait-for-connection) - [HTTP connection setup](#http-connection-setup) - [Socket connect](#socket-connect) From 46d772f9d4b3e44213b3eff21847c80cfef0a8e9 Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Wed, 10 Jul 2024 23:41:01 -0700 Subject: [PATCH 10/12] review --- docs/dotnet/README.md | 8 +-- docs/dotnet/dotnet-network-traces.md | 95 ++++++++++++++++++-------- model/trace/dotnet/dotnet-network.yaml | 18 +++-- 3 files changed, 83 insertions(+), 38 deletions(-) diff --git a/docs/dotnet/README.md b/docs/dotnet/README.md index 05e379c551..21c63a28b3 100644 --- a/docs/dotnet/README.md +++ b/docs/dotnet/README.md @@ -5,11 +5,12 @@ path_base_for_github_subdir: to: dotnet/README.md ---> -# Semantic Conventions for .NET metrics +# Semantic Conventions for .NET -**Status**: [Stable][DocumentStatus] +This article documents semantic conventions for metrics and traces emitted by the .NET runtime and individual components in the .NET ecosystem. -This article documents semantic conventions for metrics emitted by the .NET runtime and individual components in the .NET ecosystem. +The following span are currently supported: +- [HTTP client, DNS, and TLS](dotnet-network-traces.md): Semantic Conventions for HTTP client and connection-related *spans*. The following metrics are currently supported: @@ -19,4 +20,3 @@ The following metrics are currently supported: * [Kestrel](dotnet-kestrel-metrics.md): Semantic Conventions for Kestrel web server *metrics*. * [SignalR](dotnet-signalr-metrics.md): Semantic Conventions for SignalR server *metrics*. -[DocumentStatus]: https://opentelemetry.io/docs/specs/otel/document-status diff --git a/docs/dotnet/dotnet-network-traces.md b/docs/dotnet/dotnet-network-traces.md index 9dbba07af8..4a32e89163 100644 --- a/docs/dotnet/dotnet-network-traces.md +++ b/docs/dotnet/dotnet-network-traces.md @@ -4,7 +4,7 @@ linkTitle: HTTP client and server # Semantic Conventions for network spans emitted by .NET -**Status**: [Experimental][DocumentStatus] +**Status**: [Mixed][DocumentStatus] This article defines semantic conventions for HTTP client, DNS and TLS spans emitted by .NET. @@ -36,33 +36,35 @@ depends on the application. ## HTTP client request +**Status**: [Stable][DocumentStatus] + .NET `HttpClient` reports client request spans according to [HTTP Client Semantic Conventions](/docs/http/http-spans.md#http-client) with the following specific details: - `network.protocol.name`, `network.peer.port`, and `http.request.resend_count` are not reported - `url.full` is redacted by default - query parameter values are replaced with `*`. Redaction can be disabled by setting `AppContext` switch `System.Net.Http.DisableQueryRedaction` to `true`. +- When the `error.type` attribute is reported, it contains one of [HTTP Request errors](https://learn.microsoft.com/dotnet/api/system.net.http.httprequesterror) in snake_case, a full exception type, or a string representation of received status code. - all attributes are reported after `Activity` is started, none are provided at creation time. Corresponding `Activity.OperationName` is `System.Net.Http.HttpRequestOut`, `ActivitySource` name - `System.Net.Http`. -Span with HTTP semantics was added in .NET Core 9. +Span with HTTP semantics was added in .NET 9. ## HTTP client request: wait for connection +**Status**: [Experimental][DocumentStatus] + The span describes the time it takes for the HTTP request to obtain a connection from the connection pool. The span is reported only if there is no connection that's readily available. It's reported as a child of *HTTP client request* span. The span ends when the connection is obtained - it could happen when an existing connection becomes available or once a new connection is established, so the duration of *Wait For Connection* span is different from duration of the [*HTTP connection setup*](#http-connection-setup) span. -If a new connection was created to serve the request and the corresponding [*HTTP connection setup*](#http-connection-setup) was reported, the instrumentation adds the -link to the *HTTP connection setup* from the *Wait for connection* span. - Span name SHOULD be `wait_for_connection {server.address}:{server.port}`. Span kind SHOULD be `INTERNAL` -Corresponding `Activity.OperationName` is `System.Net.Http.ConnectionLink.WaitForConnection`, `ActivitySource` name - `System.Net.Http.ConnectionLink`. -Span added in .NET Core 9. +Corresponding `Activity.OperationName` is `Experimental.System.Net.Http.ConnectionLink.WaitForConnection`, `ActivitySource` name - `Experimental.System.Net.Http`. +Span added in .NET 9. The time it takes to get a connection from the pool is also reported by the [`http.client.request.time_in_queue` metric](/docs/dotnet/dotnet-http-metrics.md#metric-httpclientrequesttime_in_queue). @@ -76,7 +78,7 @@ The time it takes to get a connection from the pool is also reported by the | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| -| [`error.type`](/docs/attributes-registry/error.md) | string | The full name of exception type. | `System.OperationCanceledException` | `Conditionally Required` if and only if an error has occurred. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`error.type`](/docs/attributes-registry/error.md) | string | One of the [HTTP Request errors](https://learn.microsoft.com/dotnet/api/system.net.http.httprequesterror) in snake_case, or a full exception type. | `version_negotiation_error`; `System.OperationCanceledException` | `Conditionally Required` if and only if an error has occurred. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | `error.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. @@ -93,16 +95,22 @@ The time it takes to get a connection from the pool is also reported by the ## HTTP connection setup +**Status**: [Experimental][DocumentStatus] + The span describes the establishment of the HTTP connection. It includes the time it takes to resolve the DNS, establish the socket connection, and perform the TLS handshake. Span name SHOULD be `HTTP connection_setup {address}:{server.port}`. The `{address}` SHOULD be `server.address` when it's available and `network.peer.address` otherwise. -Span kind SHOULD be `CLIENT`. +Span kind SHOULD be `INTERNAL`. + +If the [*HTTP connection setup*](#http-connection-setup) is reported, the instrumentation adds the +link to the *HTTP client request* span pointing to the *HTTP connection setup* span. I.e. each client request span +is linked to the connection that served this request (if the connection was ever associated with this request). -Corresponding `Activity.OperationName` is `System.Net.Http.Connections.ConnectionSetup`, `ActivitySource` name - `System.Net.Http.Connections`. -Added in .NET Core 9. +Corresponding `Activity.OperationName` is `Experimental.System.Net.Http.Connections.ConnectionSetup`, `ActivitySource` name - `Experimental.System.Net.Http.Connections`. +Added in .NET 9. @@ -113,7 +121,7 @@ Added in .NET Core 9. | Attribute | Type | Description | Examples | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Stability | |---|---|---|---|---|---| -| [`error.type`](/docs/attributes-registry/error.md) | string | The full name of exception type. | `System.OperationCanceledException`; `System.Net.Sockets.SocketException` | `Conditionally Required` if and only if an error has occurred. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`error.type`](/docs/attributes-registry/error.md) | string | One of the [HTTP Request errors](https://learn.microsoft.com/dotnet/api/system.net.http.httprequesterror) in snake_case, or a full exception type. | `name_resolution_error`; `System.OperationCanceledException` | `Conditionally Required` if and only if an error has occurred. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`network.peer.address`](/docs/attributes-registry/network.md) | string | Peer address of the network connection - IP address or Unix domain socket name. | `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`server.address`](/docs/attributes-registry/server.md) | string | Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. [1] | `example.com`; `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`server.port`](/docs/attributes-registry/server.md) | int | Server port number. [2] | `80`; `8080`; `443` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | @@ -140,16 +148,18 @@ Added in .NET Core 9. ## Socket connect +**Status**: [Experimental][DocumentStatus] + The span describes the establishment of the socket connection. It's different from [*HTTP connection setup*](#http-connection-setup) span, which also covers the DNS lookup and TLS handshake. When *Socket connect* span is reported along with *HTTP connection setup* span, the socket span becomes a child of HTTP connection setup. Span name SHOULD be `socket connect {network.peer.address}:{network.peer.port}`. -Span kind SHOULD be `CLIENT`. +Span kind SHOULD be `INTERNAL`. -Corresponding `Activity.OperationName` is `System.Net.Sockets.Connect`, `ActivitySource` name - `System.Net.Sockets`. -Added in .NET Core 9. +Corresponding `Activity.OperationName` is `Experimental.System.Net.Sockets.Connect`, `ActivitySource` name - `Experimental.System.Net.Sockets`. +Added in .NET 9. @@ -162,8 +172,9 @@ Added in .NET Core 9. |---|---|---|---|---|---| | [`error.type`](/docs/attributes-registry/error.md) | string | Socket error code. [1] | `connection_refused`; `address_not_available` | `Conditionally Required` if and only if an error has occurred. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | | [`network.peer.address`](/docs/attributes-registry/network.md) | string | Peer address of the network connection - IP address or Unix domain socket name. | `10.1.2.80`; `/tmp/my.sock` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`network.peer.port`](/docs/attributes-registry/network.md) | int | Peer port number of the network connection. | `65123` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | -| [`network.type`](/docs/attributes-registry/network.md) | string | [OSI network layer](https://osi-model.com/network-layer/) or non-OSI equivalent. [2] | `ipv4`; `ipv6` | `Recommended` | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`network.peer.port`](/docs/attributes-registry/network.md) | int | Peer port number of the network connection. | `65123` | `Recommended` [2] | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`network.transport`](/docs/attributes-registry/network.md) | string | [OSI transport layer](https://osi-model.com/transport-layer/) or [inter-process communication method](https://wikipedia.org/wiki/Inter-process_communication). [3] | `tcp`; `udp`; `unix` | `Recommended` [4] | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| [`network.type`](/docs/attributes-registry/network.md) | string | [OSI network layer](https://osi-model.com/network-layer/) or non-OSI equivalent. [5] | `ipv4`; `ipv6` | `Recommended` if `network.peer.address` is an IP address. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | **[1]:** The following errors codes are reported: @@ -188,7 +199,17 @@ Added in .NET Core 9. See socket errors on [Windows](https://learn.microsoft.com/windows/win32/api/winsock2/nf-winsock2-connect#return-value) and [Linux](https://man7.org/linux/man-pages/man2/connect.2.html) for more details. -**[2]:** The value SHOULD be normalized to lowercase. +**[2]:** If port is supported for the socket address family. + +**[3]:** The value SHOULD be normalized to lowercase. + +Consider always setting the transport when setting a port number, since +a port number is ambiguous without knowing the transport. For example +different processes could be listening on TCP port 12345 and UDP port 12345. + +**[4]:** If value is not `tcp`. When missing, the value is assumed to be `tcp`. + +**[5]:** The value SHOULD be normalized to lowercase. @@ -199,6 +220,16 @@ See socket errors on [Windows](https://learn.microsoft.com/windows/win32/api/win | `_OTHER` | A fallback error value to be used when the instrumentation doesn't define a custom value. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +`network.transport` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. + +| Value | Description | Stability | +|---|---|---| +| `pipe` | Named or anonymous pipe. | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| `tcp` | TCP | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| `udp` | UDP | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | +| `unix` | Unix domain socket | ![Stable](https://img.shields.io/badge/-stable-lightgreen) | + + `network.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used. | Value | Description | Stability | @@ -215,6 +246,8 @@ See socket errors on [Windows](https://learn.microsoft.com/windows/win32/api/win ## DNS resolution +**Status**: [Experimental][DocumentStatus] + The span describes DNS lookups performed with one of the methods on [System.Net.Dns](https://learn.microsoft.com/dotnet/api/system.net.dns) class. DNS lookup duration is also reported by [`dns.lookup.duration` metric](/docs/dotnet/dotnet-dns-metrics.md#metric-dnslookupduration). @@ -226,12 +259,12 @@ and a sibling of *Socket connect*. DNS spans are reported for both lookups and reverse lookups. -Lookup (IP addresses from host name) span name SHOULD be `DNS lookup {dns.question.name}`. TODO? +Lookup (IP addresses from host name) span name SHOULD be `DNS lookup {dns.question.name}`. Reverse lookup (host names from IP address) span name SHOULD be `DNS reverse lookup {dns.question.name}`. -Span kind SHOULD be `CLIENT`. +Span kind SHOULD be `INTERNAL`. -Corresponding `Activity.OperationName` is `System.Net.NameResolution.DnsLookup`, `ActivitySource` name - `System.Net.NameResolution`. -Added in .NET Core 9 +Corresponding `Activity.OperationName` is `Experimental.System.Net.NameResolution.DnsLookup`, `ActivitySource` name - `Experimental.System.Net.NameResolution`. +Added in .NET 9 @@ -275,15 +308,17 @@ See [SocketError](https://learn.microsoft.com/dotnet/api/system.net.sockets.sock ## TLS handshake +**Status**: [Experimental][DocumentStatus] + The span describes TLS client or server handshake performed with [System.Net.Security.SslStream](https://learn.microsoft.com/dotnet/api/system.net.security.sslstream). Span name SHOULD be `TLS client {server.address}` when authenticating on the client side and `TLS server` when authenticating the server. -Span kind SHOULD be `CLIENT` in both cases. +Span kind SHOULD be `INTERNAL` in both cases. When *TLS* span is reported for client-side authentication along with *HTTP connection setup* and *Socket connect* span, the *TLS* span becomes a child of *HTTP connection setup*. -Corresponding `Activity.OperationName` is `System.Net.Security.TlsHandshake`, `ActivitySource` name - `System.Net.Security`. -Added in .NET Core 9. +Corresponding `Activity.OperationName` is `Experimental.System.Net.Security.TlsHandshake`, `ActivitySource` name - `Experimental.System.Net.Security`. +Added in .NET 9. @@ -331,7 +366,7 @@ Added in .NET Core 9. If connection is immediately available for the request, `HttpClient` creates one span for HTTP request. ``` -<------------------ GET / (CLIENT, trace=t1, span=s1) ---------------------------> +<------------------ GET / (INTERNAL, trace=t1, span=s1) ---------------------------> ``` ### HTTP request has to wait for connection setup @@ -341,8 +376,8 @@ If connection was not immediately available for the request, `HttpClient` create connection was created. There was no cached DNS record for the host. ``` -<----------------------- GET / (trace=t1, span=s1) --------------------------------> -<-- wait_for_connection (trace=t1, span=s2, link_to=t2,s3) --> +<----------------------- GET / (trace=t1, span=s1, link_to=t2,s3) --------------------------------> +<--------- wait_for_connection (trace=t1, span=s2) ----------> <--------- HTTP connection_setup (trace=t2, span=s3) --------> @@ -354,8 +389,8 @@ connection was created. There was no cached DNS record for the host. ### HTTP request has to wait for connection setup and other requests on that connection to complete If connection was not immediately available for the request, `HttpClient` creates span for HTTP request and -*Wait for connection* span. In this example, request was performed on a new connection, but before this connection -became available for this request, other requests were performed on it. +*Wait for connection* span. In this example, request was performed on a new connection, but this connection +served other requests in the queue before it became available for this request. ``` <--------------------- GET / (trace=t1, span=s1) ------------------------------> diff --git a/model/trace/dotnet/dotnet-network.yaml b/model/trace/dotnet/dotnet-network.yaml index e750e0b210..3c41367662 100644 --- a/model/trace/dotnet/dotnet-network.yaml +++ b/model/trace/dotnet/dotnet-network.yaml @@ -7,9 +7,10 @@ groups: - ref: error.type requirement_level: conditionally_required: if and only if an error has occurred. - brief: The full name of exception type. + brief: > + One of the [HTTP Request errors](https://learn.microsoft.com/dotnet/api/system.net.http.httprequesterror) in snake_case, or a full exception type. note: "" - examples: ["System.OperationCanceledException"] + examples: ["version_negotiation_error", "System.OperationCanceledException"] - id: dotnet.http.connection_setup type: span @@ -22,11 +23,12 @@ groups: - ref: server.address - ref: server.port - ref: error.type - brief: The full name of exception type. + brief: > + One of the [HTTP Request errors](https://learn.microsoft.com/dotnet/api/system.net.http.httprequesterror) in snake_case, or a full exception type. note: "" requirement_level: conditionally_required: if and only if an error has occurred. - examples: ["System.OperationCanceledException", "System.Net.Sockets.SocketException"] + examples: ["name_resolution_error", "System.OperationCanceledException"] - ref: url.scheme - id: dotnet.socket.connect @@ -36,8 +38,16 @@ groups: The span describes the establishment of the socket connection. attributes: - ref: network.peer.port + requirement_level: + recommended: If port is supported for the socket address family. - ref: network.peer.address - ref: network.type + requirement_level: + recommended: if `network.peer.address` is an IP address. + - ref: network.transport + examples: ['tcp', 'udp', 'unix'] + requirement_level: + recommended: If value is not `tcp`. When missing, the value is assumed to be `tcp`. - ref: error.type brief: "Socket error code." requirement_level: From 90c3e4939f259ca405f8a2b75c79e196185d7644 Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Thu, 11 Jul 2024 00:04:39 -0700 Subject: [PATCH 11/12] opt in + experimental --- docs/dotnet/dotnet-network-traces.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/dotnet/dotnet-network-traces.md b/docs/dotnet/dotnet-network-traces.md index 4a32e89163..ccbb9073de 100644 --- a/docs/dotnet/dotnet-network-traces.md +++ b/docs/dotnet/dotnet-network-traces.md @@ -25,14 +25,16 @@ This article defines semantic conventions for HTTP client, DNS and TLS spans emi .NET `HttpClient` reports HTTP client request spans according to [HTTP Semantic Conventions](/docs/http/http-spans.md#http-client). -In addition to HTTP request spans, `HttpClient` reports spans describing HTTP connection establishment and its stages. +In addition to stable HTTP client request spans, `HttpClient` reports experimental spans describing HTTP connection establishment and its stages. -While such spans represent low-level details, connection lifetime is usually measured in minutes, therefore in common case -when application is under the load, the rate of connection-related spans is expected to be much lower than the rate of HTTP client spans. +The connection lifetime is usually measured in minutes, so when application is under the load but connection pool is not +overloaded, the rate of connection-related spans is expected to be much lower than the rate of +HTTP client request spans. -Application developers are encouraged to enable corresponding instrumentation in development or test environments. Using connection-level -instrumentation in production should be done after appropriate validation as it increases the volume of reported telemetry and has performance overhead that -depends on the application. +Applications are encouraged to enable *HTTP client request* spans by default in production environments. + +Connection-level spans are experimental - their semantics may be changed in the future in a breaking manner. +Using connection-level instrumentation in production environments should be done after appropriate validation. ## HTTP client request From e101225c2a3a29e37d2d0db8126ee8d9df29a80d Mon Sep 17 00:00:00 2001 From: Liudmila Molkova Date: Thu, 11 Jul 2024 13:50:41 -0700 Subject: [PATCH 12/12] tls names --- docs/dotnet/dotnet-network-traces.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/dotnet/dotnet-network-traces.md b/docs/dotnet/dotnet-network-traces.md index ccbb9073de..b58cebe439 100644 --- a/docs/dotnet/dotnet-network-traces.md +++ b/docs/dotnet/dotnet-network-traces.md @@ -314,7 +314,7 @@ See [SocketError](https://learn.microsoft.com/dotnet/api/system.net.sockets.sock The span describes TLS client or server handshake performed with [System.Net.Security.SslStream](https://learn.microsoft.com/dotnet/api/system.net.security.sslstream). -Span name SHOULD be `TLS client {server.address}` when authenticating on the client side and `TLS server` when authenticating the server. +Span name SHOULD be `TLS client handshake {server.address}` when authenticating on the client side and `TLS server handshake` when authenticating the server. Span kind SHOULD be `INTERNAL` in both cases. When *TLS* span is reported for client-side authentication along with *HTTP connection setup* and *Socket connect* span, the *TLS* span becomes a child of *HTTP connection setup*.