OpenTelemetry Bridgeedit

The OpenTelemetry Bridge in the Elastic .NET APM Agent bridges OpenTelemetry spans into Elastic APM transactions and spans. The Elastic APM OpenTelemetry bridge allows you to use the vendor-neutral OpenTelemetry Tracing API to manually instrument your code and have the Elastic .NET APM agent handle those API calls. This means you can use the Elastic APM agent for tracing, without any vendor lock-in from adding manual tracing using the APM agent’s own Public API.

Getting startededit

The OpenTelemetry bridge is part of the core agent package (Elastic.Apm), so you don’t need to add an additional dependency.

Disabling the OpenTelemetry Bridgeedit

The OpenTelemetry bridge is enabled out of the box starting version 1.23.0.

This allows you to instrument code through ActivitySource and StartActivity() without any additional configuration.

If you want to disable the bridge you can disable it for now through the OpenTelemetryBridgeEnabled configuration setting.

If you configured the agent via environment variables, set the ELASTIC_APM_OPENTELEMETRY_BRIDGE_ENABLED environment variable to false.

If you configured the agent via the appsettings.json file, then set ElasticApm:OpenTelemetryBridgeEnabled to false.

{
  "ElasticApm":
    {
      "ServerUrl":  "http://myapmserver:8200",
      "SecretToken":  "apm-server-secret-token",
      "OpenTelemetryBridgeEnabled": false
    }
}

Create an ActivitySource and start spansedit

You can create OpenTelemetry spans, or in .NET terminology, you can start creating new activities via the activity source, and the agent will bridge those spans automatically.

public static void Sample()
{
	var src = new ActivitySource("Test");
	using var activity1 = src.StartActivity(nameof(Sample), ActivityKind.Server);
	Thread.Sleep(100);
	using var activity2 = src.StartActivity("foo");
	Thread.Sleep(150);
}

The code snippet above creates a span named Sample and a child span on Sample named foo. The bridge will create a transaction from Sample and a child span named foo.

Mixing OpenTelemetry and the Elastic APM Public APIedit

You can also mix the Activity API with the Public API, the OpenTelemetry bridge will take care of putting the spans into the right place. The advantage of this is that if you already have some libraries that you instrumented via the Public API, but going forward, you’d like to use the vendor-independent OpenTelemetry API, you don’t need to replace all Public API calls in one go.

/// ElasticTransaction
/// -
/// ---> OTelSpan
///           -
///           ---> ElasticSpan

var src = new ActivitySource("Test");
tracer.CaptureTransaction( nameof(Sample4), "test", t =>
{
	Thread.Sleep(100);
	using (var activity = src.StartActivity("foo"))
	{
		tracer.CurrentSpan.CaptureSpan("ElasticApmSpan", "test", () => Thread.Sleep(50));
		Thread.Sleep(150);
	}
});

The code snippet above creates a transaction with the Elastic .NET APM Agent’s Public API. Then it creates an activity called foo; this activity will be a child of the previously created transaction. Finally, a span is created again using the Elastic .NET APM Agent’s Public API; this span will be a child span of the OpenTelemetry span.

Of course these calls don’t have to be in the same method. The concept described here works across different methods, types, or libraries.

Baggage supportedit

The Elastic APM Agent also integrates with Activity.Baggage.

Here is an example that sets a baggage value with the above API:

_activitySource.StartActivity("MyActivity")?.AddBaggage("foo", "bar");

The Elastic APM Agent will automatically propagate such values according to the W3C Baggage specification and Activity.Baggage is automatically populated based on the incoming baggage header.

Furthermore, the agent offers the BaggageToAttach configuration to automatically attach values from Activity.Baggage to captured events.

Supported OpenTelemetry implementationsedit

OpenTelemetry in .NET is implemented via the Activity API and there is an OpenTelemetry shim which follows the OpenTelemetry specification more closer. This shim is built on top of the Activity API.

The OpenTelemetry bridge in the Elastic .NET APM Agent targets the Activity API. Since the OpenTelemetry .NET shim builds on top of the Activity API, the shim is implicitly supported as well, although we don’t directly test it, because the Activity API is the recommended OpenTelemetry API for .NET.

Caveatsedit

Not all features of the OpenTelemetry API are supported.

Metricsedit

This bridge only supports the tracing API. The Metrics API is currently not supported.

Span Eventsedit

Span events (Span#addEvent()) are not currently supported. Events will be silently dropped.

Baggageedit

Propagating baggage within or outside the process is not supported. Baggage items are silently dropped.