dd-trace
    Preparing search index...

    dd-trace

    Datadog JavaScript Tracer API

    This is the API documentation for the Datadog JavaScript Tracer. If you are just looking to get started, check out the tracing setup documentation.

    Overview

    The module exported by this library is an instance of the Tracer class.

    Agentless mode

    Set DD_AGENTLESS_ENABLED=true to send supported telemetry directly to Datadog without a local Agent. Agentless mode disables features that require an Agent.

    Set the API key with DD_API_KEY or DATADOG_API_KEY. Agentless crash tracking requires this key and sends crash data directly to Datadog.

    Agentless mode uses the Datadog trace intake and ignores OTEL_TRACES_EXPORTER. Explicit DD_TRACE_SAMPLE_RATE, OTEL_TRACES_SAMPLER, OTEL_TRACES_SPAN_METRICS_ENABLED, and DD_METRICS_OTEL_ENABLED settings still apply.

    Agentless mode submits Bunyan, Pino, and Winston logs directly by default. During Test Optimization, it also submits best-effort formatted console.warn and console.error calls made with an active test, suite, or session span. Set DD_AGENTLESS_LOG_SUBMISSION_ENABLED=false to disable this behavior. Set DD_LOGS_OTEL_ENABLED=true to use the OpenTelemetry log exporter instead. Direct log submission takes precedence if both exporters are explicitly enabled. DD_AGENTLESS_LOG_SUBMISSION_URL overrides the Datadog logs intake URL.

    Feature Flag Configuration for SSR

    Use dd-trace/openfeature/rules-based to fetch rules and serialize configuration for browser initialization. These helpers do not initialize the tracer, register a provider, or enable tracking. The rules decoder is loaded only when this entrypoint is imported, not by dd-trace/openfeature or normal tracer or provider imports.

    import { fetchRulesConfiguration, configurationToString } from 'dd-trace/openfeature/rules-based.js'

    export async function getServerSideProps () {
    const configuration = await fetchRulesConfiguration({
    distributionChannel: 'client',
    clientToken: process.env.DD_CLIENT_TOKEN,
    env: process.env.DD_ENV,
    })

    return { props: { flagsConfiguration: configurationToString(configuration) } }
    }

    The browser can parse flagsConfiguration with configurationFromString from @datadog/openfeature-browser/rules-based and pass the result to DatadogCoreProvider.setConfiguration(). Use your framework's safe SSR data serialization; do not interpolate the string directly into HTML or a script.

    Only forward client-distributed configuration to browsers. The fetch helper defaults to the server distribution channel, which requires apiKey instead of clientToken. Serialization does not remove server-only flags. The helper accepts explicit env, optional site, timeoutMs (default 5000), signal, and custom fetch options; it does not inherit tracer configuration or read environment variables automatically. Catch ConfigurationFetchError to handle loading failures using its code and optional HTTP status.

    Use require('dd-trace/openfeature/rules-based') for CommonJS or named imports from dd-trace/openfeature/rules-based.js for native Node.js ESM.

    Feature Flag Exposure Logging

    Built-in Datadog exposure logging is enabled by default (DD_FEATURE_FLAGS_EXPOSURES_DATADOG_LOGGING_ENABLED=true). Set DD_FEATURE_FLAGS_EXPOSURES_DATADOG_LOGGING_ENABLED=false before tracer initialization to disable exposure buffering and delivery to Datadog in both agentless and Remote Configuration modes. Local flag evaluation and application OpenFeature hooks continue to work. Only false (case-insensitive) or 0 disables exposure logging. The tracer ignores unrecognized values.

    Disabling Datadog exposure delivery prevents experiment results from using those Datadog-collected exposures. If you log exposures separately to your data warehouse, warehouse-native analysis can use that source instead.

    This switch is independent of evaluation counts, which remain enabled by default. Evaluation events can include targeting keys. By default, valid non-empty keys are sent as unsalted SHA-256 hashes. When the flag configuration sets observeFullEvaluationData to true, events can include raw keys and a bounded evaluation-context snapshot. To disable aggregated flagevaluation events as well, also set DD_FLAGGING_EVALUATION_COUNTS_ENABLED=false. Span enrichment, OpenTelemetry evaluation metrics, and debug logging retain their own settings; this switch does not disable all Feature Flagging telemetry.

    Feature Flag Exposures in Your Own Data Store

    Use the ExposureHook to receive every feature flag evaluation with the same deduplication decision the tracer uses, so your application can record exposures in its own data store:

    const tracer = require('dd-trace').init()
    const { OpenFeature } = require('@openfeature/server-sdk')
    const { ExposureHook } = require('dd-trace/openfeature/exposure-hook')

    OpenFeature.addHooks(new ExposureHook((evaluation) => {
    if (!evaluation.shouldSend()) return
    // Queue for your own writer; the callback runs on the evaluation thread and must not do I/O.
    recordExposure({
    flag: evaluation.flagKey,
    variant: evaluation.variant,
    allocation: evaluation.allocation,
    targetingKey: evaluation.targetingKey,
    features: evaluation.getFeatures(),
    })
    }))

    await OpenFeature.setProviderAndWait(tracer.openfeature)

    Register the hook with OpenFeature.addHooks or on a client. The callback runs for every evaluation, including errors and repeats:

    • isExposure(): the evaluation succeeded and selected an allocation that logs exposures, whether or not this subject was already exposed.
    • isCacheHit(): this exposure repeats one already recorded for this subject (same flag, allocation, variant and serial id).
    • shouldSend(): a new or changed exposure; exactly what the tracer sends to Datadog.
    • getFeatures(): the read-only __dd_feature.<key> metadata of the selected split, such as holdout.key, holdout.assignment_group and holdout.should_include_in_holdout_analysis.

    The callback runs on the evaluation thread: hand the data to a background queue instead of writing it from the callback. An exception from the callback does not affect the evaluation; the first failure is logged at warn level and later ones at debug level.

    To stop sending exposures to Datadog while the hook keeps working, see Feature Flag Exposure Logging. The hook still receives every evaluation with the same shouldSend() decision, and exposure deduplication keeps running.

    Feature Flag Evaluation Events

    The tracer-managed Datadog OpenFeature provider emits aggregated flagevaluation track EVP events by default. Set DD_FLAGGING_EVALUATION_COUNTS_ENABLED=false to disable this collection. This setting does not disable flag evaluation, exposure events, span enrichment, or OpenTelemetry evaluation metrics.

    Privacy consent comes from observeFullEvaluationData in the flag configuration used for each evaluation:

    • Unless it is literally true, valid targeting keys are sent as unsalted SHA-256 hashes and evaluation context is omitted. Hashing is pseudonymization, not anonymity: a predictable targeting key can still be guessed and hashed.
    • With consent, events may include the raw targeting key and a bounded, flattened evaluation-context snapshot.
    • When aggregation reaches its identity-level limits, degraded rows omit targeting keys and context even with consent.
    • Events may include approved error codes, but never free-form evaluation error messages.

    The background worker starts with the first evaluation batch. Partial batches are scheduled after 20 ms when the application event loop can run. There is no public flush API for these events. Internal flush signals and graceful shutdown bypass the batching delay. On Node.js beforeExit, shutdown attempts to drain pending evaluations for up to five seconds. Diagnostic counters already recorded by the worker are collected before instrumentation telemetry's final send; counters produced during the subsequent drain may miss that send. Delivery is best-effort: process.exit(), terminating signals, crashes, and frozen runtimes can prevent the drain and lose pending events.

    The worker requires its JavaScript file and dependencies to be available at runtime. Bundling dd-trace into a single file does not automatically include the worker; the Datadog esbuild plugin does not currently package it. Keep dd-trace external to the bundle with its installed package available. If the worker cannot load, flagevaluation track EVP events are disabled for that provider and a bounded warning is logged; flag evaluations and existing exposure events continue.

    By default, the Datadog esbuild and webpack plugins inject DD_GIT_COMMIT_SHA and DD_GIT_REPOSITORY_URL into the bundle for Source Code Integration. Set DD_BUNDLER_INJECT_GIT_METADATA=false to skip that injection when you need stable artifact hashes across commits (for example, content-addressed Lambda deployments).

    Per-subject Evaluation Telemetry Opt-out

    Enable the context parameter before you first access tracer.openfeature:

    const tracer = require('dd-trace').init({
    featureFlags: {
    enableEvaluationTelemetryOptOutParameter: true
    }
    })
    const { OpenFeature } = require('@openfeature/server-sdk')
    await OpenFeature.setProviderAndWait(tracer.openfeature)
    const enabled = await OpenFeature.getClient().getBooleanValue('checkout', false, {
    targetingKey: 'subject-id',
    dd_evaluation_telemetry_opt_out: true
    })

    The option defaults to false. The provider captures it at construction. Only boolean true in the merged dd_evaluation_telemetry_opt_out context attribute suppresses new evaluation EVP events, OpenTelemetry evaluation metrics, and automatic flag span tags. Strings, numbers, null, missing attributes, and false keep existing behavior. You can also enable per-subject opt-out with DD_FEATURE_FLAGS_EVALUATION_TELEMETRY_PER_SUBJECT_OPT_OUT_ENABLED=true. Explicit configuration takes precedence over this environment variable, including false. This enables the context parameter; it does not disable evaluation telemetry globally.

    The attribute remains available to targeting rules and exposure reporting, whether this option is enabled or disabled. Changing it can affect assignments through targeting rules and can produce another exposure under normal deduplication rules.

    The telemetry control does not change flag values, variants, reasons, defaults, experiment exposures, exposure deduplication, or customer hooks. Set the subject attribute before evaluation. Changes from After or Error hooks are not a supported opt-out API. Previously queued events and span data remain available. Each evaluation has its own decision, including nested and concurrent calls. The option does not change protected/full-data reporting consent or debug logging.

    LLM Observability Experiments

    LLM Observability Experiments use a project name separate from the ML app name. Configure the default Experiments project when initializing the tracer:

    const tracer = require('dd-trace').init({
    llmobs: {
    projectName: 'experiments-project'
    }
    })

    The equivalent environment variable is DD_LLMOBS_PROJECT_NAME. If no project name is configured, Experiments uses default-project. The mlApp and service settings are not used as Experiments project-name fallbacks. Dataset and experiment operations can override the default with an operation-level projectName option, for example experiments.createDataset(name, { projectName: 'other-project' }) or experiments.experiment({ projectName: 'other-project', ... }).

    Automatic Instrumentation

    APM provides out-of-the-box instrumentation for many popular frameworks and libraries by using a plugin system. By default, all built-in plugins are enabled. Disabling plugins can cause unexpected side effects, so it is highly recommended to leave them enabled.

    Built-in plugins can be configured individually:

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

    // enable and configure postgresql integration
    tracer.use('pg', {
    service: 'pg-cluster'
    })

    LLM Observability integrations accept an llmobs option. Setting it to false stops LLM Observability span capture for that integration only — APM spans and distributed trace context propagation are unaffected. This is useful when another enabled integration already captures the same operation and the input/output payloads would otherwise be stored twice.

    The option is supported by ai, anthropic, aws-sdk (Bedrock Runtime only), claude-agent-sdk, google-cloud-vertexai, google-genai, langchain, langgraph, modelcontextprotocol-sdk, openai, openai-agents, and typesafe.

    // Keep APM tracing for OpenAI, but let another integration own the LLM Observability spans.
    tracer.use('openai', {
    llmobs: false
    })

    For Amazon Bedrock LLM Observability integrations, see the automatic instrumentation documentation.

    Available Plugins

    Manual Instrumentation

    If you aren’t using supported library instrumentation (see Compatibility), you may want to manually instrument your code.

    This can be done using the tracer.trace() and the tracer.wrap() methods which handle the span lifecycle and scope management automatically. In some rare cases the scope needs to be handled manually as well in which case the tracer.scope() method is provided.

    The different ways to use the above methods are described below.

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

    This method allows you to trace a specific operation at the moment it is executed. It supports synchronous and asynchronous operations depending on how it's called.

    Synchronous

    To trace synchronously, simply call tracer.trace() without passing a function to the callback.

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

    If an error is thrown in the callback, it will be automatically added to the span.

    Callback

    The most basic approach to trace asynchronous operations is to pass a function to the callback provided to the method.

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

    Errors passed to the callback will automatically be added to the span.

    Promise

    For promises, the span will be finished after the promise has been either resolved or rejected.

    function handle () {
    return tracer.trace('web.request', () => {
    return new Promise((resolve, reject) => {
    // some code
    })
    })
    }

    Any error from rejected promises will automatically be added to the span.

    Async/await

    For promises, the span lifecycle will be according to the returned promise.

    async function handle () {
    return await tracer.trace('web.request', async () => {
    // some code
    })
    }

    Any error from the awaited handler will automatically be added to the span.

    Recording handled exceptions

    Use span.recordException() to add a handled exception as an event without marking the span as failed.

    tracer.trace('checkout', span => {
    try {
    authorizePayment()
    } catch (error) {
    span.recordException(error, {
    handled: true,
    'payment.provider': 'example',
    })
    }
    })

    If the exception leaves the traced callback, tracer.trace() records it as a span error automatically.

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

    This method works very similarly to tracer.trace() except it wraps a function so that tracer.trace() is called automatically every time the function is called. This makes it easier to patch entire functions that have already been defined, or that are returned from code that cannot be edited easily.

    function handle () {
    // some code
    }

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

    Similar to tracer.trace(), it handles synchronous calls, callbacks, promises and async/await. The only difference being that if the last argument of the wrapped function is a callback, the span will only be finished when that callback is called.

    For example:

    function handle (a, b, c, callback) {
    // some code
    callback()
    }

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

    tracer.scope()

    In order to provide context propagation, this library includes a scope manager available with tracer.scope(). A scope is basically a wrapper around a span that can cross both synchronous and asynchronous contexts.

    In most cases, it's not necessary to interact with the scope manager since tracer.trace() activates the span on its scope, and uses the active span on the current scope if available as its parent. This should only be used directly for edge cases, like an internal queue of functions that are executed on a timer for example in which case the scope is lost.

    The scope manager contains 3 APIs available on tracer.scope():

    scope.active()

    This method returns the active span from the current scope.

    scope.activate(span, fn)

    This method activates the provided span in a new scope available in the provided function. Any asynchronous context created from within that function will also have the same scope.

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

    const requestSpan = tracer.startSpan('web.request')
    const promise = Promise.resolve()

    scope.activate(requestSpan, () => {
    log(scope.active()) // requestSpan because in new scope

    someFunction() // requestSpan because called in scope

    setTimeout(() => {
    log(scope.active()) // requestSpan because setTimeout called in scope
    })

    promise.then(() => {
    log(scope.active()) // requestSpan because then() called in scope
    })
    })

    function someFunction () {
    log(scope.active())
    }

    log(scope.active()) // null

    someFunction() // null because called outside the scope

    scope.bind(target, [span])

    This method binds a function to the specified span, or to the active span if unspecified.

    When a span is provided, the function is always bound to that span. Explicitly passing null as the span will actually bind to null or no span. When a span is not provided, the function is bound to the span that is active when scope.bind(fn) is called.

    Example
    const tracer = require('dd-trace').init()
    const scope = tracer.scope()
    const log = console.log

    const outerSpan = tracer.startSpan('web.request')

    scope.activate(outerSpan, () => {
    const innerSpan = tracer.startSpan('web.middleware')

    const boundToInner = scope.bind(() => {
    log(scope.active())
    }, innerSpan)

    const boundToOuter = scope.bind(() => {
    log(scope.active())
    })

    boundToInner() // innerSpan because explicitly bound
    boundToOuter() // outerSpan because implicitly bound
    })

    See the API documentation for more details.

    OpenTracing Compatibility

    This library is OpenTracing compliant. Use the OpenTracing API and the Datadog Tracer (dd-trace) library to measure execution times for specific pieces of code. In the following example, a Datadog Tracer is initialized and used as a global tracer:

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

    opentracing.initGlobalTracer(tracer)

    The following tags are available to override Datadog-specific options:

    • service.name: The service name to be used for this span. The service name from the tracer will be used if this is not provided.
    • resource.name: The resource name to be used for this span. The operation name will be used if this is not provided.
    • span.type: The span type to be used for this span. Will fallback to custom if not provided.

    OpenTelemetry Compatibility

    This library is OpenTelemetry compliant. Use the OpenTelemetry API and the Datadog Tracer (dd-trace) library to measure execution times for specific pieces of code. In the following example, a Datadog TracerProvider is registered with @opentelemetry/api:

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

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

    The following attributes are available to override Datadog-specific options:

    • service.name: The service name to be used for this span. The service name from the tracer will be used if this is not provided.
    • resource.name: The resource name to be used for this span. The operation name will be used if this is not provided.
    • span.type: The span type to be used for this span. Will fallback to custom if not provided.

    OpenTelemetry Logs

    dd-trace-js includes experimental support for OpenTelemetry logs, designed as a drop-in replacement for the OpenTelemetry SDK. This support is primarily intended for logging libraries rather than direct user configuration. Enable it by setting DD_LOGS_OTEL_ENABLED=true and use the OpenTelemetry Logs API to emit structured log data:

    require('dd-trace').init()
    const { logs } = require('@opentelemetry/api-logs')
    const express = require('express')

    const app = express()
    const logger = logs.getLogger('my-service', '1.0.0')

    app.get('/api/users/:id', (req, res) => {
    logger.emit({
    severityText: 'INFO',
    severityNumber: 9,
    body: `Processing user request for ID: ${req.params.id}`,
    })
    res.json({ id: req.params.id, name: 'John Doe' })
    })

    app.listen(3000)

    The Datadog SDK supports many of the configurations supported by the OpenTelemetry SDK. The following environment variables are supported:

    • DD_LOGS_OTEL_ENABLED - Enable OpenTelemetry logs (default: false)
    • OTEL_EXPORTER_OTLP_LOGS_ENDPOINT - OTLP endpoint URL for logs. Falls back to OTEL_EXPORTER_OTLP_ENDPOINT with /v1/logs appended (default: http://localhost:4318/v1/logs)
    • OTEL_EXPORTER_OTLP_LOGS_HEADERS - Optional headers for logs in JSON format. Falls back to OTEL_EXPORTER_OTLP_HEADERS (default: {})
    • OTEL_EXPORTER_OTLP_LOGS_PROTOCOL - OTLP protocol for logs. Options: http/protobuf, http/json. Falls back to OTEL_EXPORTER_OTLP_PROTOCOL (default: http/protobuf)
    • OTEL_EXPORTER_OTLP_LOGS_TIMEOUT - Request timeout in milliseconds for logs. Falls back to OTEL_EXPORTER_OTLP_TIMEOUT (default: 10000)
    • OTEL_BSP_SCHEDULE_DELAY - Batch export delay in milliseconds (default: 5000)
    • OTEL_BSP_MAX_EXPORT_BATCH_SIZE - Maximum logs per batch (default: 512)
    • OTEL_BSP_MAX_QUEUE_SIZE - Maximum logs to queue before dropping (default: 2048)

    For complete OTLP exporter configuration options, see the OpenTelemetry OTLP Exporter documentation.

    OpenTelemetry Metrics

    dd-trace-js includes experimental support for OpenTelemetry metrics, designed as a drop-in replacement for the OpenTelemetry Metrics SDK. This lightweight implementation is fully compliant with the OpenTelemetry Metrics API and integrates with the existing OTLP export infrastructure. Enable it by setting DD_METRICS_OTEL_ENABLED=true and use the OpenTelemetry Metrics API to record metric data:

    require('dd-trace').init()
    const { metrics } = require('@opentelemetry/api')

    const meterProvider = metrics.getMeterProvider()
    const meter = meterProvider.getMeter('my-service', '1.0.0')

    // Counter - monotonically increasing values
    const requestCounter = meter.createCounter('http.requests', {
    description: 'Total HTTP requests',
    unit: 'requests'
    })
    requestCounter.add(1, { method: 'GET', status: 200 })

    // Histogram - distribution of values
    const durationHistogram = meter.createHistogram('http.duration', {
    description: 'HTTP request duration',
    unit: 'ms'
    })
    durationHistogram.record(145, { route: '/api/users' })

    // UpDownCounter - can increase and decrease
    const connectionCounter = meter.createUpDownCounter('active.connections', {
    description: 'Active connections',
    unit: 'connections'
    })
    connectionCounter.add(1) // New connection
    connectionCounter.add(-1) // Connection closed

    // ObservableGauge - asynchronous observations
    const cpuGauge = meter.createObservableGauge('system.cpu.usage', {
    description: 'CPU usage percentage',
    unit: 'percent'
    })
    cpuGauge.addCallback((result) => {
    const cpuUsage = process.cpuUsage()
    result.observe(cpuUsage.system / 1000000, { core: '0' })
    })

    Short-lived processes can call meterProvider.shutdown(callback) after the final measurement to export once more and stop collection. The optional callback receives null on success or an error on failure. This method isn't part of the OpenTelemetry Metrics API. In TypeScript, intersect the provider type with import('dd-trace').opentelemetry.MeterProvider to use it.

    The Datadog SDK supports many of the configurations supported by the OpenTelemetry SDK. The following environment variables are supported:

    • DD_METRICS_OTEL_ENABLED - Enable OpenTelemetry metrics (default: false)
    • OTEL_EXPORTER_OTLP_METRICS_ENDPOINT - OTLP endpoint URL for metrics. Falls back to OTEL_EXPORTER_OTLP_ENDPOINT with /v1/metrics appended (default: http://localhost:4318/v1/metrics)
    • OTEL_EXPORTER_OTLP_METRICS_HEADERS - Optional headers for metrics in JSON format. Falls back to OTEL_EXPORTER_OTLP_HEADERS (default: {})
    • OTEL_EXPORTER_OTLP_METRICS_PROTOCOL - OTLP protocol for metrics. Options: http/protobuf, http/json. Falls back to OTEL_EXPORTER_OTLP_PROTOCOL (default: http/protobuf)
    • OTEL_EXPORTER_OTLP_METRICS_TIMEOUT - Request timeout in milliseconds for metrics. Falls back to OTEL_EXPORTER_OTLP_TIMEOUT (default: 10000)
    • OTEL_METRIC_EXPORT_INTERVAL - Metric export interval in milliseconds (default: 10000)
    • OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE - Aggregation temporality preference. Options: CUMULATIVE, DELTA, LOWMEMORY (default: DELTA). See OpenTelemetry spec for details
    • OTEL_BSP_MAX_QUEUE_SIZE - Maximum metrics to queue before dropping (default: 2048)
    • OTEL_METRIC_EXPORT_TIMEOUT - [NOT YET SUPPORTED] Time to export metrics including retries

    For complete OTLP exporter configuration options, see the OpenTelemetry OTLP Exporter documentation.

    Advanced Configuration

    Tracer settings

    Options can be configured as a parameter to the init() method or as environment variables. These are documented over on Configuring the Node.js Tracing Library.

    Test Optimization settings

    Failure screenshot and video uploads are enabled by default for supported browser test integrations and transports. When DD_TEST_FAILURE_SCREENSHOTS_ENABLED or DD_TEST_FAILURE_VIDEOS_ENABLED is unset, Playwright and Cypress must be configured to capture the corresponding media. Explicitly setting a flag to true also enables its capture in Playwright (1.38.0 or later) and Cypress. Playwright uses only-on-failure screenshots and retain-on-failure videos unless the project already captures failures; existing capture options are preserved. Cypress enables screenshotOnRunFailure or video. Setting either flag to false disables that upload without modifying the framework's capture settings. The flags operate independently. Only automatic failure media is uploaded.

    For WebdriverIO 9 and later with the Mocha or Jasmine adapter, explicitly set DD_TEST_FAILURE_VIDEOS_ENABLED=true to record and upload failure videos automatically. Install FFmpeg with the libvpx encoder and make the ffmpeg executable available on the WDIO worker's PATH. Check the installation with ffmpeg -version and ffmpeg -encoders. No WebdriverIO video reporter or additional dd-trace npm dependency is required. Encoding runs in a separate process and only for failed attempts. If FFmpeg is unavailable, recording is disabled and a warning is logged. When videos are enabled and both FFmpeg and video uploads are available, dd-trace defaults new sessions to unhandledPromptBehavior: 'ignore' so background screenshots preserve open dialogs. Explicit prompt policies are preserved. Recording is disabled with a warning if any session's negotiated policy allows screenshots to accept or dismiss dialogs. Policies are checked before each capture; reloading a session with an unsafe policy discards the active recording. Tests must handle their dialogs; other WebDriver commands no longer automatically dismiss them under the ignore policy.

    WebdriverIO recordings are screenshot sequences encoded as WebM, using the approach of wdio-video-reporter. They capture browser command results and sample idle periods every 500ms; browser dialogs and native UI outside screenshots are not recorded. Each failed attempt, including retries and test hook failures, gets its own upload. Passing and skipped attempts are discarded. Multiremote sessions produce separate videos for the same attempt. Videos are limited to 1280×720 pixels and use two frames per second. Temporary frames and videos are removed after completion. Raw frames share a 200 MiB budget per WDIO worker across capturing, encoding, and uploading attempts, released after file cleanup, with a limit of 16 megapixels per screenshot. Capture, encoding, or upload failures do not fail the test run.

    Set DD_CODE_COVERAGE_FLAGS to a comma-separated list of flags to attach to uploaded code coverage reports. Whitespace around each flag is removed and empty entries are ignored. Up to 32 flags are accepted; if more are provided, the report is uploaded without flags.

    Set DD_TEST_EARLY_FLAKE_DETECTION_RETRY_COUNT to a non-negative integer to override the number of Early Flake Detection retries in every supported test-duration bucket. A value of 0 disables EFD retries. Tests that run for at least five minutes are not retried. When the variable is unset, the backend-provided duration-based retry policy applies.

    Set DD_CIVISIBILITY_DYNAMIC_ATR_ENABLED=true to enable dynamic Auto Test Retries budgets based on test duration, instead of the flat per-test retry limit. When enabled, the number of retries allowed for a test is determined by the duration of its initial attempt. Dynamic ATR uses inclusive upper bounds of 5s, 10s, 30s, and 5m, followed by a >5m bucket. EFD retains its exclusive upper bounds. Requires Auto Test Retries to be enabled by the backend. For Mocha, dynamic ATR requires version 8 or newer. Older supported versions use the flat retry limit.

    Set DD_CIVISIBILITY_DYNAMIC_ATR_BUCKETS to a comma-separated list of five positive integers in [1, 20] overriding the five duration-based Auto Test Retries budgets (for the 5s, 10s, 30s, 5m, and >5m buckets respectively). When unset, empty, or invalid, the Early Flake Detection retry settings from the backend are used with a minimum of one ATR retry. Local EFD retry-count overrides do not affect dynamic ATR. Only takes effect when DD_CIVISIBILITY_DYNAMIC_ATR_ENABLED is enabled.

    Set DD_TEST_MANAGEMENT_REPORT_ENABLED=false to hide the end-of-session Test Management report from CI logs. The report is enabled by default. Disabling the report does not disable Test Management or change whether tests are disabled, quarantined, or run in Attempt to Fix mode.

    Custom Logging

    By default, logging from this library is disabled. In order to get debugging information and errors sent to logs, the DD_TRACE_DEBUG env var should be set to true.

    The tracer will then log debug information to console.log() and errors to console.error(). This behavior can be changed by passing a custom logger to the tracer. The logger should contain a debug() and error() methods that can handle messages and errors, respectively.

    For example:

    const bunyan = require('bunyan')
    const logger = bunyan.createLogger({
    name: 'dd-trace',
    level: 'trace'
    })

    process.env.DD_TRACE_DEBUG = 'true'

    const tracer = require('dd-trace').init({
    logger: {
    error: err => logger.error(err),
    warn: message => logger.warn(message),
    info: message => logger.info(message),
    debug: message => logger.trace(message),
    }
    })

    Span Hooks

    In some cases, it's necessary to update the metadata of a span created by one of the built-in integrations. This is possible using span hooks registered by integration. Each hook provides the span as the first argument and other contextual objects as additional arguments.

    For example:

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

    tracer.use('express', {
    hooks: {
    request: (span, req, res) => {
    span.setTag('customer.id', req.query.id)
    }
    }
    })

    Right now this functionality is limited to Web frameworks.

    More information on which hooks are supported for each integration can be found in each individual plugins.

    User Identification

    The tracer provides a convenience function to link an actor to a trace. For example to correlate users to web requests. You have to pass an object with at least an id property.

    For example:

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

    function handle () {
    tracer.setUser({
    id: '123456789', // *REQUIRED* Unique identifier of the user.

    // All other fields are optional.
    email: 'jane.doe@example.com', // Email of the user.
    name: 'Jane Doe', // User-friendly name of the user.
    session_id: '987654321', // Session ID of the user.
    role: 'admin', // Role the user is making the request under.
    scope: 'read:message, write:files', // Scopes or granted authorizations the user currently possesses.

    // Arbitrary fields are also accepted to attach custom data to the user (RBAC, Oauth, etc…)
    custom_tag: 'custom data'
    })
    }

    Mocha supports the same preventFailureSuppression and noAutoRetry callback annotations from dd-trace/ci/test-annotations shown below for Jest. Apply them to it, test, and parameterized callbacks, including only and skip declarations. The annotations are preserved in serial and parallel workers. Native Mocha retries remain available when noAutoRetry excludes Datadog ATR, EFD, and Attempt to Fix.

    Use the native Gherkin tags @datadog:prevent_failure_suppression and @datadog:no_auto_retry on a Scenario or Scenario Outline. Outline tags apply to every example. These are tracer declaration annotations, resolved before Datadog disabling, quarantine, ATR, EFD, and Attempt to Fix. Explicit --retry settings remain available. Parallel Test Management exclusions require Cucumber 11 or later, which exposes the worker runTestCase lifecycle; serial scenarios support Cucumber 7 or later. Cucumber's normal tag selection and dry runs still apply. The annotation and assigned Test Management span tags follow the callback API below.

    Playwright 1.38 and later support the preventFailureSuppression and noAutoRetry callback annotations from dd-trace/ci/test-annotations. Apply them to individual test callbacks, including generated cases, test.only, and test.skip. Callback fixture parameters remain available. Exclusions are resolved in the coordinator before disabling and retries; worker spans retain both annotation and backend assignment tags. Explicit project and suite retry settings remain available. Playwright retries serial groups together, so a group containing noAutoRetry also excludes Datadog automatic retries for its other members. Explicit native group and project retries remain available.

    With the jest-circus runner, annotate test callbacks using dd-trace/ci/test-annotations:

    const { preventFailureSuppression, noAutoRetry } = require('dd-trace/ci/test-annotations')

    test('critical check', preventFailureSuppression(noAutoRetry(() => {
    expect(check()).toBe(true)
    })))

    test.each(cases)('critical case %s', preventFailureSuppression(value => {
    expect(check(value)).toBe(true)
    }))

    preventFailureSuppression(callback) prevents Datadog quarantine and disabling from applying to that callback. It does not override Test Impact Analysis, developer skips, or test selection, and does not prevent retries.

    noAutoRetry(callback) prevents Datadog Auto Test Retries, Early Flake Detection retries, and Attempt to Fix retries. It does not turn off test discovery or flakiness reporting. Explicit jest.retryTimes(...) calls remain available. To protect a failure from both quarantine/disable and automatic retries, combine the helpers.

    Each helper returns an annotated callback without modifying the original. Callback arguments, return values, errors, this, and arity are preserved. Apply the helper to the callback passed to test.each to protect every case. The helpers can be imported without initializing the tracer; enforcement requires the corresponding test framework instrumentation.

    Test events report test.test_management.prevent_failure_suppression and test.test_management.no_auto_retry as true when the corresponding annotation is present; absent annotations omit the tag. These describe annotations observed on that execution, on any branch. Management-property tags retain backend assignments even when annotations override their runtime behavior. Default-branch synchronization and UI restrictions require backend support; these helpers do not update remote test properties. Files skipped by Test Impact Analysis produce no new observation.

    Framework support is described in the framework-specific sections. The legacy Jest Jasmine runner does not enforce these helpers.

    Annotate callbacks with preventFailureSuppression and noAutoRetry from dd-trace/ci/test-annotations. These declarations apply to all generated test.each cases and work with Vitest's test modifiers, worker processes and supported browser/no-worker modes. Annotation flags travel with test task metadata before Vitest replaces callbacks for fixtures or parameterization.

    Protection overrides Datadog quarantine/disabling; retry exclusion blocks Datadog ATR, EFD and Attempt to Fix. Explicit native retries on a test or suite remain available and are reported as framework retries. Developer skips and TIA retain their ordinary selection semantics. Backend-assigned property tags remain visible when the execution policy is overridden; observed annotation tags are true-only.

    With Cypress 12 and later, annotate the callback passed to it or specify using preventFailureSuppression and noAutoRetry from dd-trace/ci/test-annotations. Both helpers compose in the same way as the Jest examples above. Skipped declarations, loop-generated cases, and allowed native retries retain their annotation tags.

    preventFailureSuppression overrides Datadog quarantine and disabling while preserving normal test selection, explicit skips, and Test Impact Analysis. noAutoRetry excludes Datadog ATR, EFD, and Attempt to Fix. Explicit Cypress retries configured on a test, suite, or globally remain available and are reported as framework retries. Test isolation must remain enabled for Datadog automatic retry controls to apply.

    Management tags continue to describe backend assignments. Annotation tags describe the observed callback, and effective execution/final status follows the exclusions.

    With the WebdriverIO Mocha or Jasmine adapter (WebdriverIO 9 and later), apply preventFailureSuppression and noAutoRetry from dd-trace/ci/test-annotations to callbacks passed to it or xit. The helpers compose as in the Jest example. They apply to every declaration generated in a loop and retain annotation tags on explicit skips and permitted native retries.

    preventFailureSuppression overrides Datadog quarantine and disabling without blocking retries. noAutoRetry excludes Datadog ATR, EFD, and Attempt to Fix; native Mocha retries and explicit WebdriverIO Jasmine retries remain available and are reported as framework retries. Both helpers preserve ordinary selection and expected-failure behavior. Management property tags retain backend assignments even when their execution policy is overridden.