Skip to main content
dd-trace includes an OpenTelemetry-compatible TracerProvider that can be registered with @opentelemetry/api. This allows you to write instrumentation using the standard OTel API while sending data to Datadog.

Setup

const tracer = require('dd-trace').init()
const { TracerProvider } = tracer

const provider = new TracerProvider()
provider.register()
After calling provider.register(), all calls to @opentelemetry/api will use dd-trace as the backend.
const { trace, context } = require('@opentelemetry/api')

const otelTracer = trace.getTracer('my-service', '1.0.0')

const span = otelTracer.startActiveSpan('my-operation', (span) => {
  try {
    span.setAttribute('user.id', '123')
    // do work
    span.setStatus({ code: 1 }) // SpanStatusCode.OK
    return result
  } catch (err) {
    span.recordException(err)
    span.setStatus({ code: 2, message: err.message }) // SpanStatusCode.ERROR
    throw err
  } finally {
    span.end()
  }
})

TracerProvider

The TracerProvider is a constructor available at tracer.TracerProvider.
new TracerProvider(config?: Record<string, unknown>): TracerProvider

getTracer(name, version?, options?)

Returns an OTel-compatible Tracer for the given instrumentation scope.
getTracer(name: string, version?: string, options?: any): Tracer
name
string
required
The name of the tracer or instrumentation library.
version
string
The version of the tracer or instrumentation library.
returns
Tracer
An OTel-compatible Tracer instance backed by dd-trace.

register()

Registers this provider with @opentelemetry/api.
register(): void

OTel Tracer methods

startSpan(name, options?, context?)

Starts a new span without activating it on the context.
startSpan(name: string, options?: SpanOptions, context?: Context): Span
const span = otelTracer.startSpan('db.query')
span.setAttribute('db.system', 'postgresql')
span.end()

startActiveSpan(name, fn) / startActiveSpan(name, options, fn) / startActiveSpan(name, options, context, fn)

Starts a new span and activates it in the context for the duration of the callback.
startActiveSpan<F extends (span: Span) => unknown>(name: string, fn: F): ReturnType<F>
startActiveSpan<F extends (span: Span) => unknown>(name: string, options: SpanOptions, fn: F): ReturnType<F>
startActiveSpan<F extends (span: Span) => unknown>(name: string, options: SpanOptions, context: Context, fn: F): ReturnType<F>
const result = otelTracer.startActiveSpan('http.request', span => {
  try {
    const data = fetchData()
    span.setStatus({ code: 1 })
    return data
  } catch (err) {
    span.recordException(err)
    span.setStatus({ code: 2, message: err.message })
    throw err
  } finally {
    span.end()
  }
})

OTel Span methods

The OTel Span interface is backed by dd-trace spans. The following methods are available:
MethodDescription
setAttribute(key, value)Sets a single attribute
setAttributes(attributes)Sets multiple attributes
addEvent(name, attributes?, time?)Adds a span event
setStatus(status)Sets the span status
updateName(name)Updates the span name
end(endTime?)Ends the span
isRecording()Whether the span is recording
recordException(exception, time?)Records an exception as a span event
addLink(link)Adds a causal link
addLinks(links)Adds multiple causal links
spanContext()Returns the SpanContext

Attribute mapping to Datadog tags

OpenTelemetry span attributes map to Datadog tags. The following attributes have special meaning:
OTel attributeDatadog tagDescription
service.nameserviceService name for the span
resource.nameresourceResource name for the span
span.typespan.typeSpan type (falls back to custom)
All other OTel attributes are stored as-is in Datadog span tags.

Context propagation

dd-trace supports W3C Trace Context (traceparent/tracestate) by default. Use the OTel propagation API to inject and extract context:
const { propagation, context, trace } = require('@opentelemetry/api')

// Inject into outgoing headers
const carrier = {}
propagation.inject(context.active(), carrier)
fetch('/downstream', { headers: carrier })

// Extract from incoming headers
const ctx = propagation.extract(context.active(), req.headers)
const span = otelTracer.startActiveSpan('request', {}, ctx, span => {
  // span is a child of the extracted context
  span.end()
})

Full example

const tracer = require('dd-trace').init({ service: 'my-service' })

const provider = new tracer.TracerProvider()
provider.register()

const { trace } = require('@opentelemetry/api')
const otelTracer = trace.getTracer('my-service')

async function processRequest(req) {
  return otelTracer.startActiveSpan('process.request', async (span) => {
    try {
      span.setAttribute('request.id', req.id)
      span.setAttribute('service.name', 'processor')

      const result = await doWork(req)

      span.setStatus({ code: 1 })
      return result
    } catch (err) {
      span.recordException(err)
      span.setStatus({ code: 2, message: err.message })
      throw err
    } finally {
      span.end()
    }
  })
}

Build docs developers (and LLMs) love