Estimated end-of-life date, accurate to within three months: 05-2027
See the support level definitions for more information.
Upgrade Notes
- LLM Observability
- when APM and LLMObs are both enabled, the APM trace writer now uses the
v0.4trace API version (v0.5cannot carry the LLMObs span data). SettingDD_TRACE_API_VERSION=v0.5with LLMObs enabled logs a warning and downgrades tov0.4. No user action is required.
- when APM and LLMObs are both enabled, the APM trace writer now uses the
- ASM
- This upgrades libddwaf to 2.0.0.
New Features
- AI Guard
- This introduces the
DD_AI_GUARD_OPENAI_ENABLEDenvironment variable (trueby default) as a per-provider kill switch. Set it tofalseto disable AI Guard auto-instrumentation of the OpenAI SDK without affecting other providers or requiring a tracer version rollback. - add AI Guard support for LangChain 1.0+ agents built with
create_agent. - Added opt-in evaluation of streamed OpenAI Chat Completions and Responses via
DD_AI_GUARD_ANALYZE_STREAM_RESPONSES_ENABLED(default off); streams are buffered and evaluated before any chunk is delivered, raisingAIGuardAbortErroron a block. - This introduces AI Guard standalone mode. When APM tracing is disabled (
DD_APM_TRACING_ENABLED=false), traces produced by AI Guard are still sent to Datadog, kept withUSER_KEEPsampling priority and the AI Guard decision maker so that they can be attributed to AI Guard, while APM host billing is not triggered. - Add opt-in buffered stream response evaluation for AI Guard on Anthropic streaming calls. When
DD_AI_GUARD_ANALYZE_STREAM_RESPONSES_ENABLED=true(defaultfalse), all streamed chunks are buffered, the full assistant response is evaluated by AI Guard, and chunks are replayed to the caller only after an ALLOW verdict. On DENY/ABORT,AIGuardAbortErroris raised and zero chunks are delivered. When the flag is off (the default), streaming behavior is unchanged.
- This introduces the
- AAP
- Adds the normalized HTTP route span tag (
_dd.appsec.normalized_route) for Tornado, following RFC-1103 and the existing FastAPI, Starlette, Django, and Flask implementations. The tag is emitted on every request span that already carrieshttp.routewhen the API Security feature is active. Tornado routes using named capturing groups ((?P<name>...)) produce named parameters (e.g./users/{id}); positional groups produce auto-numbered placeholders (e.g.{param1}). Optional trailing-slash patterns (/?) are treated as not declaring a trailing slash per RFC-1103 rule 1. #18398
- Adds the normalized HTTP route span tag (
- AppSec:
- Detect OpenAI LLM usage within API endpoints. When AppSec is enabled and an OpenAI
chat.completions,completions, orresponsescall is made during a web request, the WAF addressserver.business_logic.llm.eventis emitted with the provider and model name. This enables WAF rules to tag the trace withappsec.events.llm.call.providerandappsec.events.llm.call.model, surfacing LLM-backed endpoints in the API Endpoint Catalog. Supports both sync and async OpenAI clients, Azure OpenAI (enginekwarg), and streaming. Only the first LLM call per request is recorded (endpoint-level detection, not per-invocation).
- Detect OpenAI LLM usage within API endpoints. When AppSec is enabled and an OpenAI
- aws_durable_execution_sdk_python
- Add
aws.durable.operation_attempttag toaws.durable.stepandaws.durable.wait_for_conditionspans. The tag is0for the original attempt and1,2, etc. for each subsequent retry.
- Add
- ray_serve
- Adds instrumentation support for
ray[serve]>=2.47.1. When Ray is instrumented, ddtrace now traces Serve HTTP and gRPC requests, deployment routing, deployment method execution, and calls made withDeploymentHandle.remote(), with distributed trace context propagated across Serve deployments. See the Ray documentation for more information. #18076
- Adds instrumentation support for
- LLM Observability
- This introduces support for attaching audio to messages on LLM spans. Input and output messages annotated via
LLMObs.annotatenow accept an optionalaudio_partsfield, a list of audio segments each with amime_typeand either inline base64contentor anattachment_key. This lets audio (for example, speech-to-text and text-to-speech payloads) be collected and rendered in LLM Observability. - Added a
sample_rateargument toLLMObs.enable()to configure the proportion of LLMObs traces to sample (between0.0and1.0) in code. This takes precedence over theDD_LLMOBS_SAMPLE_RATEenvironment variable. - Add
SyncExperiment.rerun_evaluators()to re-run evaluators on the stored task outputs from a previous experiment run without re-executing the task function. Reads fromexperiment.result(set byrun()orpull()) and returns a newSyncExperimentwith fresh evaluations while preserving original span IDs, trace IDs, inputs, and outputs via replay span copies linked back to the originals viaparent_experiment_span_id. Themissing_task_strategyparameter controls behavior when prior rows contain errors:"raise"(default) raises immediately,"skip"omits the row, and"retry"re-executes the task for that row. - LLM span data can now be exported to the Datadog Agent over the APM trace, and is reliably delivered even when the APM trace is not sampled. This has no effect on APM sampling decisions or billing.
- The OpenAI integration now captures input and output audio on audio chat completions (any audio-capable Chat Completions model, e.g.
gpt-audio,gpt-audio-mini,gpt-4o-audio-preview) asaudio_partson LLM span messages. Note: audio in streamed responses (stream=True) is not captured yet. - Adds support for
DD_LLMOBS_SAMPLE_RATE, which controls the proportion of LLM Observability spans (between0.0and1.0, defaults to1.0) that are retained. This does not affect APM span retention or the accuracy of LLM Observability metrics such as token usage, and cost. - Adds span
metadatato the data exposed to the span processor registered withLLMObs.enable(span_processor=...)orLLMObs.register_processor(...). Previously onlyinputandoutputwere exposed; the processor can now read and modifymetadatato redact or remove sensitive values that integrations record there. - Adds support for submitting LLM Observability spans for
mistralaiclient chat and embedding calls.
- This introduces support for attaching audio to messages on LLM spans. Input and output messages annotated via
- profiling
- implement heap live count data collection
- The adaptive sampling mechanism has been revamped to better match the needs of real-life workloads.
- The PyTorch profiler now properly shows nested frames in flame graphs.
- mistralai
- Adds tracing support for the
mistralaiclient chat and embedding calls.
- Adds tracing support for the
- pytorch
- Adds a
pytorch.ranklifetime span for PyTorch distributed training. The span opens atinit_process_groupand closes atdestroy_process_groupor process exit. Tags includerank,world_size,framework(DDP / FSDP / DeepSpeed),launcher,torch.distributed.backend, andtraining_job_id(resolved from launcher environment variables). When running under Ray Train,ray.train.run_name,ray.submission_id, andray.metadata.*are also applied. Enable withDD_PATCH_MODULES=pytorch:true.
- Adds a
- This change adds the ability to override a manually installed tracer for Single Step Instrumentation. When this is set, all ddtrace packages will be preferred over the user installed packages. For example, wrapt, bytecode, and others. To ensure the injected library takes precedence,
DD_INJECT_EXPERIMENTAL_OVERRIDE_USER_DDTRACE=truecan be added to the environment. - CI Visibility
- The
DD_TEST_MANAGEMENT_ATTEMPT_TO_FIX_RETRIESenvironment variable is now respected by theddtrace.testinginternal pytest plugin. When set to a valid integer, it overrides the retry count returned by the Datadog API for "attempt to fix" tests.
- The
Bug Fixes
- LLM Observability:
- Fixes agentless export dropping data on the
us3,us5,ap1, andap2Datadog sites. This affected customers on these sites when no Datadog Agent was running or agentless export was explicitly enabled (DD_LLMOBS_AGENTLESS_ENABLED=1). - Resolves an issue in the
openaiintegration where streamed chat completion spans under-reportedoutput_tokensandtotal_tokensfor OpenAI-compatible providers that emit a cumulativeusageobject on every streamed chunk. - Fixes an issue where the span writer ignored its configured request timeout (
_DD_LLMOBS_WRITER_TIMEOUT, default 5 seconds) and instead used the 2 second connection default, causing intermittentTimeoutErrorand dropped span events on high-latency connections to the agent or intake. - This fix resolves an issue where the OpenAI and Anthropic integrations did not record the model output on the LLM Observability span when AI Guard blocked the request after the model call completed. The model response is now captured even though the span is marked as errored by the block.
- Fixes an issue where spans with very large JSON depth nested fields were being submitted but dropped by Datadog. The LLM Observability integration now detects nested fields that exceed the allowed depth and stringifies them, ensuring spans will not be dropped due to JSON depth limits in Datadog.
- Resolves an issue where Azure OpenAI calls through the LiteLLM integration tagged
model_namewith the request deployment name (e.g.my-deployment) instead of the canonical model returned by the API (e.g.gpt-4o-2024-08-06). The integration now prefers the response model for theazureandazure_textproviders. - Resolves an issue where spans annotated with
metadatacontaining non-string keys (e.g.int/float/bool) could be dropped during ingestion. Metadata keys are now stringified before encoding. - Resolves an issue where the OpenAI integration recorded unset request parameters (OpenAI SDK's
Omit/NotGivensentinel values) as noise in LLM span metadata. - Resolve an issue where tool results parsed from a streamed OpenAI chat completion could be attributed to the preceding input message instead of the streamed output.
- Resolves an issue where non-string tag values passed to
LLMObs.annotate(tags=...)could cause spans to be dropped during ingestion.
- Fixes agentless export dropping data on the
- AI Guard:
- This fix resolves an issue where the Anthropic integration dropped
documentcontent blocks, which could cause evaluation to be skipped for prompts whose only content was a document. Document text is now scanned and binary documents leave a placeholder so evaluation still runs. - This fix resolves an issue where the LiteLLM proxy guardrail allowed a per-request
blockdynamic parameter, supplied in the incoming request body, to disable the operator-configured blocking policy and let a denied request proceed in monitor mode. Request-supplied parameters can now only strengthen blocking (turning monitor mode into blocking); they can no longer weaken an enabled blocking policy. - This fix resolves an issue where the Strands integration silently dropped non-text Bedrock content (images, documents, video), which could cause evaluation to be skipped for prompts or tool results with no text.
- This fix resolves an issue where the Anthropic integration dropped
- langchain
- Fix AI Guard blocked requests (DENY/ABORT) not appearing in APM and LLM Observability.
- aiokafka
- Fixes
kafka.partitionandkafka.message_offsetspan tags being incorrectly set to-1. Consumer spans no longer misreport0(e.g. single-partition topics or the first message in a partition) due to falsy evaluation. Producer spans and any span where the value is genuinely unknown now omit these tags entirely rather than emitting a misleading-1.
- Fixes
- anthropic
- Fixes LLM Observability spans reporting
model_providerasunknownfor theAnthropicVertexandAnthropicBedrockclients. The provider is now resolved togoogleandamazonrespectively.
- Fixes LLM Observability spans reporting
- AAP
- Resolve an issue where some request bodies could be skipped during analysis depending on the
Content-Typeheader for the Django, Tornado, Flask, and FastAPI integrations. - This fix resolves an issue where the target URL of a redirect followed internally by
urllib3was not inspected for SSRF and API Security (API10).
- Resolve an issue where some request bodies could be skipped during analysis depending on the
- ASM
- This fix resolves an issue where user blocking could be bypassed when calling
ddtrace.contrib.trace_utils.set_userif neitherddtrace.appsec.trace_utilsnor the user tracking SDK had been imported. The user blocking decision is now always enforced when AppSec is enabled. - This fix resolves an issue where
bytescommands passed toos.system,os.spawn*, andsubprocess(for exampleos.system(b"...")orsubprocess.run(b"...", shell=True)) bypassed the Exploit Prevention (RASP) shell and command injection checks.bytescommands are valid on POSIX systems and are now passed to the security checks likestrcommands. - This fix resolves an issue where the Django session id collected by automatic user activity tracking was not hashed in
anonymizationmode. It is now hashed, consistently with the user id and login.
- This fix resolves an issue where user blocking could be bypassed when calling
- aws_durable_execution_sdk_python
- This fix resolves an issue where the
aws.durable.operation_attemptspan tag was reported off by one for replayed durable operations, causing a resumed (replayed) execution to record a different attempt number than the original execution for the same operation. Replayed operations now report the same 0-indexed attempt number as a fresh execution.
- This fix resolves an issue where the
- CI visibility
- Fixes a
ValueError: tool 1 is already in useerror that occurred on Python 3.12+ when running pytest withcoverage.pyorpytest-covalongside ddtrace. Both tools previously competed forsys.monitoring.COVERAGE_ID(slot 1). ddtrace now tries tool slots in priority order (4, 3, 1), falling back gracefully if all candidate slots are occupied. - Fixes a
ResourceWarning: unclosed socketthat occurred when using the pytest plugin. The background writer thread's thread-local HTTP connection was not closed on thread exit.
- Fixes a
- database monitoring
- Resolved a memory leak that grew with query volume when
DD_DBM_PROPAGATION_MODEwas set tofull,service, ordynamic_service.
- Resolved a memory leak that grew with query volume when
- elasticsearch
- Fix zombie spans on TransportError. When a request failed, the generator coroutine holding the open span was not explicitly closed, leaving the span open until Python GC ran — producing spans with grossly inflated durations on non-CPython runtimes (e.g. PyPy). Both the sync and async wrappers now call
coro.close()immediately on the error path. Affects Elasticsearch and OpenSearch integrations.
- Fix zombie spans on TransportError. When a request failed, the generator coroutine holding the open span was not explicitly closed, leaving the span open until Python GC ran — producing spans with grossly inflated durations on non-CPython runtimes (e.g. PyPy). Both the sync and async wrappers now call
- tracing
- Resolves an issue where wrapping an async generator on Python 3.11 through 3.14 raises a
TypeError: object NoneType can't be used in 'await' expressionerror. This occurs when the generator body awaits a coroutine that suspends to the event loop before its firstyield. Python 3.9 and 3.10 are not affected. - This fix resolves an issue where _dd.svc_src was incorrectly set in some cases.
- This fix resolves an issue where traces buffered before
os.fork()could be sent twice, once by the parent and once by the child. - Fixes a race condition where extra service names could be silently dropped from Remote Configuration
/v0.7/configpayloads in multi-threaded applications (e.g. uWSGI). - Applying
@tracer.wrap()to an async generator now forwards sent values, thrown exceptions, and close requests to the underlying generator, so it behaves like the unwrapped generator in all cases. Previously the wrapper only relayed values during forward iteration, so sent values were dropped andtry/finallycleanup was skipped whenever the generator was closed early or received a thrown exception. - Fixes a
TypeError: cannot pickle '_thread.lock'raised when serializing ddtrace-instrumented objects withcloudpickle. Fork-safe locks and events (ddtrace.internal.forksafe.Lock/Event) are now pickle-safe, and unpickling reconstructs a fresh instance. - A rare crash happening on versions of CPython prior to 3.12 has been fixed.
- Fixes
network.client.ipto contain the actual TCP peer IP address (i.e.REMOTE_ADDR) rather than the resolved HTTP client IP (which could originate from forwarding headers such asX-Forwarded-For). This affects the Flask, Django, ASGI (FastAPI/Starlette), and Tornado integrations. The resolved HTTP client IP continues to be reported underhttp.client_ip, which is the value used by App and API Protection (AAP) for IP-based threat detection and blocking.
- Resolves an issue where wrapping an async generator on Python 3.11 through 3.14 raises a
- botocore
- Fixes a bug in Data Streams Monitoring where the pathway context of an SQS message was not extracted when the message body was valid JSON, silently breaking the data stream for non-SNS messages with a JSON payload. The
_datadogmessage attribute is now read from the top-level SQSMessageAttributesfirst, and the message body is only parsed for SNS-to-SQS notifications. - Kinesis
PutRecordsnow propagates trace context to each record in the batch. This enables trace context propagation to correctly map to each individual record, as well as enabling the correct tracking of messages through Data Streams Monitoring. Previously, only the first record would ever have been tracked. - aiobotocore: Resolves an issue where outbound AWS SDK requests to strict-signature endpoints (e.g. AppSync, API Gateway with IAM authorization) were rejected with
The request signature we calculated does not match the signature you providedwhen distributed tracing was enabled.
- Fixes a bug in Data Streams Monitoring where the pathway context of an SQS message was not extracted when the message body was valid JSON, silently breaking the data stream for non-SNS messages with a JSON payload. The
- celery
- Fixes Celery worker and producer spans ignoring
DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED, causing spans to always usecelery-worker/celery-producerinstead of the configured global service name.
- Fixes Celery worker and producer spans ignoring
- Django
- This fix resolves an issue where async function-based middleware attributes, such as
process_exception, were not preserved, causing Django to skip exception handlers under ASGI.
- This fix resolves an issue where async function-based middleware attributes, such as
- fastapi
- Fixes span resource names for requests on nested routers being set to only the leaf path segment instead of the full composed path. Affects FastAPI >= 0.137.
- Fixes span resource names being duplicated when both the FastAPI and Starlette patches are active. Affects FastAPI >= 0.137.
- grpc
- Fix streaming
grpc.aioclient spans intermittently reportingerror.messageas"Internal error from Core"instead of the application-set abort details when a server aborts the RPC. #18015
- Fix streaming
- Code Security (IAST)
- This fix resolves an issue where instrumenting
re.finditereagerly consumed the entire match iterator to taint every match, which removed the laziness ofre.finditerand allowed a request-controlled input with many matches to allocate excess memory. Matches are now tainted lazily as the application iterates over them. - Fixed an issue where sensitive content could be left unredacted in vulnerability reports when a sensitive value overlapped a tainted range.
- A crash that could happen at interpreter teardown has been fixed.
- This fix resolves an issue where instrumenting
- litellm
- Fix
AttributeErrorwhenmetadata=Noneis passed to tracedlitellm.completion()calls. #18033
- Fix
- sqlalchemy
- Fixes duplicate SQLAlchemy event listeners when
trace_engine()is called repeatedly for the same engine.
- Fixes duplicate SQLAlchemy event listeners when
- code origin
- fix deepcopying of view functions performed by frameworks like cadwyn, when code origin is enabled.
- fixed an issue that could have caused pytest to crash internally when inspecting the call stack from an exception thrown by a view function when Code Origin is enabled.
- core
- This fix prevents periodic thread restarts from blocking application code from resuming in forked children.
- google_genai
- Fix
TypeErrorwhen Google GenAI returnsNonefor optional response fields (token counts orcandidates) introduced in google-genai>=2.6.0.
- Fix
- kafka
- Fixes an issue where Data Streams Monitoring would incorrectly record consume checkpoints for error messages.
- otel
- Resolves an issue where OpenTelemetry OTLP metrics export requests to the collector were incorrectly traced as spans.
- profiling
- Reduces native heap memory used by the stack collector in gevent and asyncio workloads.
- Rare crashes that could happen post-fork in fork-based applications have been fixed.
- protobuf
- This fix resolves an issue where Data Streams Monitoring schema tags were missing from protobuf spans due to incorrect patching of generated message classes.
- redis
- Fixes missing
out.hostandserver.addresstags on spans produced byredis.cluster.RedisClusterandredis.asyncio.cluster.RedisCluster(redis-py >=4.1). These clients do not expose aconnection_poolattribute, so connection metadata was never extracted and the Datadog inferred-entity feature fell back to the genericpeer.db.system: redisidentifier instead of resolving to the specific cluster hostname. Spans now includeout.hostandserver.addressderived from the cluster's startup node, enabling the service map to display a host-specific Redis entity.
- Fixes missing
- remoteconfig
- Fixed a configuration being reported as
acknowledgedbefore the product received it. The state is now set toacknowledgedonly after the configuration has been delivered to the product, and toerroronly when the payload is malformed and cannot be deserialized.
- Fixed a configuration being reported as
- starlette
- Fix high-cardinality span resources for CORS preflight requests. When
CORSMiddlewarehandled anOPTIONSrequest, the span resource was set to the raw URL path (e.g.OPTIONS /users/123) instead of the route template (e.g.OPTIONS /users/{user_id}). The route pattern is now resolved via the app's route tree whenCORSMiddlewareshort-circuits before the Starlette router runs. Fixes #14321.
- Fix high-cardinality span resources for CORS preflight requests. When
Other Changes
- profiling
- Reduces allocator churn in the native stack collector by reusing the cycle-detection set across stack-unwind calls.
- Reduces memory and allocation overhead for applications with many default-named asyncio tasks or gevent greenlets by avoiding storing generated task and greenlet names in the profiler's internal string table. #18437