dd-trace: Datadog APM Tracer for Node.js
dd-trace is the official Datadog APM tracing client library for Node.js applications, designed to automatically and manually capture performance monitoring data. It provides distributed tracing capabilities, allowing developers to instrument their Node.js services to gain insights into request lifecycles, identify bottlenecks, and monitor service health within the Datadog platform. The current stable release line is `v5`, with the latest version being `5.97.0`. Datadog maintains a regular release cadence for patch and minor versions, often weekly or bi-weekly, to introduce new features, improvements, and bug fixes, while major versions are released less frequently, with `v5` being released in January 2024. A key differentiator is its deep integration with the Datadog ecosystem, offering automatic instrumentation for popular Node.js frameworks and libraries, support for Single-Step Install (SSI), and Kubernetes Injection. It requires a Datadog Agent to be running to collect and forward the captured trace data.
Common errors
-
Error: dd-trace requires Node.js >=18
cause Attempting to run dd-trace v5 on an unsupported Node.js version.fixUpgrade Node.js to version 18 or higher. Alternatively, if upgrading Node.js is not possible, install an older, compatible major version of `dd-trace` (e.g., `npm install dd-trace@4` for Node.js >=16). -
[dd-trace] No agent could be found. Traces will be dropped.
cause The Datadog Agent is not running, is not accessible at the configured host/port, or firewall rules are blocking communication.fixStart the Datadog Agent. Ensure `DD_AGENT_HOST` and `DD_AGENT_PORT` environment variables are correctly set, pointing to the agent's location. Verify network connectivity and firewall rules between your application and the agent. -
TypeError: Cannot read properties of undefined (reading 'startSpan')
cause `tracer.init()` was not called before attempting to use tracing methods, or the `tracer` object was not correctly imported/referenced.fixEnsure `tracer.init()` is called once at the very beginning of your application's entry point, preferably before any other modules are loaded, and that the `tracer` object is properly imported and available where `startSpan` is invoked.
Warnings
- breaking Older `dd-trace` major versions (v1, v2, v3, v4) are End-of-Life (EOL). Continuing to use these versions means no new features, bug fixes, or critical security updates.
- breaking `dd-trace` v5 requires Node.js version 18 or higher. Using it with older Node.js versions will result in immediate startup errors or unpredictable runtime behavior due to reliance on modern Node.js APIs.
- gotcha The `dd-trace` library critically depends on a running and accessible Datadog Agent to send traces. If the agent is not available at the configured host and port, traces will be buffered for a short period and then dropped, leading to missing APM data.
- gotcha Careless or excessive manual instrumentation, especially in performance-critical code paths, can introduce noticeable overhead. Similarly, enabling `debug: true` or very verbose logging in production environments can severely impact performance.
- gotcha Automatic instrumentation may conflict with other APM agents or custom module patching, leading to unexpected behavior or incomplete traces. This is particularly true in environments with multiple observability tools.
Install
-
npm install dd-trace -
yarn add dd-trace -
pnpm add dd-trace
Imports
- tracer.init
const tracer = require('dd-trace'); // Forget to call .init()import tracer from 'dd-trace'; tracer.init();
- tracer.startSpan
import { startSpan } from 'dd-trace';import tracer from 'dd-trace'; const span = tracer.startSpan('my.operation'); - Span
import { Span } from 'dd-trace';import type { Span, SpanOptions } from 'dd-trace';
Quickstart
import tracer from 'dd-trace';
import express from 'express';
// Initialize the Datadog tracer early in your application lifecycle.
// Configuration can also be done via environment variables (DD_SERVICE, DD_ENV, DD_VERSION).
tracer.init({
service: process.env.DD_SERVICE || 'my-node-app',
env: process.env.DD_ENV || 'development',
version: process.env.DD_VERSION || '1.0.0',
logInjection: true,
debug: false // Set to true for verbose logging
});
const app = express();
const port = process.env.PORT || 3000;
app.get('/', async (req, res) => {
// Automatic instrumentation will create a span for the Express request.
// We can also create a custom span manually within it.
const customSpan = tracer.startSpan('custom.db.query', {
tags: { 'db.name': 'users_db', 'db.statement': 'SELECT * FROM users' }
});
try {
await new Promise(resolve => setTimeout(resolve, 100)); // Simulate async DB call
customSpan.addTags({ 'db.row_count': 5, 'http.status_code': 200 });
res.send('Data retrieved successfully via Datadog Tracing!');
} catch (error) {
customSpan.setTag('error', true);
customSpan.log({ 'event': 'error', 'error.message': error.message });
res.status(500).send('Error during data retrieval!');
} finally {
customSpan.finish();
}
});
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
console.log(`Datadog Tracer initialized for service: ${tracer.dogstatsd.service}`);
console.log(`Ensure a Datadog Agent is running and accessible at DD_AGENT_HOST:${process.env.DD_AGENT_PORT || 8126}`);
});