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/.github/CODEOWNERS b/.github/CODEOWNERS
index 6f7ec8d555..4d79193dc6 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -68,7 +68,7 @@
/model/container/ @open-telemetry/specs-semconv-approvers @open-telemetry/semconv-container-approvers
/model/oci/ @open-telemetry/specs-semconv-approvers @open-telemetry/semconv-container-approvers
-# .NET semantic conventions
+# .NET semantic conventions approvers
/docs/dotnet/ @open-telemetry/specs-semconv-approvers @open-telemetry/semconv-dotnet-approver @open-telemetry/semconv-http-approvers
/docs/runtime/dotnet-metrics.md @open-telemetry/specs-semconv-approvers @open-telemetry/semconv-dotnet-approver
/model/aspnetcore/ @open-telemetry/specs-semconv-approvers @open-telemetry/semconv-dotnet-approver @open-telemetry/semconv-http-approvers
diff --git a/docs/attributes-registry/dns.md b/docs/attributes-registry/dns.md
index b694e02b3e..b7673d45f5 100644
--- a/docs/attributes-registry/dns.md
+++ b/docs/attributes-registry/dns.md
@@ -12,6 +12,7 @@ This document defines the shared attributes used to report a DNS query.
| Attribute | Type | Description | Examples | Stability |
|---|---|---|---|---|
+| `dns.answers` | string[] | The list of IPv4 or IPv6 addresses resolved during DNS lookup. | `["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] `dns.question.name`:** 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/README.md b/docs/dotnet/README.md
index 05e379c551..89fd25bdca 100644
--- a/docs/dotnet/README.md
+++ b/docs/dotnet/README.md
@@ -5,11 +5,13 @@ 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:
@@ -18,5 +20,3 @@ The following metrics are currently supported:
* [HTTP](dotnet-http-metrics.md): Semantic Conventions for HTTP client and server *metrics*.
* [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
new file mode 100644
index 0000000000..28eb99d52c
--- /dev/null
+++ b/docs/dotnet/dotnet-network-traces.md
@@ -0,0 +1,427 @@
+
+
+# Semantic Conventions for network spans emitted by .NET
+
+**Status**: [Mixed][DocumentStatus]
+
+This article defines semantic conventions for HTTP client, DNS and TLS spans emitted by .NET.
+
+
+
+- [HTTP client request](#http-client-request)
+- [HTTP client request: wait for connection](#http-client-request-wait-for-connection)
+- [HTTP connection setup](#http-connection-setup)
+- [DNS lookup](#dns-lookup)
+- [Socket connect](#socket-connect)
+- [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)
+ - [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)
+ - [HTTP request fails because connection cannot be established](#http-request-fails-because-connection-cannot-be-established)
+
+
+
+.NET `HttpClient` reports HTTP client request spans according to [HTTP Semantic Conventions](/docs/http/http-spans.md#http-client).
+
+In addition to stable HTTP client request spans, `HttpClient` reports experimental spans describing HTTP connection establishment and its stages.
+
+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.
+
+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
+
+**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` attributes 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 name, or a string representation of received status code.
+- All attributes are reported after `Activity` is started, none are provided at creation time.
+- In case redirects occur, each redirected request is reported as a separate span.
+- `SocketsHttpHandler` may retry requests on connection failure. Such retries are not reported as separate spans.
+
+Corresponding `Activity.OperationName` is `System.Net.Http.HttpRequestOut`, `ActivitySource` name - `System.Net.Http`.
+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.
+
+Span name SHOULD be `HTTP wait_for_connection {server.address}:{server.port}`.
+
+Span kind SHOULD be `INTERNAL`
+
+Corresponding `Activity.OperationName` is `Experimental.System.Net.Http.Connections.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).
+
+
+
+
+
+
+
+
+| 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 | 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.
+
+| 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
+
+**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 {server.address}:{server.port}`.
+
+Span kind SHOULD be `INTERNAL`.
+
+There is no parent-child relationship between the [*HTTP client request*](#http-client-request) and the [*HTTP connection setup*](#http-connection-setup) spans; the latter will always be a root span, defining a separate trace. However, if the connection attempt represented by the [*HTTP connection setup*](#http-connection-setup) span results in a successful HTTP connection, and that connection is picked up by a request to serve it, the instrumentation adds a link to the [*HTTP client request*](#http-client-request) span pointing to the *HTTP connection setup* span. I.e., each request is linked to the connection that served this request.
+
+Corresponding `Activity.OperationName` is `Experimental.System.Net.Http.Connections.ConnectionSetup`, `ActivitySource` name - `Experimental.System.Net.Http.Connections`.
+Added in .NET 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 | 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 IP address of the socket connection. [1] | `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. [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] `network.peer.address`:** The `network.peer.address` attribute is available only if the connection was successfully established and only for IP sockets.
+
+**[2] `server.address`:** 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] `server.port`:** 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) |
+
+
+
+
+
+
+## DNS lookup
+
+**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).
+
+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 the *DNS lookup* span is reported along with *HTTP connection setup* and *socket connect* span, the *DNS lookup* span span becomes a child of *HTTP connection setup*
+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}`.
+Reverse lookup (host names from IP address) span name SHOULD be `DNS reverse lookup {dns.question.name}`.
+Span kind SHOULD be `INTERNAL`.
+
+Corresponding `Activity.OperationName` is `Experimental.System.Net.NameResolution.DnsLookup`, `ActivitySource` name - `Experimental.System.Net.NameResolution`.
+Added in .NET 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 error code or exception name returned by [System.Net.Dns](https://learn.microsoft.com/dotnet/api/system.net.dns). [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 (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] `error.type`:** 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.
+
+**[2] `dns.question.name`:** 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.
+
+---
+
+`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 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}` when socket address family has a notion of port and `socket connect {network.peer.address}`
+otherwise.
+Span kind SHOULD be `INTERNAL`.
+
+Corresponding `Activity.OperationName` is `Experimental.System.Net.Sockets.Connect`, `ActivitySource` name - `Experimental.System.Net.Sockets`.
+Added in .NET 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 | 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` [2] | ![Stable](https://img.shields.io/badge/-stable-lightgreen) |
+| [`network.transport`](/docs/attributes-registry/network.md) | string | [OSI transport layer](https://wikipedia.org/wiki/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://wikipedia.org/wiki/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] `error.type`:** 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] `network.peer.port`:** If port is supported for the socket address family.
+
+**[3] `network.transport`:** 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] `network.transport`:** If value is not `tcp`. When missing, the value is assumed to be `tcp`.
+
+**[5] `network.type`:** 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) |
+| `quic` | QUIC | ![Experimental](https://img.shields.io/badge/-experimental-blue) |
+| `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) |
+
+
+
+
+
+
+## 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 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*.
+
+Corresponding `Activity.OperationName` is `Experimental.System.Net.Security.TlsHandshake`, `ActivitySource` name - `Experimental.System.Net.Security`.
+Added in .NET 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] | `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) |
+
+**[1] `server.address`:** 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.
+
+---
+
+`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
+
+### 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 and links it to the *HTTP connection_setup* span
+associated with this connection (the *HTTP connection_setup* span has already ended at this point).
+
+```
+<- HTTP connection_setup - (trace=t1, span=s1) ->
+<--- DNS --->
+ <--- socket connect --->
+ <--- TLS -->
+ <--- GET / (INTERNAL, trace=t2, span=s2, link_to=t1,s1) --->
+```
+
+### 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. Instrumentation added a link to *HTTP connection_setup* span on HTTP request `GET` span.
+
+```
+<--------- HTTP connection_setup (trace=t1, span=s1) -------->
+<--- DNS --->
+ <--------- socket connect -------->
+ <--- TLS --->
+
+
+<----------------------- GET / (trace=t2, span=s2, link_to=t1,s1) -------------------------------->
+<--------- HTTP wait_for_connection (trace=t2, span=s3) ---------->
+```
+
+### 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 this connection
+served other requests in the queue before it became available for this request.
+
+```
+<- HTTP connection_setup - (trace=t1, span=s1) ->
+ <--------------------- GET / (trace=t2, span=s2) ------------------------------>
+ <---- HTTP wait_for_connection (trace=t2, span=s3, link_to=t1,s1) ---->
+```
+
+The *HTTP connection_setup* span 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.
+
+### HTTP request fails because connection cannot be established
+
+If HTTP request fails before connection is established:
+
+- all attempts to establish connections are recorded as *HTTP connection_setup* spans
+- HTTP request `GET` span is recorded with the corresponding error type along with *Wait for connection* span.
+- HTTP request `GET` span is **not** linked to any of the *HTTP connection_setup* spans since these connections were never associated with corresponding request.
+
+```
+<- HTTP connection_setup - (trace=t1, span=s1) - ERROR ->
+<------------------- DNS - timeout ---------------->
+
+<---------- GET / (trace=t2, span=s2) - ERROR ---------->
+<- HTTP wait_for_connection (trace=t2, span=s3) - ERROR ->
+```
+
+[DocumentStatus]: https://opentelemetry.io/docs/specs/otel/document-status
diff --git a/model/dns/registry.yaml b/model/dns/registry.yaml
index 78310e93d1..b8a8ef0951 100644
--- a/model/dns/registry.yaml
+++ b/model/dns/registry.yaml
@@ -16,3 +16,9 @@ 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: dns.answers
+ type: string[]
+ stability: experimental
+ brief: The list of IPv4 or IPv6 addresses resolved during DNS lookup.
+ examples:
+ - ["10.0.0.1", "2001:0db8:85a3:0000:0000:8a2e:0370:7334"]
diff --git a/model/dotnet/network-spans.yaml b/model/dotnet/network-spans.yaml
new file mode 100644
index 0000000000..ebefb330d3
--- /dev/null
+++ b/model/dotnet/network-spans.yaml
@@ -0,0 +1,135 @@
+groups:
+ - id: span.dotnet.http.request.wait_for_connection.internal
+ type: span
+ span_kind: internal
+ stability: experimental
+ 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: >
+ 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: ["version_negotiation_error", "System.OperationCanceledException"]
+
+ - id: span.dotnet.http.connection_setup.client
+ type: span
+ span_kind: client
+ stability: experimental
+ 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.peer.address
+ brief: Peer IP address of the socket connection.
+ note: >
+ The `network.peer.address` attribute is available only if the connection was successfully established and only for IP sockets.
+ - ref: server.address
+ - ref: server.port
+ - ref: error.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: ["name_resolution_error", "System.OperationCanceledException"]
+ - ref: url.scheme
+
+ - id: span.dotnet.socket.connect.client
+ type: span
+ span_kind: client
+ stability: experimental
+ brief: >
+ 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:
+ 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: span.dotnet.dns.lookup.client
+ type: span
+ span_kind: client
+ stability: experimental
+ brief: >
+ The span describes DNS lookup.
+ attributes:
+ - ref: dns.question.name
+ brief: The domain name or an IP address being queried.
+ - ref: dns.answers
+ brief: List of resolved IP addresses (for DNS lookup) or a single element containing domain name (for reverse lookup).
+ - ref: error.type
+ brief: The error code or exception name returned by [System.Net.Dns](https://learn.microsoft.com/dotnet/api/system.net.dns).
+ 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: span.dotnet.tls.handshake.client
+ type: span
+ span_kind: client
+ stability: experimental
+ brief: >
+ 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:
+ 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.
+ note: ""
+ examples: ["System.Net.Security.Authentication.AuthenticationException", "System.OperationCanceledException"]