Overview

Datadog tracing libraries provide an implementation of the OpenTelemetry API for instrumenting your code. This means you can maintain vendor-neutral instrumentation of all your services, while still taking advantage of Datadog’s native implementation, features, and products. You can configure it to generate Datadog-style spans and traces to be processed by the Datadog tracing library for your language, and send those to Datadog.

By instrumenting your code with OpenTelemetry API:

  • Your code remains free of vendor-specific API calls.
  • Your code does not depend on Datadog tracing libraries at compile time (only runtime).
  • Your code does not use the deprecated OpenTracing API.

Replace the OpenTelemetry SDK with the Datadog tracing library in the instrumented application, and the traces produced by your running code can be processed, analyzed, and monitored alongside Datadog traces and in Datadog proprietary products.

For more information, read Interoperability of OpenTelemetry API and Datadog instrumented traces.

The Datadog tracing library, when configured as described here, accepts the spans and traces generated by OpenTelemetry-instrumented code, processes the telemetry, and sends it to Datadog. You can use this approach, for example, if your code has already been instrumented with the OpenTelemetry API, or if you want to instrument using the OpenTelemetry API, and you want to gain the benefits of using the Datadog tracing libraries without changing your code.

If you’re looking for a way to instrument your code with OpenTelemetry and then send span data to Datadog without going through the Datadog tracing library, see OpenTelemetry in Datadog.

Requirements and limitations

  • Datadog Java tracing library dd-trace-java version 1.10.0 or greater.

The following OpenTelemetry features implemented in the Datadog library as noted:

FeatureSupport notes
OpenTelemetry Context propagationDatadog distributed header format is used instead by default.
Span processorsUnsupported
Span ExportersUnsupported
Trace/span ID generatorsID generation is performed by the tracing library, with support for 128-bit trace IDs.
Metrics, Baggage and Context APIUnsupported
Span links (Beta)Requires dd-trace-java version 1.24.0 or greater.

Configuring OpenTelemetry to use the Datadog tracing library

If you have not yet read the instructions for auto-instrumentation and setup, start with the Java Setup Instructions.
  1. Add your desired manual OpenTelemetry instrumentation to your Java code following the OpenTelemetry Java Manual Instrumentation documentation.

  2. Add the Datadog tracing library to the JVM. Beta: You can optionally do this with One-Step APM Instrumentation.

  3. Make sure you only depend on the OpenTelemetry API (and not the OpenTelemetry SDK).

// OpenTelemetry API
implementation "io.opentelemetry:opentelemetry-api:${opentelemetryVersion}"
<!-- OpenTelemetry API -->
<dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-api</artifactId>
    <version>${io.opentelemetry.version}</version>
</dependency>
  1. Set the dd.trace.otel.enabled system property or the DD_TRACE_OTEL_ENABLED environment variable to true.

Datadog combines these OpenTelemetry spans with other Datadog APM spans into a single trace of your application.

Common use cases

Add custom attributes to the current or local root span

// Add attributes to the current span
Span currentSpan = Span.current();
currentSpan.setAttributes("some-key", "some-value");

// Add attributes to the local root span
ContextKey<OtelSpan> localRootSpanKey = ContextKey.named("opentelemetry-traces-local-root-span");
Span rootSpan = Context.current().get(localRootSpanKey);
rootSpan.setAttributes("some-key", "some-value");

Note: If there isn’t a current or local root span, the returned span is invalid, not null, and attributes are not set.

Add custom spans using annotations

First add a dependency to the opentelemetry-instrumentation-annotations library.

  // OpenTelemetry instrumentation annotations
  implementation "io.opentelemetry.instrumentation:opentelemetry-instrumentation-annotations:${opentelemetryVersion}"
<!-- OpenTelemetry instrumentation annotations -->
<dependency>
    <groupId>io.opentelemetry.instrumentation</groupId>
    <artifactId>opentelemetry-instrumentation-annotations</artifactId>
    <version>${io.opentelemetry.version}</version>
</dependency>

Then annotate your methods with the @WithSpan annotation to create a new span each call. The parameters of the call can be annotated with the @SpanAttribute annotation to capture the arguments as span attributes:

@WithSpan
public void myMethod(@SpanAttribute("parameter1") String parameter1,
    @SpanAttribute("parameter2") long parameter2) {
    <...>
}

Note: Using the @AddingSpanAttributes method annotation instead of @WithSpan allows capturing method arguments using the @SpanAttribute annotation without creating a new span. The current span, if it exists, is going to be updated with the captured arguments.

Further Reading