Datadog Python APM Tracer (ddtrace)

raw JSON →
4.6.4 verified Tue May 12 auth: no python install: verified quickstart: stale

Datadog APM Python tracing library. Current version: 4.6.4 (Mar 2026). Three breaking major versions since 2023: v2 (dropped Python 2.7/3.5/3.6, removed DD_CALL_BASIC_CONFIG), v3 (dropped Python 3.7, removed deprecated config names), v4 (dropped Python 3.8, removed Pin class, removed Span.set_tag_str, removed ddtrace.settings package). Preferred usage is ddtrace-run CLI wrapper — NOT importing patch_all() in code. Requires Datadog Agent running separately. Auto-instrumentation patches libraries at import time.

pip install ddtrace
error Failed to send traces to Datadog Agent...: ConnectionRefusedError(111, 'Connection refused')
cause The `ddtrace` library cannot connect to the Datadog Agent, usually because the Agent is not running, is on a different host/port than configured, or its connection limit has been reached.
fix
Ensure the Datadog Agent is running and accessible from the application host. Verify DD_TRACE_AGENT_URL (or DD_AGENT_HOST and DD_AGENT_PORT) environment variables are correctly set to the Agent's address. Use ddtrace-run --info to check the tracer's connection to the agent.
error ModuleNotFoundError: No module named 'Cython'
cause This error occurs during `ddtrace` installation, indicating that `pip` is having trouble building the `ddtrace` package due to a missing `Cython` module or an outdated `pip` version.
fix
Upgrade your pip version to 18 or newer using pip install -U pip>=18.
error Pin.app is removed.
cause The `Pin.app` attribute, along with `Pin.app_type`, was removed in `ddtrace` v4.x as part of API simplification. The `ddtrace.settings` package was also removed.
fix
Migrate your configuration to use environment variables or direct integration configurations instead of Pin.app. For instance, configure service names and other tracing metadata via DD_SERVICE or integration-specific environment variables.
error Repeated calls to patch_all() eventually seem to infinite loop
cause Calling `ddtrace.patch_all()` multiple times within an application, especially in test suites or certain framework setups, can lead to unexpected behavior including infinite loops in `ddtrace` versions 2.15.1 and later.
fix
Ensure ddtrace.patch_all() is called only once during application startup. Implement a guard to prevent multiple invocations, or leverage ddtrace-run which handles patching automatically.
error ddtrace 3.18.1 fails to import on Python 3.14.0 due to attempting to access asyncio.events.BaseDefaultEventLoopPolicy
cause In `ddtrace` versions prior to Python 3.14 compatibility fixes, the library attempted to access a private `asyncio` attribute (`asyncio.events.BaseDefaultEventLoopPolicy`) which was renamed to `_BaseDefaultEventLoopPolicy` in Python 3.14.
fix
Upgrade ddtrace to a version that supports Python 3.14 (e.g., v4.x or a later v3.x release that includes the compatibility fix).
breaking v4.0.0 dropped Python 3.8. v3.0.0 dropped Python 3.7. v2.0.0 dropped Python 2.7/3.5/3.6. Check Python version before upgrading major versions.
fix v4 requires Python 3.9+. v3 requires Python 3.8+. v2 requires Python 3.7+.
breaking Pin class removed in v4.0. Code using Pin.get_from(), Pin.override(), ddtrace.Pin raises ImportError.
fix Remove Pin usage. Configure integrations via environment variables or ddtrace.config instead.
breaking Span.set_tag_str() removed in v4.0. Raises AttributeError.
fix Use span.set_tag('key', 'value') for all tag types.
breaking ddtrace.settings package removed in v4.0. Code importing from ddtrace.settings raises ImportError.
fix Use environment variables (DD_TRACE_*, DD_SERVICE, etc.) for configuration.
breaking patch_all() and patch() must be called BEFORE the library being instrumented is imported. Calling after import silently produces no instrumentation.
fix Use ddtrace-run CLI wrapper which handles import order automatically.
breaking DD_CALL_BASIC_CONFIG removed in v2.0. Raises error if set.
fix Remove DD_CALL_BASIC_CONFIG from environment. ddtrace now logs to stdout by default.
gotcha Datadog Agent must be running at localhost:8126 (default). Without it, traces are silently dropped — no error raised.
fix Run Datadog Agent before starting app. Verify with: ddtrace-run --info. Override with DD_AGENT_HOST and DD_TRACE_AGENT_PORT.
gotcha Unified Service Tagging requires DD_SERVICE, DD_ENV, DD_VERSION env vars. Without them, services appear as unnamed in Datadog UI.
fix Set DD_SERVICE=my-service DD_ENV=production DD_VERSION=1.0.0 before running.
breaking Calling `ddtrace.patch(all=True)` is incorrect and will raise `ddtrace._monkey.ModuleNotFoundException`. The `patch` function expects specific integration names as keyword arguments (e.g., `patch(flask=True)`).
fix Use `ddtrace.patch_all()` to instrument all available integrations, or specify individual integrations using `ddtrace.patch(integration_name=True, ...)`.
breaking Calling ddtrace.patch(all=True) is incorrect and will raise a ModuleNotFoundException. 'all' is not a valid module name for selective patching.
fix Use ddtrace.patch_all() to instrument all available integrations, or ddtrace.patch('integration_name') for specific ones.
python os / libc status wheel install import disk
3.10 alpine (musl) - - - 58.8M
3.10 slim (glibc) - - - 55M
3.11 alpine (musl) - - - 64.0M
3.11 slim (glibc) - - - 61M
3.12 alpine (musl) - - - 55.1M
3.12 slim (glibc) - - - 52M
3.13 alpine (musl) - - - 54.8M
3.13 slim (glibc) - - - 52M
3.9 alpine (musl) - - - 58.3M
3.9 slim (glibc) - - - 55M

ddtrace — auto-instrumentation via ddtrace-run and custom spans.

# pip install ddtrace
# Requires Datadog Agent running at localhost:8126

# Option 1: ddtrace-run (recommended)
# DD_SERVICE=my-app DD_ENV=prod ddtrace-run python app.py

# Option 2: manual patch at top of entry point (before all other imports)
from ddtrace import patch
patch(all=True)  # must be before any library imports

# OR selectively:
# patch(requests=True, sqlalchemy=True, redis=True)

import flask  # patched because patch() was called first

from ddtrace import tracer

app = flask.Flask(__name__)

@app.route('/checkout')
def checkout():
    with tracer.trace('checkout.process', resource='checkout') as span:
        span.set_tag('user.id', flask.request.args.get('user_id'))
        # Unified Service Tagging via env vars:
        # DD_SERVICE, DD_ENV, DD_VERSION
        return 'ok'

# Check agent connectivity:
# ddtrace-run --info