Instrument Dotnet applications with OpenTelemetry
This guide shows how to instrument your .NET application with OpenTelemetry and export the traces to Dynatrace. To learn more about how Dynatrace works with OpenTelemetry, see Send data to Dynatrace with OpenTelemetry.
To learn more about Dynatrace support for Ruby monitoring, see .NET.
Prerequisites
- Dynatrace version 1.222+
- W3C Trace Context is enabled
- From the Dynatrace menu, go to Settings > Server-side service monitoring > Deep monitoring > Distributed tracing.
- Turn on Send W3C Trace Context HTTP headers.
Overview
To monitor your .NET application with OpenTelemetry you need to
- Instrument your application,
- Send the data to Dynatrace, and
- Restart your application and verify the data in Dynatrace
1. Instrument your application
To instrument automatically, add the package reference of the instrumentations for the frameworks you use to your .csproj file (see OpenTelemetry page):
<PackageReference Include="OpenTelemetry.Instrumentation.<USED_FRAMEWORK>" Version="1.0.0" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.0.0-rc8" />
Add the instrumentations below to the tracer builder code from the section above.
//TODO Replace <instrumentations> in the code above with the following code:
.Add<USED_FRAMEWORK>Instrumentation()
Replace <USED_FRAMEWORK>
in the code snippets above with the framework that you use. See GitHub to find your OpenTelemetry.Instrumentation.<USED_FRAMEWORK>
.
To instrument manually, make sure to call the ActivitySource initialized before. You can give it a name and add custom attributes.
using var activity = MyActivitySource.StartActivity("my-span");
activity?.SetTag("my-key-1","my-value-1"); //TODO Add attributes
2. Send the data to Dynatrace
To send data to Dynatrace, add the following package references to your .csproj file and add the code snippet below:
<PackageReference Include="OpenTelemetry" Version="1.2.0-beta1" />
<PackageReference Include="OpenTelemetry.Api" Version="1.2.0-beta1" />
private const string activitySource = "Dynatrace.DotNetApp.Sample";
public static readonly ActivitySource MyActivitySource = new ActivitySource(activitySource);
List<KeyValuePair<string, object>> dt_metadata = new List<KeyValuePair<string, object>>();
foreach (string name in new string[] {"dt_metadata_e617c525669e072eebe3d0f08212e8f2.properties", "/var/lib/dynatrace/enrichment/dt_metadata.properties"}) {
try {
foreach (string line in System.IO.File.ReadAllLines(name.StartsWith("/var") ? name : System.IO.File.ReadAllText(name))) {
var keyvalue = line.Split("=");
dt_metadata.Add( new KeyValuePair<string, object>(keyvalue[0], keyvalue[1]));
}
}
catch { }
}
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
Sdk.CreateTracerProviderBuilder()
.SetSampler(new AlwaysOnSampler())
.AddSource(activitySource)
.SetResourceBuilder(ResourceBuilder.CreateEmpty().AddService("dotnet-quickstart").AddAttributes(dt_metadata))
// TODO Add <instrumentations>
// TODO Add <exporter> in case of no OneAgent (see below)
.Build();
private const string activitySource = "Dynatrace.DotNetApp.Sample";
public static readonly ActivitySource MyActivitySource = new ActivitySource(activitySource);
public void ConfigureServices(IServiceCollection services)
{
List<KeyValuePair<string, object>> dt_metadata = new List<KeyValuePair<string, object>>();
foreach (string name in new string[] {"dt_metadata_e617c525669e072eebe3d0f08212e8f2.properties", "/var/lib/dynatrace/enrichment/dt_metadata.properties"}) {
try {
foreach (string line in System.IO.File.ReadAllLines(System.IO.File.ReadAllText(name))) {
var keyvalue = line.Split("=");
dt_metadata.Add( new KeyValuePair<string, object>(keyvalue[0], keyvalue[1]));
}
}
catch { }
}
services.AddControllers();
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
services.AddOpenTelemetryTracing((builder) => builder
.SetSampler(new AlwaysOnSampler())
.AddSource(activitySource)
.SetResourceBuilder(ResourceBuilder.CreateEmpty().AddAttributes(dt_metadata).AddService("dotnet-quickstart")) //TODO Replace with the name of your application
// TODO Add <instrumentations>
// TODO Add <exporter> in case of no OneAgent (see below)
;
}
If you have the OneAgent installed, it will automatically ingest OpenTelemetry data.
Add the following package reference to your .csproj file and replace <exporter>
in the code snippet above with the code below:
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.2.0-beta1" />
var token = "Api-Token <TOKEN>"; //TODO Replace <TOKEN> with the authentication token created in section 3 below
//TODO Replace <exporter> in the code above with the following code:
.AddOtlpExporter(otlpOptions =>
{
otlpOptions.Endpoint = new Uri("<URL>"); //TODO Replace <URL> with the URL as determined in section 3 below
otlpOptions.Protocol = OtlpExportProtocol.HttpProtobuf;
otlpOptions.Headers = $"Authorization={token}";
})
Lastly, you need to define the correct endpoint and token, to make sure your data arrives where it should be.
- To set the endpoint:
- Use your Environment ID to set the endpoint to which your app will send traces as follows:
- Dynatrace SaaS
https://{your-environment-id}.live.dynatrace.com/api/v2/otlp/v1/traces
- Dynatrace Managed
https://{your-domain}/e/{your-environment-id}/api/v2/otlp/v1/traces
- Dynatrace SaaS
- Replace
<URL>
in the code snippet above with your endpoint.
- Use your Environment ID to set the endpoint to which your app will send traces as follows:
- To create an authentication token
- In the Dynatrace menu, go to Access tokens and select Generate new token.
- Provide a Token name.
- In the Search scopes box, search for
Ingest OpenTelemetry traces
and select the checkbox. - Select Generate token.
- Select Copy to copy the token to your clipboard.
- Save the token in a safe place; you can't display it again, and you will need it in section 3 below.
- Replace
<TOKEN>
in the code snippet above with your token.
Verify that the traces are being ingested into Dynatrace
After restarting your app you will be able to find your spans within a few minutes (and if your app is getting traffic):
- Under the tab Ingested Traces at Applications & Microservices > Distributed traces.
- As part of an existing PurePath distributed trace if the root of your call is already being monitored by the OneAgent.
(Optional) Configure data capturing to meet privacy requirements
While Dynatrace automatically captures all OpenTelemetry resource and span attributes, only attribute values specified in the allowlist are stored and shown in the web UI. This prevents accidental storage of personal data, so you can meet your privacy requirements and control the amount of monitoring data that's being stored.
To view and edit the allowlists:
- Span attributes In the Dynatrace menu, go to Settings > Server-side service monitoring > Span attributes.
- Resource attributes In the Dynatrace menu, go to Settings > Server-side service monitoring > Resource attributes.