From b5490359730b4a3402bf34de29b1d4de71dc35b8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Aug 2026 20:10:46 +0000 Subject: [PATCH 01/11] Initial plan From 1769eb009f05a87aa08e2db34b8187c14a09d868 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Aug 2026 20:12:07 +0000 Subject: [PATCH 02/11] Add using directives snippet marker Co-authored-by: adegeo <67293991+adegeo@users.noreply.github.com> --- docs/core/diagnostics/snippets/OTLP-Example/csharp/Program.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/core/diagnostics/snippets/OTLP-Example/csharp/Program.cs b/docs/core/diagnostics/snippets/OTLP-Example/csharp/Program.cs index d86c239f4cb6e..50acab56a712f 100644 --- a/docs/core/diagnostics/snippets/OTLP-Example/csharp/Program.cs +++ b/docs/core/diagnostics/snippets/OTLP-Example/csharp/Program.cs @@ -1,4 +1,5 @@ // +// using System.Diagnostics; using System.Diagnostics.Metrics; using OpenTelemetry.Metrics; @@ -8,6 +9,7 @@ using OpenTelemetry.Logs; using OpenTelemetry; using Azure.Monitor.OpenTelemetry.AspNetCore; +// var builder = WebApplication.CreateBuilder(args); From fc5b196d9489c2d4fb55cff2c1dd420d1d184ba4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Aug 2026 20:13:30 +0000 Subject: [PATCH 03/11] Reorder OTLP article steps, add using directives step, update package versions and port guidance Co-authored-by: adegeo <67293991+adegeo@users.noreply.github.com> --- .../diagnostics/observability-otlp-example.md | 67 +++++++++++-------- 1 file changed, 40 insertions(+), 27 deletions(-) diff --git a/docs/core/diagnostics/observability-otlp-example.md b/docs/core/diagnostics/observability-otlp-example.md index 7c3e727533e92..abbe0602bc40e 100644 --- a/docs/core/diagnostics/observability-otlp-example.md +++ b/docs/core/diagnostics/observability-otlp-example.md @@ -1,7 +1,7 @@ --- title: "Example: Use OpenTelemetry with OTLP and the standalone Aspire Dashboard" description: An introduction to observing .NET apps with OTLP and the standalone Aspire Dashboard -ms.date: 6/14/2023 +ms.date: 08/20/2026 ms.topic: how-to ms.custom: sfi-image-nochange --- @@ -22,24 +22,17 @@ Create a simple web API project by using the **ASP.NET Core Empty** template in dotnet new web ``` -## 2. Add metrics and activity definitions +## 2. Add using directives -The following code defines a new metric (`greetings.count`) for the number of times the API has been called, and a new activity source (`Otel.Example`). +Add the following `using` directives to the top of the file: -:::code language="csharp" source="snippets/OTLP-Example/csharp/Program.cs" id="Snippet_CustomMetrics"::: - -## 3. Create an API endpoint - -Insert the following code between `builder.Build();` and `app.Run()` +:::code language="csharp" source="snippets/OTLP-Example/csharp/Program.cs" id="Snippet_Usings"::: -:::code language="csharp" source="snippets/OTLP-Example/csharp/Program.cs" id="Snippet_MapGet"::: - -Insert the following function at the bottom of the file: +## 3. Add metrics and activity definitions -:::code language="csharp" source="snippets/OTLP-Example/csharp/Program.cs" id="Snippet_SendGreeting"::: +The following code defines a new metric (`greetings.count`) for the number of times the API has been called, and a new activity source (`Otel.Example`). Insert this code before `builder.Build();`: -> [!NOTE] -> The endpoint definition doesn't use anything specific to OpenTelemetry. It uses the .NET APIs for observability. +:::code language="csharp" source="snippets/OTLP-Example/csharp/Program.cs" id="Snippet_CustomMetrics"::: ## 4. Reference the OpenTelemetry packages @@ -47,10 +40,10 @@ Use the NuGet Package Manager or command line to add the following NuGet package ``` xml - - - - + + + + ``` @@ -59,7 +52,7 @@ Use the NuGet Package Manager or command line to add the following NuGet package ## 5. Configure OpenTelemetry with the correct providers -Insert the following code before `builder.Build();`: +Insert the following code before `builder.Build();`, after the code added in [step 3](#3-add-metrics-and-activity-definitions): :::code language="csharp" source="snippets/OTLP-Example/csharp/Program.cs" id="Snippet_OTEL"::: @@ -85,7 +78,20 @@ You can add additional environment variables for the [.NET OTLP Exporter](https: > [!NOTE] > A common gotcha is to mix up _AppSettings.json_ and _AppSettings.Development.json_. If the latter is present, it will be used when you F5 from Visual Studio, and any settings in _AppSettings.json_ will be ignored. -## 7. Start the Aspire Dashboard container +## 7. Create an API endpoint + +Insert the following code between `builder.Build();` and `app.Run()`: + +:::code language="csharp" source="snippets/OTLP-Example/csharp/Program.cs" id="Snippet_MapGet"::: + +Insert the following function at the bottom of the file: + +:::code language="csharp" source="snippets/OTLP-Example/csharp/Program.cs" id="Snippet_SendGreeting"::: + +> [!NOTE] +> The endpoint definition doesn't use anything specific to OpenTelemetry. It uses the .NET APIs for observability. + +## 8. Start the Aspire Dashboard container Use `docker` to download and run the dashboard container. @@ -103,17 +109,24 @@ Data displayed in the dashboard can be sensitive. By default, the dashboard is s Copy the URL shown, and replace `0.0.0.0` with `localhost`, for example, `http://localhost:18888/login?t=123456780abcdef123456780`, and open that in your browser. Or you can also paste the key after `/login?t=` when the login dialog is shown. The token changes each time you start the container. -## 8. Run the project +## 9. Run the project + +Run the project with `dotnet run`. The console output displays the URLs that the app is listening on, for example: + +``` output +info: Microsoft.Hosting.Lifetime[14] + Now listening on: http://localhost:5086 +``` -Run the project and then access the API with the browser or curl. +Use the port shown in your own console output, as it can differ from the examples in this article. Access the API with the browser or curl, using that port: ``` dotnetcli -curl -k http://localhost:7275 +curl -k http://localhost:5086 ``` Each time you request the page, it increments the count for the number of greetings that have been made. -### 8.1 Log output +### 9.1 Log output The logging statements from the code are output using `ILogger`. By default, the [Console Provider](../extensions/logging/overview.md?tabs=command-line#configure-logging) is enabled so that output is directed to the console. @@ -127,7 +140,7 @@ The logs are shown in the dashboard as structured logs - any properties you set [![Logs in standalone dashboard](./media/aspire-dashboard-logs-thumb.png)](./media/aspire-dashboard-logs.png#lightbox) -### 8.2 Viewing the metrics +### 9.2 Viewing the metrics The Aspire dashboard shows metrics on a per resource basis (a resource being the OTel way of talking about sources of telemetry such as a process). When a resource is selected, the dashboard enumerates each metric that has been sent to its OTLP endpoint by the resource. The list of metrics is dynamic, and is updated as new metrics are received. @@ -139,7 +152,7 @@ The view for the metrics depends on the type of metric that's being used: - Histograms that track a value per request, such as a timespan or bytes sent per request, are collected into a series of buckets. The dashboard graphs the P50, P90, and P99 percentiles. Histogram results can include exemplars, which are individual datapoints together with the trace/spanId for that request. These are shown as dots on the graph. Selecting one navigates to the respective trace so you can see what happened to cause that value. This is useful for diagnosing outliers. - Metrics can include dimensions, which are key/value pairs associated with individual values. The values are aggregated per dimension. Using the dropdowns in the view, you can filter the results to look at specific dimensions, such as only `GET` requests, or those for a specific URL route in ASP.NET. -### 8.3 Viewing the tracing +### 9.3 Viewing the tracing The tracing view shows a list of traces. Each trace is a set of activities that share the same traceId. Work is tracked with spans, which represent a unit of work. Processing an ASP.NET request creates a span. Making an HttpClient request is a span. By tracking the span's parent, a hierarchy of spans can be visualized. By collecting spans from each resource (process), you can track the work that happens across a series of services. HTTP requests have a header that's used to pass the traceId and parent spanId to the next service. Each resource needs to collect telemetry and send it to the same collector. It will then aggregate and present a hierarchy of the spans. @@ -149,4 +162,4 @@ The dashboard shows a list of traces with summary information. Whenever spans wi [![Spans in standalone dashboard](./media/aspire-dashboard-spans-thumb.png)](./media/aspire-dashboard-spans.png#lightbox) -Selecting a span shows its details including any properties on the span, such as the `greeting` tag that you set in [step 3](#3-create-an-api-endpoint). +Selecting a span shows its details including any properties on the span, such as the `greeting` tag that you set in [step 7](#7-create-an-api-endpoint). From 7b7c82812064cb1302dd423bf72b2c3047b951be Mon Sep 17 00:00:00 2001 From: "Andy De George (from Dev Box)" Date: Thu, 20 Aug 2026 15:52:28 -0700 Subject: [PATCH 04/11] Give observability-otlp-example its own snippet project The Program.cs under snippets/OTLP-Example/csharp is shared with observability-applicationinsights.md, so editing it for this article risked breaking that unrelated article. Create a dedicated snippets/observability-otlp-example/csharp project (via dotnet new web) with its own Program.cs, NuGet package references, and snippet region markers, and point this article's code references at it. Revert the Snippet_Usings markers that had been added to the shared file. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../diagnostics/observability-otlp-example.md | 10 +- .../snippets/OTLP-Example/csharp/Program.cs | 2 - .../csharp/Program.cs | 93 +++++++++++++++++++ .../csharp/Properties/launchSettings.json | 23 +++++ .../csharp/appsettings.Development.json | 8 ++ .../csharp/appsettings.json | 9 ++ .../csharp/observability-otlp-example.csproj | 16 ++++ 7 files changed, 154 insertions(+), 7 deletions(-) create mode 100644 docs/core/diagnostics/snippets/observability-otlp-example/csharp/Program.cs create mode 100644 docs/core/diagnostics/snippets/observability-otlp-example/csharp/Properties/launchSettings.json create mode 100644 docs/core/diagnostics/snippets/observability-otlp-example/csharp/appsettings.Development.json create mode 100644 docs/core/diagnostics/snippets/observability-otlp-example/csharp/appsettings.json create mode 100644 docs/core/diagnostics/snippets/observability-otlp-example/csharp/observability-otlp-example.csproj diff --git a/docs/core/diagnostics/observability-otlp-example.md b/docs/core/diagnostics/observability-otlp-example.md index abbe0602bc40e..341b5d25b686c 100644 --- a/docs/core/diagnostics/observability-otlp-example.md +++ b/docs/core/diagnostics/observability-otlp-example.md @@ -26,13 +26,13 @@ dotnet new web Add the following `using` directives to the top of the file: -:::code language="csharp" source="snippets/OTLP-Example/csharp/Program.cs" id="Snippet_Usings"::: +:::code language="csharp" source="snippets/observability-otlp-example/csharp/Program.cs" id="Snippet_Usings"::: ## 3. Add metrics and activity definitions The following code defines a new metric (`greetings.count`) for the number of times the API has been called, and a new activity source (`Otel.Example`). Insert this code before `builder.Build();`: -:::code language="csharp" source="snippets/OTLP-Example/csharp/Program.cs" id="Snippet_CustomMetrics"::: +:::code language="csharp" source="snippets/observability-otlp-example/csharp/Program.cs" id="Snippet_CustomMetrics"::: ## 4. Reference the OpenTelemetry packages @@ -54,7 +54,7 @@ Use the NuGet Package Manager or command line to add the following NuGet package Insert the following code before `builder.Build();`, after the code added in [step 3](#3-add-metrics-and-activity-definitions): -:::code language="csharp" source="snippets/OTLP-Example/csharp/Program.cs" id="Snippet_OTEL"::: +:::code language="csharp" source="snippets/observability-otlp-example/csharp/Program.cs" id="Snippet_OTEL"::: This code sets up OpenTelemetry with the different sources of telemetry: @@ -82,11 +82,11 @@ You can add additional environment variables for the [.NET OTLP Exporter](https: Insert the following code between `builder.Build();` and `app.Run()`: -:::code language="csharp" source="snippets/OTLP-Example/csharp/Program.cs" id="Snippet_MapGet"::: +:::code language="csharp" source="snippets/observability-otlp-example/csharp/Program.cs" id="Snippet_MapGet"::: Insert the following function at the bottom of the file: -:::code language="csharp" source="snippets/OTLP-Example/csharp/Program.cs" id="Snippet_SendGreeting"::: +:::code language="csharp" source="snippets/observability-otlp-example/csharp/Program.cs" id="Snippet_SendGreeting"::: > [!NOTE] > The endpoint definition doesn't use anything specific to OpenTelemetry. It uses the .NET APIs for observability. diff --git a/docs/core/diagnostics/snippets/OTLP-Example/csharp/Program.cs b/docs/core/diagnostics/snippets/OTLP-Example/csharp/Program.cs index 50acab56a712f..d86c239f4cb6e 100644 --- a/docs/core/diagnostics/snippets/OTLP-Example/csharp/Program.cs +++ b/docs/core/diagnostics/snippets/OTLP-Example/csharp/Program.cs @@ -1,5 +1,4 @@ // -// using System.Diagnostics; using System.Diagnostics.Metrics; using OpenTelemetry.Metrics; @@ -9,7 +8,6 @@ using OpenTelemetry.Logs; using OpenTelemetry; using Azure.Monitor.OpenTelemetry.AspNetCore; -// var builder = WebApplication.CreateBuilder(args); diff --git a/docs/core/diagnostics/snippets/observability-otlp-example/csharp/Program.cs b/docs/core/diagnostics/snippets/observability-otlp-example/csharp/Program.cs new file mode 100644 index 0000000000000..8efe247018e1f --- /dev/null +++ b/docs/core/diagnostics/snippets/observability-otlp-example/csharp/Program.cs @@ -0,0 +1,93 @@ +// +using System.Diagnostics; +using System.Diagnostics.Metrics; +using OpenTelemetry.Exporter; +using OpenTelemetry.Logs; +using OpenTelemetry.Metrics; +using OpenTelemetry.Resources; +using OpenTelemetry.Trace; +// + +// +// Custom metrics for the application +var greeterMeter = new Meter("OTel.Example", "1.0.0"); +var countGreetings = greeterMeter.CreateCounter("greetings.count", description: "Counts the number of greetings"); + +// Custom ActivitySource for the application +var greeterActivitySource = new ActivitySource("OTel.Example"); +// + +var builder = WebApplication.CreateBuilder(args); + +// +// Configure the shared OTLP connection used by logs, metrics, and traces. +var otlpEndpoint = new Uri(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]!); +Action configureOtlp = options => +{ + options.Endpoint = otlpEndpoint; + options.Protocol = OtlpExportProtocol.Grpc; + options.Headers = builder.Configuration["OTEL_EXPORTER_OTLP_HEADERS"]; // To secure endpoint (not in this example) +}; + +// Setup logging to be exported via OpenTelemetry +builder.Logging.AddOpenTelemetry(logging => +{ + logging.IncludeFormattedMessage = true; + logging.IncludeScopes = true; + logging.AddOtlpExporter(configureOtlp); +}); + +var otel = builder.Services.AddOpenTelemetry(); + +// Identify this application as a single service in the Aspire dashboard. +otel.ConfigureResource(resource => resource.AddService(builder.Configuration["OTEL_SERVICE_NAME"]!)); + +// Add Metrics for ASP.NET Core and our custom metrics and export via OTLP +otel.WithMetrics(metrics => +{ + // Metrics provider from OpenTelemetry + metrics.AddAspNetCoreInstrumentation(); + //Our custom metrics + metrics.AddMeter(greeterMeter.Name); + // Metrics provides by ASP.NET Core in .NET + metrics.AddMeter("Microsoft.AspNetCore.Hosting"); + metrics.AddMeter("Microsoft.AspNetCore.Server.Kestrel"); + metrics.AddOtlpExporter(configureOtlp); +}); + +// Add Tracing for ASP.NET Core and our custom ActivitySource and export via OTLP +otel.WithTracing(tracing => +{ + tracing.AddAspNetCoreInstrumentation(); + tracing.AddHttpClientInstrumentation(); + tracing.AddSource(greeterActivitySource.Name); + tracing.AddOtlpExporter(configureOtlp); +}); +// + +var app = builder.Build(); + +// +app.MapGet("/", SendGreeting); +// + +app.Run(); + +// +async Task SendGreeting(ILogger logger) +{ + // Create a new Activity scoped to the method + using var activity = greeterActivitySource.StartActivity("GreeterActivity"); + + // Log a message + logger.LogInformation("Sending greeting"); + + // Increment the custom counter + countGreetings.Add(1); + + // Add a tag to the Activity + activity?.SetTag("greeting", "Hello World!"); + + return "Hello World!"; +} +// diff --git a/docs/core/diagnostics/snippets/observability-otlp-example/csharp/Properties/launchSettings.json b/docs/core/diagnostics/snippets/observability-otlp-example/csharp/Properties/launchSettings.json new file mode 100644 index 0000000000000..a5ccafe0eff32 --- /dev/null +++ b/docs/core/diagnostics/snippets/observability-otlp-example/csharp/Properties/launchSettings.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "http://localhost:5245", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "https://localhost:7147;http://localhost:5245", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/docs/core/diagnostics/snippets/observability-otlp-example/csharp/appsettings.Development.json b/docs/core/diagnostics/snippets/observability-otlp-example/csharp/appsettings.Development.json new file mode 100644 index 0000000000000..0c208ae9181e5 --- /dev/null +++ b/docs/core/diagnostics/snippets/observability-otlp-example/csharp/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/docs/core/diagnostics/snippets/observability-otlp-example/csharp/appsettings.json b/docs/core/diagnostics/snippets/observability-otlp-example/csharp/appsettings.json new file mode 100644 index 0000000000000..10f68b8c8b4f7 --- /dev/null +++ b/docs/core/diagnostics/snippets/observability-otlp-example/csharp/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/docs/core/diagnostics/snippets/observability-otlp-example/csharp/observability-otlp-example.csproj b/docs/core/diagnostics/snippets/observability-otlp-example/csharp/observability-otlp-example.csproj new file mode 100644 index 0000000000000..3af5e4e1f10a3 --- /dev/null +++ b/docs/core/diagnostics/snippets/observability-otlp-example/csharp/observability-otlp-example.csproj @@ -0,0 +1,16 @@ + + + + net10.0 + enable + enable + + + + + + + + + + From f9a9f77b00106bca27e5debae9496f815697b40c Mon Sep 17 00:00:00 2001 From: "Andy De George (from Dev Box)" Date: Thu, 20 Aug 2026 15:53:39 -0700 Subject: [PATCH 05/11] Add OTLP env vars to appsettings.Development.json Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../csharp/appsettings.Development.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/core/diagnostics/snippets/observability-otlp-example/csharp/appsettings.Development.json b/docs/core/diagnostics/snippets/observability-otlp-example/csharp/appsettings.Development.json index 0c208ae9181e5..10ed8ec34d916 100644 --- a/docs/core/diagnostics/snippets/observability-otlp-example/csharp/appsettings.Development.json +++ b/docs/core/diagnostics/snippets/observability-otlp-example/csharp/appsettings.Development.json @@ -4,5 +4,7 @@ "Default": "Information", "Microsoft.AspNetCore": "Warning" } - } + }, + "OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4317", + "OTEL_SERVICE_NAME": "OTLP-Example" } From d6aa2851be2eefb314a1d0c6728562363a536e93 Mon Sep 17 00:00:00 2001 From: "Andy De George (from Dev Box)" Date: Thu, 20 Aug 2026 15:56:15 -0700 Subject: [PATCH 06/11] Drop Snippet_ prefix from snippet IDs Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../diagnostics/observability-otlp-example.md | 10 +++++----- .../csharp/Program.cs | 20 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/core/diagnostics/observability-otlp-example.md b/docs/core/diagnostics/observability-otlp-example.md index 341b5d25b686c..da0fdc7ace3f2 100644 --- a/docs/core/diagnostics/observability-otlp-example.md +++ b/docs/core/diagnostics/observability-otlp-example.md @@ -26,13 +26,13 @@ dotnet new web Add the following `using` directives to the top of the file: -:::code language="csharp" source="snippets/observability-otlp-example/csharp/Program.cs" id="Snippet_Usings"::: +:::code language="csharp" source="snippets/observability-otlp-example/csharp/Program.cs" id="Usings"::: ## 3. Add metrics and activity definitions The following code defines a new metric (`greetings.count`) for the number of times the API has been called, and a new activity source (`Otel.Example`). Insert this code before `builder.Build();`: -:::code language="csharp" source="snippets/observability-otlp-example/csharp/Program.cs" id="Snippet_CustomMetrics"::: +:::code language="csharp" source="snippets/observability-otlp-example/csharp/Program.cs" id="CustomMetrics"::: ## 4. Reference the OpenTelemetry packages @@ -54,7 +54,7 @@ Use the NuGet Package Manager or command line to add the following NuGet package Insert the following code before `builder.Build();`, after the code added in [step 3](#3-add-metrics-and-activity-definitions): -:::code language="csharp" source="snippets/observability-otlp-example/csharp/Program.cs" id="Snippet_OTEL"::: +:::code language="csharp" source="snippets/observability-otlp-example/csharp/Program.cs" id="OTEL"::: This code sets up OpenTelemetry with the different sources of telemetry: @@ -82,11 +82,11 @@ You can add additional environment variables for the [.NET OTLP Exporter](https: Insert the following code between `builder.Build();` and `app.Run()`: -:::code language="csharp" source="snippets/observability-otlp-example/csharp/Program.cs" id="Snippet_MapGet"::: +:::code language="csharp" source="snippets/observability-otlp-example/csharp/Program.cs" id="MapGet"::: Insert the following function at the bottom of the file: -:::code language="csharp" source="snippets/observability-otlp-example/csharp/Program.cs" id="Snippet_SendGreeting"::: +:::code language="csharp" source="snippets/observability-otlp-example/csharp/Program.cs" id="SendGreeting"::: > [!NOTE] > The endpoint definition doesn't use anything specific to OpenTelemetry. It uses the .NET APIs for observability. diff --git a/docs/core/diagnostics/snippets/observability-otlp-example/csharp/Program.cs b/docs/core/diagnostics/snippets/observability-otlp-example/csharp/Program.cs index 8efe247018e1f..da7e5ea6c94c8 100644 --- a/docs/core/diagnostics/snippets/observability-otlp-example/csharp/Program.cs +++ b/docs/core/diagnostics/snippets/observability-otlp-example/csharp/Program.cs @@ -1,4 +1,4 @@ -// +// using System.Diagnostics; using System.Diagnostics.Metrics; using OpenTelemetry.Exporter; @@ -6,20 +6,20 @@ using OpenTelemetry.Metrics; using OpenTelemetry.Resources; using OpenTelemetry.Trace; -// +// -// +// // Custom metrics for the application var greeterMeter = new Meter("OTel.Example", "1.0.0"); var countGreetings = greeterMeter.CreateCounter("greetings.count", description: "Counts the number of greetings"); // Custom ActivitySource for the application var greeterActivitySource = new ActivitySource("OTel.Example"); -// +// var builder = WebApplication.CreateBuilder(args); -// +// // Configure the shared OTLP connection used by logs, metrics, and traces. var otlpEndpoint = new Uri(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]!); Action configureOtlp = options => @@ -63,17 +63,17 @@ tracing.AddSource(greeterActivitySource.Name); tracing.AddOtlpExporter(configureOtlp); }); -// +// var app = builder.Build(); -// +// app.MapGet("/", SendGreeting); -// +// app.Run(); -// +// async Task SendGreeting(ILogger logger) { // Create a new Activity scoped to the method @@ -90,4 +90,4 @@ async Task SendGreeting(ILogger logger) return "Hello World!"; } -// +// From 3b8d5709db3adbe77c99e62f92302da3dbfdbd9b Mon Sep 17 00:00:00 2001 From: "Andy De George (from Dev Box)" Date: Thu, 20 Aug 2026 15:58:58 -0700 Subject: [PATCH 07/11] Use a snippet for the OTel PackageReferences and add dotnet add package commands Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../diagnostics/observability-otlp-example.md | 20 ++++++++++--------- .../csharp/observability-otlp-example.csproj | 2 ++ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/docs/core/diagnostics/observability-otlp-example.md b/docs/core/diagnostics/observability-otlp-example.md index da0fdc7ace3f2..0727059fe1510 100644 --- a/docs/core/diagnostics/observability-otlp-example.md +++ b/docs/core/diagnostics/observability-otlp-example.md @@ -36,17 +36,19 @@ The following code defines a new metric (`greetings.count`) for the number of ti ## 4. Reference the OpenTelemetry packages -Use the NuGet Package Manager or command line to add the following NuGet packages: - -``` xml - - - - - - +Use the NuGet Package Manager, or the following `dotnet add package` commands, to add the OpenTelemetry packages: + +``` dotnetcli +dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol +dotnet add package OpenTelemetry.Extensions.Hosting +dotnet add package OpenTelemetry.Instrumentation.AspNetCore +dotnet add package OpenTelemetry.Instrumentation.Http ``` +Alternatively, add the following `PackageReference` items directly to the project file: + +:::code language="xml" source="snippets/observability-otlp-example/csharp/observability-otlp-example.csproj" id="PackageReferences"::: + > [!NOTE] > Use the latest versions, as the OTel APIs are constantly evolving. diff --git a/docs/core/diagnostics/snippets/observability-otlp-example/csharp/observability-otlp-example.csproj b/docs/core/diagnostics/snippets/observability-otlp-example/csharp/observability-otlp-example.csproj index 3af5e4e1f10a3..e25e8b40ae1f8 100644 --- a/docs/core/diagnostics/snippets/observability-otlp-example/csharp/observability-otlp-example.csproj +++ b/docs/core/diagnostics/snippets/observability-otlp-example/csharp/observability-otlp-example.csproj @@ -6,11 +6,13 @@ enable + + From 4a35c0babd4862bc9a9c7f42f3acb7a00de432a9 Mon Sep 17 00:00:00 2001 From: "Andy De George (from Dev Box)" Date: Thu, 20 Aug 2026 16:12:21 -0700 Subject: [PATCH 08/11] Reorder steps, tidy punctuation and comments - Move the NuGet package reference step right after project creation - Drop the trailing (); when referencing builder.Build in prose - Simplify the OTEL configuration step intro instead of linking back - Fix a comment typo and add spacing/comment in the metrics setup Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../diagnostics/observability-otlp-example.md | 30 +++++++++---------- .../csharp/Program.cs | 8 +++-- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/docs/core/diagnostics/observability-otlp-example.md b/docs/core/diagnostics/observability-otlp-example.md index 0727059fe1510..d2ce0e2e9eb86 100644 --- a/docs/core/diagnostics/observability-otlp-example.md +++ b/docs/core/diagnostics/observability-otlp-example.md @@ -22,19 +22,7 @@ Create a simple web API project by using the **ASP.NET Core Empty** template in dotnet new web ``` -## 2. Add using directives - -Add the following `using` directives to the top of the file: - -:::code language="csharp" source="snippets/observability-otlp-example/csharp/Program.cs" id="Usings"::: - -## 3. Add metrics and activity definitions - -The following code defines a new metric (`greetings.count`) for the number of times the API has been called, and a new activity source (`Otel.Example`). Insert this code before `builder.Build();`: - -:::code language="csharp" source="snippets/observability-otlp-example/csharp/Program.cs" id="CustomMetrics"::: - -## 4. Reference the OpenTelemetry packages +## 2. Reference the OpenTelemetry packages Use the NuGet Package Manager, or the following `dotnet add package` commands, to add the OpenTelemetry packages: @@ -52,9 +40,21 @@ Alternatively, add the following `PackageReference` items directly to the projec > [!NOTE] > Use the latest versions, as the OTel APIs are constantly evolving. +## 3. Add using directives + +Add the following `using` directives to the top of the file: + +:::code language="csharp" source="snippets/observability-otlp-example/csharp/Program.cs" id="Usings"::: + +## 4. Add metrics and activity definitions + +The following code defines a new metric (`greetings.count`) for the number of times the API has been called, and a new activity source (`Otel.Example`). Insert this code before `builder.Build`: + +:::code language="csharp" source="snippets/observability-otlp-example/csharp/Program.cs" id="CustomMetrics"::: + ## 5. Configure OpenTelemetry with the correct providers -Insert the following code before `builder.Build();`, after the code added in [step 3](#3-add-metrics-and-activity-definitions): +Insert the following code before `builder.Build`: :::code language="csharp" source="snippets/observability-otlp-example/csharp/Program.cs" id="OTEL"::: @@ -82,7 +82,7 @@ You can add additional environment variables for the [.NET OTLP Exporter](https: ## 7. Create an API endpoint -Insert the following code between `builder.Build();` and `app.Run()`: +Insert the following code between `builder.Build` and `app.Run()`: :::code language="csharp" source="snippets/observability-otlp-example/csharp/Program.cs" id="MapGet"::: diff --git a/docs/core/diagnostics/snippets/observability-otlp-example/csharp/Program.cs b/docs/core/diagnostics/snippets/observability-otlp-example/csharp/Program.cs index da7e5ea6c94c8..92222e2799faf 100644 --- a/docs/core/diagnostics/snippets/observability-otlp-example/csharp/Program.cs +++ b/docs/core/diagnostics/snippets/observability-otlp-example/csharp/Program.cs @@ -47,11 +47,15 @@ { // Metrics provider from OpenTelemetry metrics.AddAspNetCoreInstrumentation(); - //Our custom metrics + + // Our custom metrics metrics.AddMeter(greeterMeter.Name); - // Metrics provides by ASP.NET Core in .NET + + // Metrics provided by ASP.NET Core in .NET metrics.AddMeter("Microsoft.AspNetCore.Hosting"); metrics.AddMeter("Microsoft.AspNetCore.Server.Kestrel"); + + // Export the metrics via OTLP metrics.AddOtlpExporter(configureOtlp); }); From 876a9a1fb589ff4bb87d4bea091c81b0bf541ca2 Mon Sep 17 00:00:00 2001 From: "Andy De George (from Dev Box)" Date: Fri, 21 Aug 2026 08:49:00 -0700 Subject: [PATCH 09/11] Edit article for Microsoft Style Guide compliance - Convert passive voice to active voice throughout - Replace weak instruction language with imperative mood - Remove first-person plural (we/our), gerund clauses, and 'there are' constructions - Fix word choice (may->might/can, as->because, additional->other, env vars->environment variables) - Format file names and identifiers as code, not italics - Rename gerund headings (Viewing the metrics/tracing -> Metrics view/Tracing view) - Add ai-usage: ai-assisted front matter Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../diagnostics/observability-otlp-example.md | 71 ++++++++++--------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/docs/core/diagnostics/observability-otlp-example.md b/docs/core/diagnostics/observability-otlp-example.md index d2ce0e2e9eb86..f738a8ab961cb 100644 --- a/docs/core/diagnostics/observability-otlp-example.md +++ b/docs/core/diagnostics/observability-otlp-example.md @@ -4,15 +4,16 @@ description: An introduction to observing .NET apps with OTLP and the standalone ms.date: 08/20/2026 ms.topic: how-to ms.custom: sfi-image-nochange +ai-usage: ai-assisted --- # Example: Use OpenTelemetry with OTLP and the standalone Aspire Dashboard -This article is one of a series of examples to illustrate [.NET observability with OpenTelemetry](./observability-with-otel.md). +This article is one of a series of examples that illustrate [.NET observability with OpenTelemetry](./observability-with-otel.md). -In addition to being a standard part of Aspire, the Aspire Dashboard is available as a [standalone Docker container](https://aspire.dev/dashboard/standalone/), which provides an OTLP endpoint that telemetry can be sent to. The dashboard visualizes the logs, metrics, and traces. Using the dashboard in this way has no dependency on Aspire, and it visualizes telemetry from any application that sends it telemetry via OTLP. It works equally well for applications written in Java, GoLang, or Python provided they can send their telemetry to an OTLP endpoint. +The Aspire Dashboard is a standard part of Aspire, but it's also available as a [standalone Docker container](https://aspire.dev/dashboard/standalone/) that provides an OTLP endpoint for sending telemetry. The dashboard visualizes logs, metrics, and traces. Using the dashboard this way has no dependency on Aspire, and it visualizes telemetry from any app that sends telemetry via OTLP. It works equally well for apps written in Java, GoLang, or Python, provided they can send their telemetry to an OTLP endpoint. -Using the Aspire Dashboard has less configuration and setup steps than using Open Source solutions such as [Prometheus, Grafana, and Jaeger](./observability-prgrja-example.md). But unlike those tools, the Aspire Dashboard is intended as a developer visualization tool, and not for production monitoring. +The Aspire Dashboard requires less configuration and fewer setup steps than open-source solutions such as [Prometheus, Grafana, and Jaeger](./observability-prgrja-example.md). But unlike those tools, the Aspire Dashboard is a developer visualization tool, not a production monitoring tool. ## 1. Create the project @@ -24,7 +25,7 @@ dotnet new web ## 2. Reference the OpenTelemetry packages -Use the NuGet Package Manager, or the following `dotnet add package` commands, to add the OpenTelemetry packages: +To add the OpenTelemetry packages, use the NuGet Package Manager, or run the following `dotnet add package` commands: ``` dotnetcli dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol @@ -38,7 +39,7 @@ Alternatively, add the following `PackageReference` items directly to the projec :::code language="xml" source="snippets/observability-otlp-example/csharp/observability-otlp-example.csproj" id="PackageReferences"::: > [!NOTE] -> Use the latest versions, as the OTel APIs are constantly evolving. +> Because the OTel APIs are constantly evolving, use the latest versions. ## 3. Add using directives @@ -48,7 +49,7 @@ Add the following `using` directives to the top of the file: ## 4. Add metrics and activity definitions -The following code defines a new metric (`greetings.count`) for the number of times the API has been called, and a new activity source (`Otel.Example`). Insert this code before `builder.Build`: +The following code defines a new metric (`greetings.count`) that counts how many times a client calls the API, and a new activity source (`Otel.Example`). Insert this code before `builder.Build`: :::code language="csharp" source="snippets/observability-otlp-example/csharp/Program.cs" id="CustomMetrics"::: @@ -60,25 +61,25 @@ Insert the following code before `builder.Build`: This code sets up OpenTelemetry with the different sources of telemetry: -- It adds a OTel provider to ILogger to collect log records. -- It sets up metrics, registering instrumentation providers and Meters for ASP.NET and our custom Meter. -- It sets up tracing, registering instrumentation providers and our custom ActivitySource. +- It adds an OTel provider to `ILogger` to collect log records. +- It sets up metrics, registering instrumentation providers and meters for ASP.NET and the custom meter. +- It sets up tracing, registering instrumentation providers and the custom `ActivitySource`. -It then registers the OTLP exporter using env vars for its configuration. +It then registers the OTLP exporter, using environment variables for its configuration. -## 6. Configure OTLP Environment variables +## 6. Configure OTLP environment variables -The OTLP exporter can be configured via APIs in code, but it's more common to configure it via environment variables. Add the following to _AppSettings.Development.json_ +You can configure the OTLP exporter through APIs in code, but environment variables are the more common approach. Add the following to `appsettings.Development.json`: ``` json "OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4317", "OTEL_SERVICE_NAME": "OTLP-Example" ``` -You can add additional environment variables for the [.NET OTLP Exporter](https://github.com/open-telemetry/opentelemetry-dotnet/tree/main/src/OpenTelemetry.Exporter.OpenTelemetryProtocol#exporter-configuration) or common OTel variables such as `OTEL_RESOURCE_ATTRIBUTES` to define [resource attributes](https://opentelemetry.io/docs/concepts/resources/). +Add other environment variables for the [.NET OTLP exporter](https://github.com/open-telemetry/opentelemetry-dotnet/tree/main/src/OpenTelemetry.Exporter.OpenTelemetryProtocol#exporter-configuration) or common OTel variables such as `OTEL_RESOURCE_ATTRIBUTES` to define [resource attributes](https://opentelemetry.io/docs/concepts/resources/). > [!NOTE] -> A common gotcha is to mix up _AppSettings.json_ and _AppSettings.Development.json_. If the latter is present, it will be used when you F5 from Visual Studio, and any settings in _AppSettings.json_ will be ignored. +> A common mistake is mixing up `appsettings.json` and `appsettings.Development.json`. If the latter file exists, Visual Studio uses it when you press F5, and ignores any settings in `appsettings.json`. ## 7. Create an API endpoint @@ -105,63 +106,63 @@ docker run --rm -it ` mcr.microsoft.com/dotnet/aspire-dashboard:latest ``` -Data displayed in the dashboard can be sensitive. By default, the dashboard is secured with authentication that requires a token to log in. The token is displayed in the resulting output when running the container. +Data displayed in the dashboard can be sensitive. By default, the dashboard requires an authentication token to log in. The container displays this token in its output. [![Aspire Dashboard](./media/aspire-dashboard-auth.png)](./media/aspire-dashboard-auth.png#lightbox) -Copy the URL shown, and replace `0.0.0.0` with `localhost`, for example, `http://localhost:18888/login?t=123456780abcdef123456780`, and open that in your browser. Or you can also paste the key after `/login?t=` when the login dialog is shown. The token changes each time you start the container. +Copy the URL, replace `0.0.0.0` with `localhost`, for example, `http://localhost:18888/login?t=123456780abcdef123456780`, and open it in your browser. Or, paste the key after `/login?t=` in the login dialog. The token changes each time you start the container. ## 9. Run the project -Run the project with `dotnet run`. The console output displays the URLs that the app is listening on, for example: +Run the project with `dotnet run`. The console output displays the URLs the app listens on, for example: ``` output info: Microsoft.Hosting.Lifetime[14] Now listening on: http://localhost:5086 ``` -Use the port shown in your own console output, as it can differ from the examples in this article. Access the API with the browser or curl, using that port: +Use the port shown in your own console output, because it might differ from the examples in this article. Use a browser or curl to access the API on that port: ``` dotnetcli curl -k http://localhost:5086 ``` -Each time you request the page, it increments the count for the number of greetings that have been made. +Each time you request the page, the count of greetings increases. ### 9.1 Log output -The logging statements from the code are output using `ILogger`. By default, the [Console Provider](../extensions/logging/overview.md?tabs=command-line#configure-logging) is enabled so that output is directed to the console. +The code logs statements using `ILogger`. By default, .NET enables the [Console Provider](../extensions/logging/overview.md?tabs=command-line#configure-logging), which directs output to the console. -There are a few options for how logs can be egressed from .NET: +You can egress logs from .NET in a few ways: -- `stdout` and `stderr` output is redirected to log files by container systems such as [Kubernetes](https://kubernetes.io/docs/concepts/cluster-administration/logging/#how-nodes-handle-container-logs). -- Using logging libraries that integrate with ILogger. These libraries include [Serilog](https://serilog.net/) and [NLog](https://nlog-project.org/). -- Using logging providers for OTel such as OTLP. The logging section in the code from step 5 adds the OTel provider. +- Container systems such as [Kubernetes](https://kubernetes.io/docs/concepts/cluster-administration/logging/#how-nodes-handle-container-logs) redirect `stdout` and `stderr` output to log files. +- Use logging libraries that integrate with `ILogger`, such as [Serilog](https://serilog.net/) and [NLog](https://nlog-project.org/). +- Use logging providers for OTel, such as OTLP. The logging section of the code in step 5 adds the OTel provider. -The logs are shown in the dashboard as structured logs - any properties you set in the log message are extracted as fields in the log record. +The dashboard shows logs as structured logs. Any properties you set in the log message become fields in the log record. [![Logs in standalone dashboard](./media/aspire-dashboard-logs-thumb.png)](./media/aspire-dashboard-logs.png#lightbox) -### 9.2 Viewing the metrics +### 9.2 Metrics view -The Aspire dashboard shows metrics on a per resource basis (a resource being the OTel way of talking about sources of telemetry such as a process). When a resource is selected, the dashboard enumerates each metric that has been sent to its OTLP endpoint by the resource. The list of metrics is dynamic, and is updated as new metrics are received. +The Aspire dashboard shows metrics on a per resource basis. A resource is the OTel term for a source of telemetry, such as a process. When you select a resource, the dashboard lists each metric that the resource sent to its OTLP endpoint. The list of metrics is dynamic, and it updates as the dashboard receives new metrics. [![Metrics in standalone dashboard](./media/aspire-dashboard-metrics-thumb.png)](./media/aspire-dashboard-metrics.png#lightbox) -The view for the metrics depends on the type of metric that's being used: +The metrics view depends on the type of metric you use: -- Counters are shown directly. -- Histograms that track a value per request, such as a timespan or bytes sent per request, are collected into a series of buckets. The dashboard graphs the P50, P90, and P99 percentiles. Histogram results can include exemplars, which are individual datapoints together with the trace/spanId for that request. These are shown as dots on the graph. Selecting one navigates to the respective trace so you can see what happened to cause that value. This is useful for diagnosing outliers. -- Metrics can include dimensions, which are key/value pairs associated with individual values. The values are aggregated per dimension. Using the dropdowns in the view, you can filter the results to look at specific dimensions, such as only `GET` requests, or those for a specific URL route in ASP.NET. +- The dashboard shows counters directly. +- For histograms that track a value per request, such as a timespan or bytes sent per request, the dashboard collects values into a series of buckets and graphs the P50, P90, and P99 percentiles. Histogram results can include exemplars, which are individual data points together with the trace/span ID for that request. The dashboard shows these as dots on the graph. Select one to navigate to the respective trace, so you can see what caused that value. This feature helps you diagnose outliers. +- Metrics can include dimensions, which are key/value pairs associated with individual values. The dashboard aggregates values per dimension. Use the dropdowns in the view to filter results by specific dimensions, such as `GET` requests only, or a specific URL route in ASP.NET. -### 9.3 Viewing the tracing +### 9.3 Tracing view -The tracing view shows a list of traces. Each trace is a set of activities that share the same traceId. Work is tracked with spans, which represent a unit of work. Processing an ASP.NET request creates a span. Making an HttpClient request is a span. By tracking the span's parent, a hierarchy of spans can be visualized. By collecting spans from each resource (process), you can track the work that happens across a series of services. HTTP requests have a header that's used to pass the traceId and parent spanId to the next service. Each resource needs to collect telemetry and send it to the same collector. It will then aggregate and present a hierarchy of the spans. +The tracing view lists traces. Each trace is a set of activities that share the same trace ID. Spans track work, and each span represents a unit of work. Processing an ASP.NET request creates a span. Making an HttpClient request is a span. Tracking each span's parent builds a hierarchy of spans that you can visualize. Collecting spans from each resource (process) lets you track work across a series of services. HTTP requests include a header that passes the trace ID and parent span ID to the next service. Each resource must collect telemetry and send it to the same collector, which then aggregates and presents a hierarchy of the spans. [![Traces in standalone dashboard](./media/aspire-dashboard-traces-thumb.png)](./media/aspire-dashboard-traces.png#lightbox) -The dashboard shows a list of traces with summary information. Whenever spans with a new traceId are seen, they get a row in the table. Clicking view shows all the spans in the trace. +The dashboard shows a list of traces with summary information. Whenever the dashboard detects spans with a new trace ID, it adds a row to the table. Select **View** to show all the spans in the trace. [![Spans in standalone dashboard](./media/aspire-dashboard-spans-thumb.png)](./media/aspire-dashboard-spans.png#lightbox) -Selecting a span shows its details including any properties on the span, such as the `greeting` tag that you set in [step 7](#7-create-an-api-endpoint). +Select a span to show its details, including any properties on the span, such as the `greeting` tag you set in [step 7](#7-create-an-api-endpoint). From 3cc0ac0e4a205974cad29a4453e72097b7f9d953 Mon Sep 17 00:00:00 2001 From: "Andy De George (from Dev Box)" Date: Fri, 21 Aug 2026 08:51:26 -0700 Subject: [PATCH 10/11] Remove series intro sentence Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- docs/core/diagnostics/observability-otlp-example.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/core/diagnostics/observability-otlp-example.md b/docs/core/diagnostics/observability-otlp-example.md index f738a8ab961cb..70d8c7251ff81 100644 --- a/docs/core/diagnostics/observability-otlp-example.md +++ b/docs/core/diagnostics/observability-otlp-example.md @@ -9,8 +9,6 @@ ai-usage: ai-assisted # Example: Use OpenTelemetry with OTLP and the standalone Aspire Dashboard -This article is one of a series of examples that illustrate [.NET observability with OpenTelemetry](./observability-with-otel.md). - The Aspire Dashboard is a standard part of Aspire, but it's also available as a [standalone Docker container](https://aspire.dev/dashboard/standalone/) that provides an OTLP endpoint for sending telemetry. The dashboard visualizes logs, metrics, and traces. Using the dashboard this way has no dependency on Aspire, and it visualizes telemetry from any app that sends telemetry via OTLP. It works equally well for apps written in Java, GoLang, or Python, provided they can send their telemetry to an OTLP endpoint. The Aspire Dashboard requires less configuration and fewer setup steps than open-source solutions such as [Prometheus, Grafana, and Jaeger](./observability-prgrja-example.md). But unlike those tools, the Aspire Dashboard is a developer visualization tool, not a production monitoring tool. From a897bc7310fe1b52fb5c82571dac822e808ab02a Mon Sep 17 00:00:00 2001 From: "Andy De George (from Dev Box)" Date: Fri, 21 Aug 2026 08:54:28 -0700 Subject: [PATCH 11/11] Add task-focused intro paragraph and tighten title/description for SEO - Add a new opening paragraph stating what the article shows how to do - Shorten title/H1 to 'Use OpenTelemetry with OTLP and the Aspire Dashboard' (drop redundant 'Example:' and 'standalone') - Rewrite meta description as a concise, keyword-focused summary - Update the matching link text in observability-with-otel.md and the TOC entry Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- docs/core/diagnostics/observability-otlp-example.md | 8 +++++--- docs/core/diagnostics/observability-with-otel.md | 2 +- docs/navigate/tools-diagnostics/toc.yml | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/core/diagnostics/observability-otlp-example.md b/docs/core/diagnostics/observability-otlp-example.md index 70d8c7251ff81..88b88f5f0b0bd 100644 --- a/docs/core/diagnostics/observability-otlp-example.md +++ b/docs/core/diagnostics/observability-otlp-example.md @@ -1,13 +1,15 @@ --- -title: "Example: Use OpenTelemetry with OTLP and the standalone Aspire Dashboard" -description: An introduction to observing .NET apps with OTLP and the standalone Aspire Dashboard +title: "Use OpenTelemetry with OTLP and the Aspire Dashboard" +description: Learn how to instrument a .NET app with OpenTelemetry and send logs, metrics, and traces to the Aspire Dashboard using OTLP. ms.date: 08/20/2026 ms.topic: how-to ms.custom: sfi-image-nochange ai-usage: ai-assisted --- -# Example: Use OpenTelemetry with OTLP and the standalone Aspire Dashboard +# Use OpenTelemetry with OTLP and the Aspire Dashboard + +This article shows you how to instrument a .NET web API with OpenTelemetry and send its logs, metrics, and traces to the Aspire Dashboard using OTLP. You add the OpenTelemetry packages, configure custom metrics and traces, and view the results in the dashboard. The Aspire Dashboard is a standard part of Aspire, but it's also available as a [standalone Docker container](https://aspire.dev/dashboard/standalone/) that provides an OTLP endpoint for sending telemetry. The dashboard visualizes logs, metrics, and traces. Using the dashboard this way has no dependency on Aspire, and it visualizes telemetry from any app that sends telemetry via OTLP. It works equally well for apps written in Java, GoLang, or Python, provided they can send their telemetry to an OTLP endpoint. diff --git a/docs/core/diagnostics/observability-with-otel.md b/docs/core/diagnostics/observability-with-otel.md index 277a3084abddb..cd198d7a536cb 100644 --- a/docs/core/diagnostics/observability-with-otel.md +++ b/docs/core/diagnostics/observability-with-otel.md @@ -91,7 +91,7 @@ The following table describes the main packages. This topic is continued with a couple of example walkthroughs for using OpenTelemetry in .NET: -- [Example: Use OTLP and the standalone Aspire Dashboard](./observability-otlp-example.md) +- [Use OTLP and the Aspire Dashboard](./observability-otlp-example.md) - [Example: Use OpenTelemetry with Azure Monitor and Application Insights](./observability-applicationinsights.md) - [Example: Use OpenTelemetry with Prometheus, Grafana, and Jaeger](./observability-prgrja-example.md) diff --git a/docs/navigate/tools-diagnostics/toc.yml b/docs/navigate/tools-diagnostics/toc.yml index aaa83f8746a00..27167e73a40af 100644 --- a/docs/navigate/tools-diagnostics/toc.yml +++ b/docs/navigate/tools-diagnostics/toc.yml @@ -408,7 +408,7 @@ items: items: - name: Overview href: ../../core/diagnostics/observability-with-otel.md - - name: "Example: Use OpenTelemetry with OTLP and the standalone Aspire Dashboard" + - name: "Use OpenTelemetry with OTLP and the Aspire Dashboard" href: ../../core/diagnostics/observability-otlp-example.md - name: "Example: Use OpenTelemetry with Prometheus, Grafana, and Jaeger" href: ../../core/diagnostics/observability-prgrja-example.md