diff --git a/docs/azure/includes/dotnet-all.md b/docs/azure/includes/dotnet-all.md index 74ccf53e6354d..500d2a986aa62 100644 --- a/docs/azure/includes/dotnet-all.md +++ b/docs/azure/includes/dotnet-all.md @@ -477,7 +477,7 @@ | App Service - API Apps Service | NuGet [0.9.64](https://www.nuget.org/packages/Microsoft.Azure.AppService.ApiApps.Service/0.9.64) | | | | Code Analyzers for Durable Functions | NuGet [0.5.0](https://www.nuget.org/packages/Microsoft.Azure.WebJobs.Extensions.DurableTask.Analyzers/0.5.0) | | GitHub [0.5.0](https://github.com/Azure/azure-functions-durable-extension/tree/Analyzer-v0.3.0/src/WebJobs.Extensions.DurableTask.Analyzers) | | Cosmos DB - BulkExecutor | NuGet [2.5.1-preview](https://www.nuget.org/packages/Microsoft.Azure.CosmosDB.BulkExecutor/2.5.1-preview) | | GitHub [2.5.1-preview](https://github.com/Azure/azure-cosmosdb-bulkexecutor-dotnet-getting-started) | -| Cosmos DB - Direct | NuGet [3.37.2](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Direct/3.37.2) | | GitHub [3.37.2](https://github.com/Azure/azure-cosmos-dotnet-v3) | +| Cosmos DB - Direct | NuGet [3.37.3](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Direct/3.37.3) | | GitHub [3.37.3](https://github.com/Azure/azure-cosmos-dotnet-v3) | | Cosmos DB - Encryption | NuGet [2.0.3](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Encryption/2.0.3)
NuGet [2.1.0-preview4](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Encryption/2.1.0-preview4) | | GitHub [2.0.3](https://github.com/Azure/azure-cosmos-dotnet-v3/tree/releases/encryption/1.0.0-preview4/Microsoft.Azure.Cosmos.Encryption) | | Cosmos DB - Encryption | NuGet [1.0.0-preview07](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Encryption.Custom/1.0.0-preview07) | | | | Extensions - Caching Cosmos | NuGet [1.7.0](https://www.nuget.org/packages/Microsoft.Extensions.Caching.Cosmos/1.7.0) | | GitHub [1.7.0](https://github.com/Azure/Microsoft.Extensions.Caching.Cosmos/tree/v1.0.0-preview4) | diff --git a/docs/core/diagnostics/built-in-metrics-system-net.md b/docs/core/diagnostics/built-in-metrics-system-net.md index 738520aecb7b2..275386b3ab45b 100644 --- a/docs/core/diagnostics/built-in-metrics-system-net.md +++ b/docs/core/diagnostics/built-in-metrics-system-net.md @@ -67,7 +67,7 @@ The `System.Net.Http` metrics report HTTP request and connection information fro | Attribute | Type | Description | Examples | Presence | |---|---|---|---|---| | `http.connection.state` | string | State of HTTP connection in the HTTP connection pool. | `active`; `idle` | Always | -| `network.protocol.version` | string | Version of the application layer protocol used. | `1.1`; `2` | Always | +| `network.protocol.version` | string | Version of the HTTP protocol used. | `1.1`; `2` | Always | | `server.address` | string | Host identifier of the ["URI origin"](https://www.rfc-editor.org/rfc/rfc9110.html#name-uri-origin) HTTP request is sent to. | `example.com` | Always | | `server.port` | int | Port identifier of the ["URI origin"](https://www.rfc-editor.org/rfc/rfc9110.html#name-uri-origin) HTTP request is sent to. | `80`; `8080`; `443` | If not default (`80` for `http` scheme, `443` for `https`) | | `network.peer.address` | string | Peer IP address of the socket connection. | `10.5.3.2` | Always | @@ -85,7 +85,7 @@ Available starting in: .NET 8 | Attribute | Type | Description | Examples | Presence | |---|---|---|---|---| -| `network.protocol.version` | string | Version of the application layer protocol used. | `1.1`; `2` | Always | +| `network.protocol.version` | string | Version of the HTTP protocol used. | `1.1`; `2` | Always | | `server.address` | string | Host identifier of the ["URI origin"](https://www.rfc-editor.org/rfc/rfc9110.html#name-uri-origin) HTTP request is sent to. | `example.com` | Always | | `server.port` | int | Port identifier of the ["URI origin"](https://www.rfc-editor.org/rfc/rfc9110.html#name-uri-origin) HTTP request is sent to. | `80`; `8080`; `443` | If not default (`80` for `http` scheme, `443` for `https`) | | `network.peer.address` | string | IP address of the socket connection. | `10.5.3.2` | Always | @@ -105,14 +105,27 @@ Available starting in: .NET 8 | Attribute | Type | Description | Examples | Presence | |---|---|---|---|---| -| `error.type` | string | Request failure reason: one of the [HTTP request errors](xref:System.Net.Http.HttpRequestError), or a full exception type, or an HTTP 4xx/5xx status code. | `System.Threading.Tasks.TaskCanceledException`; `name_resolution_error`; `secure_connection_error` ; `404` | If request has failed. | -| `http.request.method` | string | HTTP request method. | `GET`; `POST`; `HEAD` | Always | -| `http.response.status_code` | int | [HTTP response status code](https://tools.ietf.org/html/rfc7231#section-6). | `200` | If one was received. | -| `network.protocol.version` | string | Version of the application layer protocol used. | `1.1`; `2` | If response was received. | +| `error.type` | string | Request failure reason: one of the [HTTP request errors](xref:System.Net.Http.HttpRequestError) in snake_case, or a full exception type, or an HTTP 4xx/5xx status code. | `System.Threading.Tasks.TaskCanceledException`; `name_resolution_error`; `secure_connection_error` ; `404` | If request has failed. | +| `http.request.method` | string | HTTP request method. | `GET`; `POST`; `HEAD`; `_OTHER` [2] | Always | +| `http.response.status_code` | int | [HTTP response status code](https://tools.ietf.org/html/rfc7231#section-6). | `200` | If response was received. | +| `network.protocol.version` | string | Version of the HTTP protocol used. | `1.1`; `2` | If response was received. | | `server.address` | string | Host identifier of the ["URI origin"](https://www.rfc-editor.org/rfc/rfc9110.html#name-uri-origin) HTTP request is sent to. | `example.com` | Always | -| `server.port` | int | Port identifier of the ["URI origin"](https://www.rfc-editor.org/rfc/rfc9110.html#name-uri-origin) HTTP request is sent to. | `80`; `8080`; `443` | If not default (`80` for `http` scheme, `443` for `https`) | +| `server.port` | int | Port identifier of the ["URI origin"](https://www.rfc-editor.org/rfc/rfc9110.html#name-uri-origin) HTTP request is sent to. | `80`; `8080`; `443` | Depends on .NET version. [3] | | `url.scheme` | string | The [URI scheme](https://www.rfc-editor.org/rfc/rfc3986#section-3.1) component identifying the used protocol. | `http`; `https`; `ftp` | Always | +**[1] `error.type`:** If the request has failed, the value is set to one of the following: + +- An exception name with type, for example, . +- A status code that indicates a client or server error, for example, `500`. +- If an occurred with an other than `Unknown`, the enum value in snake case, for example, `name_resolution_error`. + +**[2] `http.request.method`:** `http.request.method`:** The value contains the method name, if the method is one of the well-known methods listed in [RFC9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-methods); otherwise the value is `_OTHER`. The user-provided method names will be mapped to known names in a case-insensitive manner. For example, if the user provides the name `GeT`, it will be mapped to `GET`. + +**[3] `server.port`:** The Presence of the value is version-dependent: + +- *.NET 8*: Present if not default (`80` for `http` scheme, `443` for `https`) +- *.NET 9+*: Always present + HTTP client request duration measures the time the underlying client handler takes to complete the request. Completing the request includes the time up to reading response headers from the network stream. It doesn't include the time spent reading the response body. When using OpenTelemetry, the default buckets for this metric are set to [ 0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1, 2.5, 5, 7.5, 10 ]. @@ -131,7 +144,7 @@ Available starting in: .NET 8 | Attribute | Type | Description | Examples | Presence | |---|---|---|---|---| | `http.request.method` | string | HTTP request method. | `GET`; `POST`; `HEAD` | Always | -| `network.protocol.version` | string | Version of the application layer protocol used. | `1.1`; `2` | Always | +| `network.protocol.version` | string | Version of the HTTP protocol used. | `1.1`; `2` | Always | | `server.address` | string | Host identifier of the ["URI origin"](https://www.rfc-editor.org/rfc/rfc9110.html#name-uri-origin) HTTP request is sent to. | `example.com` | Always | | `server.port` | int | Port identifier of the ["URI origin"](https://www.rfc-editor.org/rfc/rfc9110.html#name-uri-origin) HTTP request is sent to. | `80`; `8080`; `443` | If not default (`80` for `http` scheme, `443` for `https`) | | `url.scheme` | string | The [URI scheme](https://www.rfc-editor.org/rfc/rfc3986#section-3.1) component identifying the used protocol. | `http`; `https`; `ftp` | Always | diff --git a/docs/core/diagnostics/distributed-tracing-builtin-activities.md b/docs/core/diagnostics/distributed-tracing-builtin-activities.md new file mode 100644 index 0000000000000..be61a20ca3c3b --- /dev/null +++ b/docs/core/diagnostics/distributed-tracing-builtin-activities.md @@ -0,0 +1,151 @@ +--- +title: Built-in Activities in .NET +description: Overview of activities emitted by the .NET libraries +ms.date: 12/05/2024 +ms.topic: reference +--- + +# Built-in activities in .NET + +This is a reference for distributed tracing [activities](xref:System.Diagnostics.Activity) emitted natively by .NET's built-in instances. + +## System.Net activities + +### HTTP client request + + and report the HTTP client request activity following the recommendations defined in OpenTelemetry [HTTP Client Semantic Conventions](https://opentelemetry.io/docs/specs/semconv/http/http-spans/#http-client). It describes the HTTP request sent by 's send overloads during the time interval the underlying handler completes the request. Completing the request includes the time up to reading response headers from the network stream. It doesn't include the time spent reading the response body. may retry requests, for example, on connection failures or HTTP version downgrades. Retries are not reported as separate *HTTP client request* activities. + +| Availability | name | | | +|---|---|---|---| +| .NET 9+ | `System.Net.Http` | `System.Net.Http.HttpRequestOut` | `{HTTP method}` | + +> [!NOTE] +> The `System.Net.Http.HttpRequestOut` activity is in fact available on earlier versions of .NET, however its , , and attributes (tags) are only populated starting with .NET 9. On earlier versions, the [OpenTelemetry.Instrumentation.Http](https://www.nuget.org/packages/OpenTelemetry.Instrumentation.Http/) package is recommended to fill the gaps of the built-in instrumentation. + +#### Attributes (tags) + +| Attribute | Type | Description | Examples | Presence | +|---|---|---|---|---| +| `http.request.method` | `string` | HTTP request method. [1] | `GET`; `POST`; `HEAD`; `_OTHER` | Always | +| `server.address` | `string` | Host identifier of the ["URI origin"](https://www.rfc-editor.org/rfc/rfc9110.html#name-uri-origin) HTTP request is sent to. | `example.com`; `10.1.2.80` | Always | +| `server.port` | `int` | Port identifier of the ["URI origin"](https://www.rfc-editor.org/rfc/rfc9110.html#name-uri-origin) HTTP request is sent to. | `80`; `8080`; `443` | Always | +| `url.full` | `string` | Absolute URL describing a network resource according to [RFC3986](https://www.rfc-editor.org/rfc/rfc3986) [2] | `https://www.foo.bar/search?q=*` | Always | +| `error.type` | `string` | Request failure reason: one of the [HTTP request errors](xref:System.Net.Http.HttpRequestError) in snake_case, or a full exception type, or an HTTP 4xx/5xx status code. | `System.OperationCanceledException`; `name_resolution_error`; `secure_connection_error` ; `404` | If the request has failed. | +| `http.request.method_original` | `string` | Original HTTP method sent by the client in the request line. | `ACL`; `foo` | If `http.request.method` is not a well-known method. | +| `http.response.status_code` | `int` | [HTTP response status code](https://tools.ietf.org/html/rfc7231#section-6). | `200` | If response was received. | +| `network.protocol.version` | `string` | Version of the HTTP protocol used. | `1.1`; `2` | If response was received. | + +**[1] `http.request.method`:** The value contains the method name, if the method is one of the well-known methods listed in [RFC9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-methods); otherwise the value is `_OTHER`. The user-provided method names are mapped to known names in a case-insensitive manner. For example, if the user provides the name `GeT`, it will be mapped to `GET`, and `http.request.method_original` will not be populated. + +**[2] `url.full`:** To avoid leaking secrets the value is redacted by default: the entire query is replaced with a `*` character and the user info & fragment are removed. For more information and opt-out switches, see the [URI redaction breaking change docs](../compatibility/networking/9.0/query-redaction-logs.md). + +### HTTP client request: wait for connection (experimental) + +This activity is a child of an *HTTP client request* activity. It represents the time interval the corresponding request is waiting for an available connection in the request queue. If a free connection is available in the pool when the request comes in, no *wait for connection* activity will be created. Note that *wait for connection* does not represent the actual connection establishment; that is modeled by the *HTTP connection setup* activity. may retry requests, for example, on connection failures or HTTP version downgrades. Retries are not reported as separate *HTTP client request* activities; however, each new connection attempt will result in a new *wait for connection* activity under the parent request activity. + +| Availability | name | | | +|---|---|---|---| +| .NET 9+ | `Experimental.System.Net.Http.Connections` | `Experimental.System.Net.Http.Connections.WaitForConnection` | `HTTP wait_for_connection {address}:{port}` | + +> [!TIP] +> The time it takes to get a connection from the pool is also reported by the [`http.client.request.time_in_queue`](built-in-metrics-system-net.md#metric-httpclientrequesttime_in_queue) metric. + +> [!WARNING] +> This activity is experimental. It might be altered or deleted in a future version. + +#### Attributes (tags) + +| Attribute | Type | Description | Examples | Presence | +|---|---|---|---|---| +| `error.type` | `string` | The connection failure reason: one of the [HTTP request errors](xref:System.Net.Http.HttpRequestError) in snake_case, or a full exception type. | `System.OperationCanceledException`; `name_resolution_error`; `secure_connection_error` | If the connection attempt fails. | + +### HTTP connection setup (experimental) + +This activity describes the establishment of an HTTP connection. Typically, this includes the the time it takes to resolve the DNS, establish the socket connection, and perform the TLS handshake. + +| Availability | name | | | +|---|---|---|---| +| .NET 9+ | `Experimental.System.Net.Http.Connections` | `Experimental.System.Net.Http.Connections.ConnectionSetup` | `HTTP connection_setup {address}:{port}` | + +There is no parent-child relationship between the *HTTP client request* and the *HTTP connection setup* activities; the latter will always be a root activity, living in a separate trace. However, if the connection attempt represented by *HTTP connection setup* results in a succesful HTTP connection, and that connection is picked up by a request to serve it, the instrumentation adds an to the *HTTP client request* activity pointing to the *HTTP connection setup* activity. That is, each request is linked to the connection that served the request. + +> [!NOTE] +> If *HTTP connection setup* fails, it won't be linked to any *HTTP client request*. + +> [!WARNING] +> This activity is experimental. It might be altered or deleted in a future version. + +#### Attributes (tags) + +| Attribute | Type | Description | Examples | Presence | +|---|---|---|---|---| +| `error.type` | `string` | Connection failure reason: one of the [HTTP request errors](xref:System.Net.Http.HttpRequestError) in snake_case, or a full exception type. | `System.Net.Sockets.SocketException`; `name_resolution_error`; `secure_connection_error` | If the connection attempt fails. | +| `network.peer.address` | `string` | Peer IP address of the socket connection. | `10.5.3.2` | If the connection attempt succeeds. | +| `server.address` | `string` | Host identifier of the ["URI origin"](https://www.rfc-editor.org/rfc/rfc9110.html#name-uri-origin) the initial HTTP request is sent to. | `example.com` | Always | +| `server.port` | `int` | | Port identifier of the ["URI origin"](https://www.rfc-editor.org/rfc/rfc9110.html#name-uri-origin) the initial HTTP request is sent to. | Always | +| `url.scheme` | `string` | The [URI scheme](https://www.rfc-editor.org/rfc/rfc3986#section-3.1) component identifying the used protocol. | `http`; `https` | Always | + +### DNS lookup (experimental) + +This activity describes DNS lookups performed via calls. It corresponds to the managed call and not the physical DNS lookup(s) done by the underlying OS resolver. When the *DNS lookup* activity is reported along with a *HTTP connection setup* activity, *DNS lookup* becomes a child of *HTTP connection setup*. + +| Availability | name | | | +|---|---|---|---| +| .NET 9+ | `Experimental.System.Net.NameResolution` | `Experimental.System.Net.NameResolution.DnsLookup` | `DNS [reverse] lookup {question}` | + +> [!TIP] +> The DNS lookup duration is also reported by the [`dns.lookup.duration`](built-in-metrics-system-net.md#metric-dnslookupduration) metric. + +> [!WARNING] +> This activity is experimental. It might be altered or deleted in a future version. + +#### Attributes (tags) + +| Attribute | Type | Description | Examples | Presence | +|---|---|---|---|---| +| `error.type` | `string` | The error code or exception name. [1] | `host_not_found` | If the lookup fails. | +| `dns.answers` | `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"]` | If the lookup succeeds. | +| `dns.question.name` | `string` | The domain name or an IP address being queried. | `example.com` | Always | + +**[1]:** The value is either a DNS-related in snake_case (`host_not_found`, `try_again`, `no_recovery`, `address_family_not_supported`), or a full exception name. + +### Socket connect (experimental) + +This activity describes the establishment of a connection via or . When the *socket connect* activity is reported along with an *HTTP connection setup* activity, *socket connect* becomes a child of *HTTP connection setup*. + +| Availability | name | | | +|---|---|---|---| +| .NET 9+ | `Experimental.System.Net.Sockets` | `Experimental.System.Net.Sockets.Connect` | `socket connect {address}[:{port}]` | + +> [!WARNING] +> This activity is experimental. It might be altered or deleted in a future version. + +#### Attributes (tags) + +| Attribute | Type | Description | Examples | Presence | +|---|---|---|---|---| +| `error.type` | `string` | The in snake_case. | `address_already_in_use`; `connection_refused` | If the socket connection attempt fails. | +| `network.peer.address` | `string` | Peer address of the network connection - IP address or Unix domain socket name. | `10.5.3.2`; `/tmp/my.sock` | IP and UDS sockets. | +| `network.peer.port` | `int` | Peer port number of the IP connection. | `65123` | IP sockets. | +| `network.transport` | `string` | [OSI transport layer](https://en.wikipedia.org/wiki/Transport_layer) or [inter-process communication method](https://wikipedia.org/wiki/Inter-process_communication). | `tcp`; `udp`; `unix` | IP and UDS sockets. | +| `network.type` | `string` | [OSI network layer](https://en.wikipedia.org/wiki/Network_layer) or non-OSI equivalent. | `ipv4`; `ipv6` | IP sockets. | + +### TLS handshake (experimental) + +This activity describes the TLS client or server handshake performed via 's authentication methods. When the *TLS handshake* activity is reported for client-side authentication along with the *HTTP connection setup* activity, *TLS handshake* becomes a child of *HTTP connection setup*. + +| Availability | name | | | +|---|---|---|---| +| .NET 9+ | `Experimental.System.Net.Security` | `Experimental.System.Net.Security.TlsHandshake` | `TLS client handshake {host}` -or- `TLS server handshake` | + +> [!WARNING] +> This activity is experimental. It might be altered or deleted in future versions. + +#### Attributes (tags) + +| Attribute | Type | Description | Examples | Presence | +|---|---|---|---|---| +| `error.type` | `string` | Describes a class of error the operation ended with. | `System.Net.Security.Authentication.AuthenticationException`; `System.OperationCanceledException` | If the handshake fails. | +| `server.address` | `string` | The [server name indication (SNI)](https://en.wikipedia.org/wiki/Server_Name_Indication) used in the 'Client Hello' message during TLS handshake. | `example.com` | When authenticating as client. | +| `tls.protocol.name` | `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` | When the protocol info is available. | +| `tls.protocol.version` | `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`; `1.3` | When the protocol info is available. | diff --git a/docs/core/diagnostics/distributed-tracing-concepts.md b/docs/core/diagnostics/distributed-tracing-concepts.md index bf92cf958e823..08f27cacda5cc 100644 --- a/docs/core/diagnostics/distributed-tracing-concepts.md +++ b/docs/core/diagnostics/distributed-tracing-concepts.md @@ -134,3 +134,5 @@ recorded. For example code to get started using distributed tracing in .NET applications, see the [Distributed Tracing Instrumentation](distributed-tracing-instrumentation-walkthroughs.md). + +For a list of activities emitted natively by .NET, see [Built-in activities in .NET](distributed-tracing-builtin-activities.md). diff --git a/docs/core/diagnostics/distributed-tracing.md b/docs/core/diagnostics/distributed-tracing.md index bea413c7dc64f..11c00e751bd21 100644 --- a/docs/core/diagnostics/distributed-tracing.md +++ b/docs/core/diagnostics/distributed-tracing.md @@ -35,6 +35,10 @@ For more information, see [Understand distributed tracing concepts](distributed- For third-party telemetry collection services, follow the setup instructions provided by the vendor. +## Built-in activities emitted by .NET + +For a comprehensive list of activities built into .NET see [Built-in activities in .NET](distributed-tracing-builtin-activities.md). + ## Getting started for .NET library developers .NET libraries don't need to be concerned with how telemetry is ultimately collected, only diff --git a/docs/core/extensions/generic-host.md b/docs/core/extensions/generic-host.md index f9a040858984b..013fd993b0311 100644 --- a/docs/core/extensions/generic-host.md +++ b/docs/core/extensions/generic-host.md @@ -225,7 +225,7 @@ To add host configuration, call on an . The public property allows consumers to read from or make changes to the existing configuration using available extension methods. +App configuration is created by calling on an . The public property allows consumers to read from or make changes to the existing configuration using available extension methods. # [IHostBuilder](#tab/hostbuilder) @@ -243,13 +243,13 @@ There are several ways in which a hosted process is stopped. Most commonly, a ho - If someone doesn't call or and the app exits normally with `Main` completing. - If the app crashes. -- If the app is forcefully shut down using [SIGKILL][sigkill] (or CTRL+Z). +- If the app is forcefully shut down using [SIGKILL][sigkill] (or Ctrl+Z). The hosting code isn't responsible for handling these scenarios. The owner of the process needs to deal with them the same as any other app. There are several other ways in which a hosted service process can be stopped: - If `ConsoleLifetime` is used (), it listens for the following signals and attempts to stop the host gracefully. - - [SIGINT][sigint] (or CTRL+C). - - [SIGQUIT][sigquit] (or CTRL+BREAK on Windows, CTRL+\\ on Unix). + - [SIGINT][sigint] (or Ctrl+C). + - [SIGQUIT][sigquit] (or Ctrl+BREAK on Windows, Ctrl+\\ on Unix). - [SIGTERM][sigterm] (sent by other apps, such as `docker stop`). - If the app calls . @@ -305,7 +305,7 @@ to exit gracefully. There are various other common scenarios in which graceful shutdown works in Kestrel for both HTTP/1.1 and HTTP/2 protocols, and how you can configure it in different environments with a load balancer to drain traffic smoothly. While web server configuration is beyond the scope of this article, you can find more information on [Configure options for the ASP.NET Core Kestrel web server](/aspnet/core/fundamentals/servers/kestrel/options) documentation. -When the Host receives a shutdown signal (for example, CTL+C or `StopAsync`), it notifies the application by signaling . You should subscribe to this event if you have any long-running operations that need to finish gracefully. +When the Host receives a shutdown signal (for example, Ctrl+C or `StopAsync`), it notifies the application by signaling . You should subscribe to this event if you have any long-running operations that need to finish gracefully. Next, the Host calls with a shutdown timeout that you can configure (default 30s). Kestrel (and Http.Sys) close their port bindings and stop accepting new connections. They also tell the current connections to stop processing new requests. For HTTP/2 and HTTP/3, a preliminary `GOAWAY` message is sent to the client. For HTTP/1.1, they stop the connection loop because requests are processed in order. IIS behaves differently, by rejecting new requests with a 503 status code. diff --git a/docs/core/porting/versioning-sdk-msbuild-vs.md b/docs/core/porting/versioning-sdk-msbuild-vs.md index e1310c15a8808..18a4ba8f87f45 100644 --- a/docs/core/porting/versioning-sdk-msbuild-vs.md +++ b/docs/core/porting/versioning-sdk-msbuild-vs.md @@ -16,6 +16,11 @@ The first part of the .NET SDK version matches the .NET version that it includes For example, version 7.0.203 ships with .NET 7, is the second minor Visual Studio release since 7.0.100 first came out, and is the third patch since 7.0.200 released. +An installation of Visual Studio includes a single matching copy of the .NET SDK. If you update your Visual Studio instance, the .NET SDK installed by Visual Studio is also updated, including across .NET SDK feature bands and major bands. If you want to use a different .NET SDK than what's installed by Visual Studio, you can install it from the [.NET download page](https://aka.ms/dotnet/download), and Visual Studio upgrade won't touch that version. You're responsible for updating that copy of the .NET SDK from then on. + +> [!NOTE] +The .NET SDK supports targeting down-level versions of .NET, so we recommend always updating your .NET SDK along with your Visual Studio version. + ## Lifecycle The support timeframe for the SDK typically matches that of the Visual Studio version it's included in. diff --git a/docs/core/tools/telemetry.md b/docs/core/tools/telemetry.md index b8b3fe9e1982c..121c499658901 100644 --- a/docs/core/tools/telemetry.md +++ b/docs/core/tools/telemetry.md @@ -136,6 +136,8 @@ A subset of commands sends selected options if they're used, along with their va | `--logger` | `dotnet vstest` | | `--sdk-package-version` | `dotnet migrate` | +When the SDK fails to resolve a built-in command, any command resolver that successfully resolves the command sends a hash of the command name along with the name of the command resolver type. + Except for `--verbosity` and `--sdk-package-version`, all the other values are hashed starting with .NET Core 2.1.100 SDK. ### Template engine telemetry diff --git a/docs/csharp/language-reference/keywords/get.md b/docs/csharp/language-reference/keywords/get.md index fb3e889387a27..a2bb1724e2e0a 100644 --- a/docs/csharp/language-reference/keywords/get.md +++ b/docs/csharp/language-reference/keywords/get.md @@ -10,7 +10,7 @@ helpviewer_keywords: --- # The `get` keyword -The `get` keyword defines an *accessor* method in a property or indexer that returns the property value or the indexer element. For more information, see [Properties](../../programming-guide/classes-and-structs/properties.md), [Automatically implemented Properties](../../programming-guide/classes-and-structs/automatically implemented-properties.md), and [Indexers](../../programming-guide/indexers/index.md). +The `get` keyword defines an *accessor* method in a property or indexer that returns the property value or the indexer element. For more information, see [Properties](../../programming-guide/classes-and-structs/properties.md), [Automatically implemented Properties](../../programming-guide/classes-and-structs/auto-implemented-properties.md), and [Indexers](../../programming-guide/indexers/index.md). For simple cases in which a property's `get` and `set` accessors perform no other operation than setting or retrieving a value in a private backing field, you can take advantage of the C# compiler's support for automatically implemented properties. The following example implements `Hours` as an automatically implemented property. diff --git a/docs/fundamentals/toc.yml b/docs/fundamentals/toc.yml index 2e2b40b0ea8a0..41d78e90e1aa4 100644 --- a/docs/fundamentals/toc.yml +++ b/docs/fundamentals/toc.yml @@ -445,6 +445,8 @@ items: href: ../standard/datetime/how-to-use-dateonly-timeonly.md - name: Perform arithmetic operations href: ../standard/datetime/performing-arithmetic-operations.md + - name: Use TimeProvider to write predictable code + href: ../standard/datetime/timeprovider-overview.md - name: "DateTime and DateTimeOffset support in System.Text.Json" href: ../standard/datetime/system-text-json-support.md - name: Time zones diff --git a/docs/navigate/tools-diagnostics/toc.yml b/docs/navigate/tools-diagnostics/toc.yml index 7a7ed0db9b00a..33f7ed0c9aa30 100644 --- a/docs/navigate/tools-diagnostics/toc.yml +++ b/docs/navigate/tools-diagnostics/toc.yml @@ -421,6 +421,8 @@ items: href: ../../core/diagnostics/distributed-tracing-instrumentation-walkthroughs.md - name: Collection href: ../../core/diagnostics/distributed-tracing-collection-walkthroughs.md + - name: Built-in activities + href: ../../core/diagnostics/distributed-tracing-builtin-activities.md - name: Specialized diagnostics items: - name: Overview diff --git a/docs/standard/datetime/choosing-between-datetime.md b/docs/standard/datetime/choosing-between-datetime.md index 569d5d9b2c2cc..6e9b310b33412 100644 --- a/docs/standard/datetime/choosing-between-datetime.md +++ b/docs/standard/datetime/choosing-between-datetime.md @@ -80,7 +80,7 @@ Although you could use `DateTime` while ignoring the time component, there are a For more information about `DateOnly`, see [How to use the DateOnly and TimeOnly structures](how-to-use-dateonly-timeonly.md). > [!IMPORTANT] -> `DateOnly` isn't available in .NET Framework. +> `DateOnly` isn't available for .NET Framework. ## The TimeSpan structure @@ -115,7 +115,7 @@ Prior to the `TimeOnly` type being introduced, programmers typically used either For more information about `TimeOnly`, see [How to use the DateOnly and TimeOnly structures](how-to-use-dateonly-timeonly.md). > [!IMPORTANT] -> `TimeOnly` isn't available in .NET Framework. +> `TimeOnly` isn't available for .NET Framework. ## The TimeZoneInfo class diff --git a/docs/standard/datetime/how-to-use-dateonly-timeonly.md b/docs/standard/datetime/how-to-use-dateonly-timeonly.md index cb62c12058bfa..8f1cfec99f39a 100644 --- a/docs/standard/datetime/how-to-use-dateonly-timeonly.md +++ b/docs/standard/datetime/how-to-use-dateonly-timeonly.md @@ -1,7 +1,7 @@ --- title: How to use DateOnly and TimeOnly description: Learn about the DateOnly and TimeOnly structures in .NET. -ms.date: 01/11/2023 +ms.date: 12/05/2024 dev_langs: - "csharp" - "vb" @@ -22,7 +22,7 @@ The and structures were introduced `DateOnly` and `TimeOnly` are types that represent those particular portions of a `DateTime` type. > [!IMPORTANT] -> and types aren't available in .NET Framework. +> and types aren't available for .NET Framework. ## The DateOnly structure diff --git a/docs/standard/datetime/index.md b/docs/standard/datetime/index.md index e4bcb4c7aa8c2..3a78e32677ade 100644 --- a/docs/standard/datetime/index.md +++ b/docs/standard/datetime/index.md @@ -1,7 +1,7 @@ --- description: "Learn more about: Dates, times, and time zones" title: "Dates, times, and time zones" -ms.date: 12/07/2021 +ms.date: 12/05/2024 helpviewer_keywords: - "time zone objects [.NET]" - "date and time data [.NET]" @@ -12,11 +12,9 @@ ms.assetid: 295c16e0-641b-4771-94b3-39c1ffa98c13 --- # Dates, times, and time zones -In addition to the basic structure, .NET provides the following classes that support working with time zones: - -* +.NET provides types that represent dates, times, and time zones. This article describes those types. - Use this class to work with the system's local time zone and the Coordinated Universal Time (UTC) zone. The functionality of the class is largely superseded by the class. +In addition to the basic structure, .NET provides the following classes that support working with time zones: * @@ -26,16 +24,38 @@ In addition to the basic structure, .NET provides the fol Use this structure to work with dates and times whose offset (or difference) from UTC is known. The structure combines a date and time value with that time's offset from UTC. Because of its relationship to UTC, an individual date and time value unambiguously identifies a single point in time. This makes a value more portable from one computer to another than a value. -Starting with .NET 6, the following types are available: +The following classes to support working with time: -* +* - Use this structure when working with a value that only represents a date. The date represents the entire day, from the start of the day to the end. `DateOnly` has a range of `0001-01-01` through `9999-12-31`. And, this type represents the month, day, and year combination without a specific time. If you previously used a `DateTime` type in your code to represent a date that disregarded the time, use this type in its place. For more information, see [How to use the DateOnly and TimeOnly structures](how-to-use-dateonly-timeonly.md). + Use this structure to represents a time interval, such as an elapsed amount of time or the difference between two dates. * Use this structure to represent a time without a date. The time represents the hours, minutes, and seconds of a non-specific day. `TimeOnly` has a range of `00:00:00.0000000` to `23:59:59.9999999`. This type can be used to replace `DateTime` and `TimeSpan` types in your code when you used those types to represent a time. For more information, see [How to use the DateOnly and TimeOnly structures](how-to-use-dateonly-timeonly.md). + > [!IMPORTANT] + > isn't available for .NET Framework. + +* + + This is a base class that provides an abstraction of time. A common way to check the current time is by using `DateTime.UtcNow` or `DateTimeOffset.UtcNow`. However, these types don't provide any control over what's considered "now." Why would you want to control that? Testability. For example, consider you're writing an event tracking application that provides reminders 1 day before the event. The app's logic is to check the event time every hour, and alert the user once it's 24 hours before the event. As you write your tests for the app, you would provide your own type that wraps `DateTimeOffset.UtcNow` to test this logic, but now .NET provides this abstraction class for you. + + For more information, see [What is TimeProvider](timeprovider-overview.md). + + The `TimeProvider` type is included in .NET. + + For .NET Framework and .NET Standard, `TimeProvider` is provided by the [**Microsoft.Bcl.TimeProvider** NuGet package](https://www.nuget.org/packages/Microsoft.Bcl.TimeProvider/). + +The following classes to support working with dates: + +* + + Use this structure when working with a value that only represents a date. The date represents the entire day, from the start of the day to the end. `DateOnly` has a range of `0001-01-01` through `9999-12-31`. And, this type represents the month, day, and year combination without a specific time. If you previously used a `DateTime` type in your code to represent a date that disregarded the time, use this type in its place. For more information, see [How to use the DateOnly and TimeOnly structures](how-to-use-dateonly-timeonly.md). + + > [!IMPORTANT] + > isn't available for .NET Framework. + The next section provides the information that you need to work with time zones and to create time zone-aware applications that can convert dates and times from one time zone to another. ## In this section diff --git a/docs/standard/datetime/snippets/timeprovider-overview/csharp/CalendarHelper.cs b/docs/standard/datetime/snippets/timeprovider-overview/csharp/CalendarHelper.cs new file mode 100644 index 0000000000000..8cf681196b4e7 --- /dev/null +++ b/docs/standard/datetime/snippets/timeprovider-overview/csharp/CalendarHelper.cs @@ -0,0 +1,24 @@ +namespace ExampleProject; + +// +public static class CalendarHelper +{ + static readonly DateTimeOffset MoonLandingDateTime = new(1969, 7, 20, 20, 17, 40, TimeZoneInfo.Utc.BaseUtcOffset); + + public static void SendGreeting(TimeProvider currentTime, string name) + { + DateTimeOffset localTime = currentTime.GetLocalNow(); + + Console.WriteLine($"Good morning, {name}!"); + Console.WriteLine($"The date is {localTime.Date:d} and the day is {localTime.Date.DayOfWeek}."); + + if (localTime.Date.Month == MoonLandingDateTime.Date.Month + && localTime.Date.Day == MoonLandingDateTime.Date.Day) + { + Console.WriteLine("Did you know that on this day in 1969 humans landed on the Moon?"); + } + + Console.WriteLine($"I hope you enjoy your day!"); + } +} +// diff --git a/docs/standard/datetime/snippets/timeprovider-overview/csharp/MoonLandingTimeProviderPST.cs b/docs/standard/datetime/snippets/timeprovider-overview/csharp/MoonLandingTimeProviderPST.cs new file mode 100644 index 0000000000000..9c5ad09ff18f5 --- /dev/null +++ b/docs/standard/datetime/snippets/timeprovider-overview/csharp/MoonLandingTimeProviderPST.cs @@ -0,0 +1,13 @@ +namespace ExampleProject; + +// +public class MoonLandingTimeProviderPST: TimeProvider +{ + // July 20, 1969, at 20:17:40 UTC + private readonly DateTimeOffset _specificDateTime = new(1969, 7, 20, 20, 17, 40, TimeZoneInfo.Utc.BaseUtcOffset); + + public override DateTimeOffset GetUtcNow() => _specificDateTime; + + public override TimeZoneInfo LocalTimeZone => TimeZoneInfo.FindSystemTimeZoneById("PST"); +} +// diff --git a/docs/standard/datetime/snippets/timeprovider-overview/csharp/Program.cs b/docs/standard/datetime/snippets/timeprovider-overview/csharp/Program.cs new file mode 100644 index 0000000000000..1b27b2378309f --- /dev/null +++ b/docs/standard/datetime/snippets/timeprovider-overview/csharp/Program.cs @@ -0,0 +1,62 @@ +using ExampleProject; + +Console.WriteLine(@"_./-==--======- getlocal -======--==-\._"); + +// +Console.WriteLine($"Local: {TimeProvider.System.GetLocalNow()}"); +Console.WriteLine($"Utc: {TimeProvider.System.GetUtcNow()}"); + +/* This example produces output similar to the following: + * + * Local: 12/5/2024 10:41:14 AM -08:00 + * Utc: 12/5/2024 6:41:14 PM +00:00 +*/ +// + +Console.WriteLine(@"_./-==--======- timestamp -======--==-\._"); + +// +long stampStart = TimeProvider.System.GetTimestamp(); +Console.WriteLine($"Starting timestamp: {stampStart}"); + +long stampEnd = TimeProvider.System.GetTimestamp(); +Console.WriteLine($"Ending timestamp: {stampEnd}"); + +Console.WriteLine($"Elapsed time: {TimeProvider.System.GetElapsedTime(stampStart, stampEnd)}"); +Console.WriteLine($"Nanoseconds: {TimeProvider.System.GetElapsedTime(stampStart, stampEnd).TotalNanoseconds}"); + +/* This example produces output similar to the following: + * + * Starting timestamp: 55185546133 + * Ending timestamp: 55185549929 + * Elapsed time: 00:00:00.0003796 + * Nanoseconds: 379600 +*/ +// + +Console.WriteLine(@"_./-==--======- greeting-normal -======--==-\._"); + +// +CalendarHelper.SendGreeting(TimeProvider.System, "Eric Solomon"); + +/* This example produces output similar to the following: + * + * Good morning, Eric Solomon! + * The date is 12/5/2024 and the day is Thursday. + * I hope you enjoy your day! +*/ +// + +Console.WriteLine(@"_./-==--======- greeting-moon -======--==-\._"); + +// +CalendarHelper.SendGreeting(new MoonLandingTimeProviderPST(), "Eric Solomon"); + +/* This example produces output similar to the following: + * + * Good morning, Eric Solomon! + * The date is 7/20/1969 and the day is Sunday. + * Did you know that on this day in 1969 humans landed on the Moon? + * I hope you enjoy your day! +*/ +// diff --git a/docs/standard/datetime/snippets/timeprovider-overview/csharp/myproject.csproj b/docs/standard/datetime/snippets/timeprovider-overview/csharp/myproject.csproj new file mode 100644 index 0000000000000..694035b3acd5f --- /dev/null +++ b/docs/standard/datetime/snippets/timeprovider-overview/csharp/myproject.csproj @@ -0,0 +1,10 @@ + + + + Exe + net9.0 + enable + enable + + + diff --git a/docs/standard/datetime/snippets/timeprovider-overview/vb/CalendarHelper.vb b/docs/standard/datetime/snippets/timeprovider-overview/vb/CalendarHelper.vb new file mode 100644 index 0000000000000..64403f6f3f8b3 --- /dev/null +++ b/docs/standard/datetime/snippets/timeprovider-overview/vb/CalendarHelper.vb @@ -0,0 +1,24 @@ +' +Public Module CalendarHelper + + ReadOnly MoonLandingDateTime As DateTimeOffset = #7/20/1969 20:17:40# + + Public Sub SendGreeting(currentTime As TimeProvider, name As String) + + Dim localTime As DateTimeOffset = currentTime.GetLocalNow() + + Console.WriteLine($"Good morning, {name}!") + Console.WriteLine($"The date is {localTime.Date:d} and the day is {localTime.Date.DayOfWeek}.") + + If (localTime.Date.Month = MoonLandingDateTime.Date.Month _ + And localTime.Date.Day = MoonLandingDateTime.Date.Day) Then + + Console.WriteLine("Did you know that on this day in 1969 humans landed on the Moon?") + End If + + Console.WriteLine($"I hope you enjoy your day!") + + End Sub + +End Module +' diff --git a/docs/standard/datetime/snippets/timeprovider-overview/vb/MoonLandingTimeProviderPST.vb b/docs/standard/datetime/snippets/timeprovider-overview/vb/MoonLandingTimeProviderPST.vb new file mode 100644 index 0000000000000..b568080e5f901 --- /dev/null +++ b/docs/standard/datetime/snippets/timeprovider-overview/vb/MoonLandingTimeProviderPST.vb @@ -0,0 +1,19 @@ +' +Public Class MoonLandingTimeProviderPST + Inherits TimeProvider + + 'July 20, 1969, at 20:17:40 UTC + Private ReadOnly _specificDateTime As New DateTimeOffset(1969, 7, 20, 20, 17, 40, TimeZoneInfo.Utc.BaseUtcOffset) + + Public Overrides Function GetUtcNow() As DateTimeOffset + Return _specificDateTime + End Function + + Public Overrides ReadOnly Property LocalTimeZone As TimeZoneInfo + Get + Return TimeZoneInfo.FindSystemTimeZoneById("PST") + End Get + End Property + +End Class +' diff --git a/docs/standard/datetime/snippets/timeprovider-overview/vb/Program.vb b/docs/standard/datetime/snippets/timeprovider-overview/vb/Program.vb new file mode 100644 index 0000000000000..48e05b631b8dd --- /dev/null +++ b/docs/standard/datetime/snippets/timeprovider-overview/vb/Program.vb @@ -0,0 +1,70 @@ +Imports System +Imports System.Globalization +Imports System.Text.Json + +Module Program + Sub Main(args As String()) + Console.WriteLine("_./-==--======- getlocal -======--==-\._") + + ' + Console.WriteLine($"Local: {TimeProvider.System.GetLocalNow()}") + Console.WriteLine($"Utc: {TimeProvider.System.GetUtcNow()}") + + ' This example produces output similar to the following + ' + ' Local: 12/5/2024 10:41:14 AM -08:00 + ' Utc: 12/5/2024 6:41:14 PM +00:00 + + ' + + Console.WriteLine("_./-==--======- timestamp -======--==-\._") + + ' + Dim stampStart As Long = TimeProvider.System.GetTimestamp() + Console.WriteLine($"Starting timestamp: {stampStart}") + + Dim stampEnd As Long = TimeProvider.System.GetTimestamp() + Console.WriteLine($"Ending timestamp: {stampEnd}") + + Console.WriteLine($"Elapsed time: {TimeProvider.System.GetElapsedTime(stampStart, stampEnd)}") + Console.WriteLine($"Nanoseconds: {TimeProvider.System.GetElapsedTime(stampStart, stampEnd).TotalNanoseconds}") + + ' This example produces output similar to the following: + ' + ' Starting timestamp: 55185546133 + ' Ending timestamp: 55185549929 + ' Elapsed time: 00:00:00.0003796 + ' Nanoseconds: 379600 + + ' + + Console.WriteLine("_./-==--======- greeting-normal -======--==-\._") + + ' + CalendarHelper.SendGreeting(TimeProvider.System, "Eric Solomon") + + ' This example produces output similar to the following: + ' + ' Good morning, Eric Solomon! + ' The date is 12/5/2024 and the day is Thursday. + ' I hope you enjoy your day! + + ' + + Console.WriteLine("_./-==--======- greeting-moon -======--==-\._") + + ' + CalendarHelper.SendGreeting(New MoonLandingTimeProviderPST(), "Eric Solomon") + + ' This example produces output similar to the following: + ' + ' Good morning, Eric Solomon! + ' The date is 7/20/1969 and the day is Sunday. + ' Did you know that on this day in 1969 humans landed on the Moon? + ' I hope you enjoy your day! + + ' + + End Sub + +End Module diff --git a/docs/standard/datetime/snippets/timeprovider-overview/vb/myproject.vbproj b/docs/standard/datetime/snippets/timeprovider-overview/vb/myproject.vbproj new file mode 100644 index 0000000000000..cacdff353fc16 --- /dev/null +++ b/docs/standard/datetime/snippets/timeprovider-overview/vb/myproject.vbproj @@ -0,0 +1,9 @@ + + + + Exe + ExampleProject + net9.0 + + + diff --git a/docs/standard/datetime/timeprovider-overview.md b/docs/standard/datetime/timeprovider-overview.md new file mode 100644 index 0000000000000..c105d1a2bdec0 --- /dev/null +++ b/docs/standard/datetime/timeprovider-overview.md @@ -0,0 +1,102 @@ +--- +title: What is the TimeProvider class +description: Learn about the TimeProvider class in .NET and .NET Framework. TimeProvider provides an abstraction over time. +ms.date: 12/03/2024 +ms.topic: overview +dev_langs: + - "csharp" + - "vb" +helpviewer_keywords: + - "TimeProvider class" + - "date and time classes [.NET]" +#customer intent: As a developer, I want to understand what TimeProvider is so that I can use it. +--- + +# What is TimeProvider? + + is an abstraction of time that provides a point in time as a type. By using `TimeProvider`, you ensure that your code is testable and predictable. `TimeProvider` was introduced in .NET 8 and is also available for .NET Framework 4.7+ and .NET Standard 2.0 as a NuGet package. + +The class defines the following capabilities: + +- Provides access to the date and time through and . +- High-frequency timestamps with . +- Measure time between two timestamps with . +- High-resolution timers with . +- Get the current timezone with . + +## Default implementation + +.NET provides an implementation of through the property, with the following characteristics: + +- Date and time are calculated with and . +- Timestamps are provided by . +- Timers are implemented through an internal class and exposed as . + +The following example demonstrates using to get the current date and time: + +:::code language="csharp" source="./snippets/timeprovider-overview/csharp/Program.cs" id="GetLocal"::: +:::code language="vb" source="./snippets/timeprovider-overview/vb/Program.vb" id="GetLocal"::: + +The following example demonstrates capturing elapsed time with : + +:::code language="csharp" source="./snippets/timeprovider-overview/csharp/Program.cs" id="Timestamp"::: +:::code language="vb" source="./snippets/timeprovider-overview/vb/Program.vb" id="Timestamp"::: + +## FakeTimeProvider implementation + +The [**Microsoft.Extensions.TimeProvider.Testing** NuGet package](https://www.nuget.org/packages/Microsoft.Extensions.TimeProvider.Testing/) provides a controllable `TimeProvider` implementation designed for unit testing. + +The following list describes some of the capabilities of the class: + +- Set a specific date and time. +- Automatically advance the date and time by a specified amount whenever the date and time is read. +- Manually advance the date and time. + +## Custom implementation + +While [FakeTimeProvider](#faketimeprovider-implementation) should cover most scenarios requiring predictability with time, you can still provide your own implementation. Create a new class that derives from and override members to control how time is provided. For example, the following class only provides a single date, the date of the moon landing: + +:::code language="csharp" source="./snippets/timeprovider-overview/csharp/MoonLandingTimeProviderPST.cs" id="CustomProvider"::: +:::code language="vb" source="./snippets/timeprovider-overview/vb/MoonLandingTimeProviderPST.vb" id="CustomProvider"::: + +If code using this class calls `MoonLandingTimeProviderPST.GetUtcNow`, the date of the moon landing in UTC is returned. If `MoonLandingTimeProviderPST.GetLocalNow` is called, the base class applies `MoonLandingTimeProviderPST.LocalTimeZone` to `GetUtcNow` and returns the moon landing date and time in the PST timezone. + +To demonstrate the usefulness of controlling time, consider the following example. Let's say that you're writing a calendar app that sends a greeting to the user when the app is first opened each day. The app says a special greeting when the current day has an event associated with it, such as the anniversary of the moon landing. + +:::code language="csharp" source="./snippets/timeprovider-overview/csharp/CalendarHelper.cs" id="CalendarHelper"::: +:::code language="vb" source="./snippets/timeprovider-overview/vb/CalendarHelper.vb" id="CalendarHelper"::: + +You might be inclined to write the previous code with or to get the current date and time, instead of . But with unit testing, it's hard to work around or directly. You would need to either run the tests on the day and month of the moon landing or further abstract the code into smaller but testable units. + +The normal operation of your app uses `TimeProvider.System` to retrieve the current date and time: + +:::code language="csharp" source="./snippets/timeprovider-overview/csharp/Program.cs" id="GreetingNormal"::: +:::code language="vb" source="./snippets/timeprovider-overview/vb/Program.vb" id="GreetingNormal"::: + +And unit tests can be written to test specific scenarios, such as testing the anniversary of the moon landing: + +:::code language="csharp" source="./snippets/timeprovider-overview/csharp/Program.cs" id="GreetingMoon"::: +:::code language="vb" source="./snippets/timeprovider-overview/vb/Program.vb" id="GreetingMoon"::: + +## Use with .NET + +Starting with .NET 8, the class is provided by the runtime library. Older versions of .NET or libraries targeting .NET Standard 2.0, must reference the [**Microsoft.Bcl.TimeProvider** NuGet package](https://www.nuget.org/packages/Microsoft.Bcl.TimeProvider/). + +The following methods related to asynchronous programming work with `TimeProvider`: + +- +- +- +- +- + +## Use with .NET Framework + + is implemented by the [**Microsoft.Bcl.TimeProvider** NuGet package](https://www.nuget.org/packages/Microsoft.Bcl.TimeProvider/). + +Support for working with `TimeProvider` in asynchronous programming scenarios was added through the following extension methods: + +- +- +- +-