Instrument your .NET application with OpenTelemetry and report trace data to Managed Service for OpenTelemetry. After traces flow in, you can view application topology, traces, abnormal and slow transactions, and SQL analysis in the Application Real-Time Monitoring Service (ARMS) console.
OpenTelemetry supports three instrumentation approaches for .NET. Start with automatic instrumentation. Add manual instrumentation if automatic does not cover all frameworks in your application or if you need custom business spans.
| Approach | Best for | .NET version |
|---|---|---|
| Automatic | Quick setup with zero code changes | .NET 6+ (.NET Framework not supported) |
| Manual | Full control over spans and trace context | .NET 5+, .NET Core 2.0+, .NET Framework 4.6.1+ |
| Combined (recommended) | Automatic framework traces plus custom business spans | .NET 6+ for auto; see manual requirements for custom spans |
Sample code
Download the complete sample code from dotnet-demo.
Automatic instrumentation
Automatic instrumentation uses the OpenTelemetry .NET agent to capture traces without code changes. It supports .NET 6 and later. .NET Framework is not supported.
For a full list of automatically instrumented frameworks, see Available instrumentations in the OpenTelemetry documentation.
Step 1: Create a sample web application
Create a new ASP.NET Core project and build it:
mkdir dotnet-simple-demo cd dotnet-simple-demo dotnet new web dotnet buildReplace the contents of
Properties/launchSettings.jsonwith the following configuration:{ "$schema": "http://json.schemastore.org/launchsettings.json", "profiles": { "http": { "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": true, "applicationUrl": "http://localhost:8080", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } } } }
Step 2: Install the automatic instrumentation agent
Download and run the installation script:
curl -L -O https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/releases/latest/download/otel-dotnet-auto-install.sh
./otel-dotnet-auto-install.shStep 3: Configure environment variables and run the application
Set the required environment variables, source the instrumentation script, and start the application.
Replace the following placeholders with your actual values:
| Placeholder | Description | Example |
|---|---|---|
<service-name> | A name to identify your application in ARMS | my-dotnet-app |
<endpoint> | The gRPC endpoint from the Prerequisites section | http://tracing-analysis-dc-hz.aliyuncs.com:8090 |
<token> | The authentication token from the Prerequisites section | abc123_your_token |
export OTEL_TRACES_EXPORTER=otlp \
OTEL_METRICS_EXPORTER=none \
OTEL_LOGS_EXPORTER=none \
OTEL_SERVICE_NAME=<service-name> \
OTEL_EXPORTER_OTLP_PROTOCOL=grpc \
OTEL_EXPORTER_OTLP_ENDPOINT=<endpoint> \
OTEL_EXPORTER_OTLP_HEADERS="Authentication=<token>"
. $HOME/.otel-dotnet-auto/instrument.sh
dotnet runStep 4: Verify trace reporting
Send a request to the application to generate traces:
curl localhost:8080/The automatic instrumentation agent captures the request and reports the trace to Managed Service for OpenTelemetry. To verify that traces arrived, see View monitoring data.
For additional configuration options such as resource attributes, sampler settings, and propagation, see Configuration and settings in the OpenTelemetry documentation.
Manual instrumentation
Manual instrumentation gives full control over which operations produce spans. Use this approach when automatic instrumentation does not cover your framework or when you need to trace custom business logic.
Step 1: Add OpenTelemetry packages
Navigate to the dotnet-demo/opentelemetry-demo/manual-demo directory and add the required NuGet packages:
dotnet add package OpenTelemetry
dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol
dotnet add package OpenTelemetry.Exporter.Console # Optional: export to console for debugging
dotnet add package OpenTelemetry.Extensions.HostingStep 2: Create the tracing configuration
Create OpentelemetryExporterDemo.cs with a TracerProvider that exports spans over HTTP to your Managed Service for OpenTelemetry endpoint.
Replace <endpoint> with the HTTP endpoint from the Prerequisites section.
using System.Diagnostics;
using OpenTelemetry;
using OpenTelemetry.Trace;
using OpenTelemetry.Resources;
using OpenTelemetry.Exporter;
namespace Demo
{
internal static class OpentelemetryExporterDemo
{
internal static void Run()
{
Console.WriteLine("otlp running");
// Specify the service name that appears in ARMS.
var serviceName = "otlp-test";
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddSource(serviceName)
.SetResourceBuilder(
ResourceBuilder.CreateDefault().AddService(serviceName))
.AddOtlpExporter(opt =>
{
// Set the HTTP endpoint for trace export.
opt.Endpoint = new Uri("<endpoint>");
opt.Protocol = OtlpExportProtocol.HttpProtobuf;
})
.AddConsoleExporter() // Optional: prints spans to console for debugging.
.Build();
for(int i = 0; i<10; i++)
{
var MyActivitySource = new ActivitySource(serviceName);
using var activity = MyActivitySource.StartActivity("SayHello");
activity?.SetTag("bar", "Hello World");
}
}
}
}Step 3: Update the entry point
Modify Program.cs to call the tracing demo:
using System.Diagnostics;
using System.Net.Http;
using OpenTelemetry;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
namespace Demo
{
public class Otlp
{
public static void Main(string[] args)
{
OpentelemetryExporterDemo.Run();
}
}
}Step 4: Run and verify
dotnet runThe application creates 10 sample spans and exports them to Managed Service for OpenTelemetry. To verify that traces arrived, see View monitoring data.
Combined automatic and manual instrumentation
This approach combines automatic framework-level instrumentation (for example, ASP.NET Core HTTP traces) with custom spans for business logic. For most production applications, this is the recommended approach.
OpenTelemetry can automatically instrument dozens of .NET frameworks. For a full list, see Traces instrumentations.
Step 1: Create an ASP.NET Core MVC application
Navigate to the dotnet-demo/opentelemetry-demo/auto-demo directory. Replace <your-project-name> with your application name:
mkdir <your-project-name>
cd <your-project-name>
dotnet new mvcStep 2: Add OpenTelemetry packages
Install the core OpenTelemetry packages and the ASP.NET Core instrumentation library:
dotnet add package OpenTelemetry.Exporter.Console # Optional: export to console for debugging
dotnet add package OpenTelemetry.Extensions.Hosting
dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol # Export over OTLP
dotnet add package OpenTelemetry.Instrumentation.AspNetCore # Auto-instrument ASP.NET CoreTo instrument additional frameworks (such as HttpClient, gRPC, or SQL), add the corresponding OpenTelemetry.Instrumentation.* package. See Traces instrumentations for the full list.
Step 3: Configure OpenTelemetry in Program.cs
Add the following imports at the top of Program.cs:
using System.Diagnostics;
using OpenTelemetry.Exporter;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;Add the DiagnosticsConfig class at the end of the file. Replace <your-service-name> and <your-host-name> with your actual values:
public static class DiagnosticsConfig
{
public const string ServiceName = "<your-service-name>";
public const string HostName = "<your-host-name>";
public static ActivitySource ActivitySource = new ActivitySource(ServiceName);
}Add the OpenTelemetry initialization code between builder.Services.AddControllersWithViews() and var app = builder.Build(). Choose one of the following export protocols:
Option A: Export over HTTP
Replace <http_endpoint> with the HTTP endpoint from the Prerequisites section:
// ...
builder.Services.AddOpenTelemetry()
.WithTracing(tracerProviderBuilder =>
tracerProviderBuilder
.AddSource(DiagnosticsConfig.ActivitySource.Name)
.SetResourceBuilder(OpenTelemetry.Resources.ResourceBuilder.CreateDefault()
.AddAttributes(new Dictionary<string, object> {
{"service.name", DiagnosticsConfig.ServiceName},
{"host.name",DiagnosticsConfig.HostName}
}))
.AddAspNetCoreInstrumentation()
.AddConsoleExporter() // Optional: prints spans to console for debugging.
.AddOtlpExporter(opt =>
{
opt.Endpoint = new Uri("<http_endpoint>");
opt.Protocol = OtlpExportProtocol.HttpProtobuf;
})
);
// ...Option B: Export over gRPC
Replace <grpc_endpoint> and <token> with the gRPC endpoint and authentication token from the Prerequisites section:
// ...
builder.Services.AddOpenTelemetry()
.WithTracing(tracerProviderBuilder =>
tracerProviderBuilder
.AddSource(DiagnosticsConfig.ActivitySource.Name)
.SetResourceBuilder(OpenTelemetry.Resources.ResourceBuilder.CreateDefault()
.AddAttributes(new Dictionary<string, object> {
{"service.name", DiagnosticsConfig.ServiceName},
{"host.name",DiagnosticsConfig.HostName}
}))
.AddAspNetCoreInstrumentation()
.AddConsoleExporter() // Optional: prints spans to console for debugging.
.AddOtlpExporter(opt =>
{
opt.Endpoint = new Uri("<grpc_endpoint>");
opt.Headers = "Authentication=<token>";
opt.Protocol = OtlpExportProtocol.Grpc;
})
);
// ...Step 4: Run the application
dotnet runSample output:
Building...
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://localhost:5107
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
Content root path: /path/to/<your-project-name>Step 5: Verify trace reporting
Open the URL from the output (for example, http://localhost:5107) in a browser. If the default ASP.NET Core MVC page loads, the application is running and traces are being reported to Managed Service for OpenTelemetry.

To verify that traces arrived, see View monitoring data.
View monitoring data
After you generate trace data, verify that it reaches Managed Service for OpenTelemetry:
Log on to the ARMS console.
In the left-side navigation pane, choose Application Monitoring > Applications.
On the Applications page, find your application by the service name you configured. Click the application name to view trace data, topology, and performance metrics.
If your application appears in the list, trace reporting is working. If it does not appear, wait 1--2 minutes and refresh the page. Trace data may take a short time to process.
The Language column on the Applications page indicates the connection type. Theicon means the application is connected to Application Monitoring. A hyphen (-) means the application is connected to Managed Service for OpenTelemetry.
Supported frameworks for manual and semi-automatic instrumentation
The following table lists the frameworks supported by OpenTelemetry for manual and semi-automatic .NET instrumentation.
| Framework | Windows .NET Framework | Cross-platform .NET (.NET Core) | Supported version | Instrumented library |
|---|---|---|---|---|
| ASP.NET | Yes | Not supported (MVC and Web API) | N/A | N/A |
| ASP.NET Core | N/A | Yes | N/A | N/A |
| Azure | Yes | Yes | Packages with the Azure. prefix released after October 1, 2021 | Azure SDK |
| Elasticsearch | Yes | Yes | V8.0.0 to V8.10.0 (exclusive). V8.10.0 and later are supported by the Elasticsearch Transport framework. | Elastic.Clients.Elasticsearch |
| Elasticsearch Transport | Yes | Yes | V0.4.16+ | Elastic.Transport |
| Entity Framework Core | N/A | Yes | V6.0.12+ | Microsoft.EntityFrameworkCore |
| GraphQL | N/A | Yes | V7.5.0+ | GraphQL |
| gRPC Client | Yes | Yes | V2.52.0 to V3.0.0 (exclusive) | Grpc.Net.Client |
| HttpClient | Yes | Yes | All versions | System.Net.Http.HttpClient, System.Net.HttpWebRequest |
| Quartz | V4.7.1 and earlier not supported | Yes | V3.4.0+ | Quartz |
| MassTransit | N/A | Yes | V8.0.0+ | MassTransit |
| MongoDB | Yes | Yes | V2.13.3 to V3.0.0 (exclusive) | MongoDB.Driver.Core |
| MySQL Connector | Yes | Yes | V2.0.0+ | MySqlConnector |
| MySQL Data | N/A | Yes | V8.1.0+ | MySql.Data |
| Npgsql | Yes | Yes | V6.0.0+ | Npgsql |
| NServiceBus | Yes | Yes | V8.0.0+ | NServiceBus |
| SQL Client | Yes | Yes | Microsoft.Data.SqlClient V3 not supported | Microsoft.Data.SqlClient, System.Data.SqlClient, System.Data (shipped with .NET Framework) |
| StackExchange.Redis | N/A | Yes | V2.0.405 to V3.0.0 (exclusive) | StackExchange.Redis |
| WCF Client | Yes | Yes | N/A | N/A |
| WCF Service | Yes | N/A | N/A | N/A |
icon means the application is connected to Application Monitoring. A hyphen (-) means the application is connected to Managed Service for OpenTelemetry.