3 minute read

This article is part of a series about OpenTelemetry in .NET. OpenTelemetry establishes a de facto standard for application observability by providing standardized APIs, SDKs, and tools to collect signals - metrics, traces, and logs.

OpenTelementry .NET Tracing API

The .NET runtime contains an Activity class, which is used for tracing purposes and represents a Span in OpenTelemetry terminology. The Activity class is part of the System.Diagnostics.DiagnosticSource package.

This allows applications to emit OpenTelemetry traces using the standard .NET Runtime.

To align more closely with OpenTelemetry terminology (like tracer, span instead of activitySource, activity) in the application, use the OpenTelementry.API, which wraps the .NET Activity classes.

Manual Instrumentation

Use the ActivitySource class, which provides the name and version of the application doing the instrumentation. The instance of ActivitySource should be created once and reused throughout the application.

 static ActivitySource activitySource = new ActivitySource(
    "serviceName",
    "1.0.0");

Use the ActivitySource instance to create an Activity instance, which represents a single-span operation.

 using var activity = activitySource.StartActivity("ActivityName");

If there are no listeners/samplers interested in this activity, the StartActivity returns null.

The StartActivity method starts an activity and sets it as the current activity in the ActivityContext.Current and propagates the ActivityContext from the parent activity.

using var activity = activitySource.StartActivity("ActivityName");
activity?.SetTag("http.url", "url");
activity?.AddEvent(new ActivityEvent("activity event"));
activity?.SetStatus(ActivityStatusCode.Error, "error");

Populate activity with tags follow the OpenTelemetry semantic conventions.

Configure OpenTelemetry

Install the nuget package OpenTelemetry.Extensions.Hosting to expose the OpenTelemetry SDK.

builder.Services.AddOpenTelemetry()
    .WithTracing(tracing =>
    {
        tracing.SetResourceBuilder(ResourceBuilder.CreateDefault()
                    .AddService("serviceName"))
                .AddSource("serviceName"); // Configure sources to listen
    });

Instrumentations

There are two ways how to instrument.

  • Manual instrumentation means adding custom instruments to .NET application using the Activity class.
  • Automatic instrumentation adds external instruments (HTTP, SQL, Elastic, Redis,…) to .NET application without modify a source code by adding OpenTelemetry.AutoInstrumentation nuget package.

Automatic instrumentation can also enabled by OpenTelemetry.Instrumentation.X nuget packages that are specific per resource.

For example, instruments for HTTP Requests (In) and Requests (Out) are in the OpenTelemetry.Instrumentation.AspNetCore and OpenTelemetry.Instrumentation.Http packages, which also configures and propagates trace context through Propagator API via HTTP Headers.

builder.Services.AddOpenTelemetry()
    .WithTracing(tracing =>
    {
        tracing.SetResourceBuilder(ResourceBuilder.CreateDefault()
                    .AddService("serviceName"))
                .AddSource("serviceName"); // Configures sources to listen (instrument)
                .AddAspNetCoreInstrumentation() // HTTP Requests (In) - Configures tracing context from headers
                .AddHttpClientInstrumentation() // HTTP Requests (Out) - Propagates tracing context to headers
    });

Sampling (especially Head Sampling) can be configured by tracing.SetSampler(...).

Exporters

Exporters allow an application to send instrumentation data to various backends, such as Console, Zipkin, or OTLP.

For example, export traces to the OTLP collector by OpenTelemetry.Exporter.OpenTelemetryProtocol and configure it using OTLP Exporter Configuration.

builder.Services.AddOpenTelemetry()
    .WithTracing(tracing =>
    {
        tracing.SetResourceBuilder(ResourceBuilder.CreateDefault()
                    .AddService("serviceName"))
                .AddSource("serviceName"); // Configure sources to listen (instrument)
                .AddAspNetCoreInstrumentation() // HTTP Requests (In)
                .AddHttpClientInstrumentation() // HTTP Requests (Out)
                .AddOtlpExporter()
    });

Updated: