Skip to main content
For code that is not covered by automatic instrumentation, use tracer.trace() and tracer.wrap() to create spans manually. Both methods handle the span lifecycle and scope activation automatically.

tracer.trace(name, [options], fn)

Instruments a function by creating a new span for the duration of the function’s execution. The span is automatically finished when the function completes, the returned promise resolves/rejects, or the provided callback is called.

Type signatures

trace<T>(name: string, fn: (span: Span) => T): T
trace<T>(name: string, fn: (span: Span, done: (error?: Error) => void) => T): T
trace<T>(name: string, options: TraceOptions & SpanOptions, fn: (span?: Span, done?: (error?: Error) => void) => T): T

Options

tracer.trace() accepts standard SpanOptions plus these additional TraceOptions fields:
OptionTypeDescription
resourcestringThe resource being traced (max 5000 chars).
servicestringOverride the service name for this span (max 100 chars).
typestringThe type of request (e.g. 'web', 'db').
childOfSpan | SpanContext | nullExplicit parent. Pass null to force a root span.
tags{ [key: string]: any }Tags to set on the span at creation.
measuredbooleanWhether to measure the span for metrics.
links{ context: SpanContext, attributes?: Object }[]Span links to add at creation.

Synchronous

The span finishes when the callback returns. Any thrown error is automatically recorded on the span.
const tracer = require('dd-trace').init()

function handle (err) {
  tracer.trace('web.request', span => {
    // some code
  })
}

Callback (async)

Pass a second parameter done to the callback. The span finishes when done is called. Any error passed to done is automatically recorded.
function handle (err) {
  tracer.trace('web.request', (span, done) => {
    // some code
    done(err)
  })
}

Promise

Return a Promise from the callback. The span finishes when the promise resolves or rejects. Rejected promise errors are automatically recorded.
function handle () {
  return tracer.trace('web.request', () => {
    return new Promise((resolve, reject) => {
      // some code
    })
  })
}

Async/await

Return an async function or await inside the callback. The span lifecycle follows the returned promise.
async function handle () {
  return await tracer.trace('web.request', async () => {
    // some code
  })
}

With options

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

async function fetchUser (userId) {
  return await tracer.trace('user.fetch', {
    resource: `user:${userId}`,
    service: 'user-service',
    type: 'db',
    tags: { 'user.id': userId }
  }, async (span) => {
    const user = await db.query('SELECT * FROM users WHERE id = $1', [userId])
    span.setTag('user.found', user != null)
    return user
  })
}

tracer.wrap(name, [options], fn)

Returns a wrapped version of the provided function. Every time the wrapped function is called, tracer.trace() is called automatically. This is useful for patching functions that are defined elsewhere.

Type signatures

wrap<T = (...args: any[]) => any>(name: string, fn: T): T
wrap<T = (...args: any[]) => any>(name: string, options: TraceOptions & SpanOptions, fn: T): T
wrap<T = (...args: any[]) => any>(name: string, options: (...args: any[]) => TraceOptions & SpanOptions, fn: T): T

Basic usage

function handle () {
  // some code
}

const handleWithTrace = tracer.wrap('web.request', handle)

Callback functions

If the last argument of the wrapped function is a callback, the span finishes when that callback is called:
function handle (a, b, c, callback) {
  // some code
  callback()
}

const handleWithTrace = tracer.wrap('web.request', handle)

Dynamic options

Pass a function as options to compute trace options from the wrapped function’s arguments at call time:
const handleWithTrace = tracer.wrap(
  'user.fetch',
  (userId) => ({ resource: `user:${userId}` }),
  fetchUser
)

tracer.startSpan(name, [options])

For lower-level control, startSpan creates a span without activating it on the current scope. You are responsible for finishing it.
const span = tracer.startSpan('web.request', {
  childOf: tracer.scope().active()
})

try {
  // some code
} catch (err) {
  span.setTag('error', err)
  throw err
} finally {
  span.finish()
}
Unlike tracer.trace(), spans created with startSpan are not automatically activated on the scope. Use tracer.scope().activate() if you need child spans or automatic context propagation.

Build docs developers (and LLMs) love