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 Common errors
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). Warnings
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.
Install compatibility verified last tested: 2026-05-12
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
Imports
- ddtrace-run (preferred — auto-instrumentation) wrong
# Wrong: patch_all() called after imports — too late to instrument import flask import sqlalchemy from ddtrace import patch_all patch_all() # flask and sqlalchemy already imported — not patched # Wrong: calling patch() inside app factory — same issue def create_app(): from ddtrace import patch patch(flask=True) # flask already imported abovecorrect# Preferred: use ddtrace-run CLI wrapper # This patches libraries at startup before your code imports them # Set env vars: # DD_SERVICE=my-service # DD_ENV=production # DD_VERSION=1.0.0 # DD_AGENT_HOST=localhost (default) # DD_TRACE_AGENT_PORT=8126 (default) # Run your app: # ddtrace-run python app.py # ddtrace-run gunicorn app:application # ddtrace-run uvicorn app:app # Verify config: # ddtrace-run --info - Manual tracing (custom spans) wrong
# Wrong in v4: Pin class removed from ddtrace import Pin Pin.override(my_client, service='my-svc') # ImportError in v4 # Wrong in v4: set_tag_str removed span.set_tag_str('key', 'value') # AttributeError in v4 — use set_tag()correctfrom ddtrace import tracer # Custom span with tracer.trace('my.operation', service='my-service', resource='checkout') as span: span.set_tag('user.id', '123') span.set_tag('order.id', 'ord-456') # do work # Decorator from ddtrace import tracer @tracer.wrap(service='my-service', resource='process_payment') def process_payment(order_id): pass # Error tracking try: risky_operation() except Exception as e: span.error = 1 span.set_tag('error.msg', str(e)) raise
Quickstart stale last tested: 2026-04-23
# 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