Skip to content

Commit 0a2ef1d

Browse files
fix(llmobs): ensure DD_APM_TRACING_ENABLED disables APM (#14617)
The existing DD_APM_TRACING_ENABLED functionality is specially implemented for asm and did not work for llmobs. Spans are still sent since some spans are required for asm. This change introduces a trace filter to drop all apm spans when llmobs is enabled. Consequently, asm + llmobs with apm disabled will not be possible with this change. I'm choosing to avoid complexity in this implementation until we see a concrete ask for this functionality. Co-authored-by: Yun Kim <[email protected]>
1 parent b7d99dc commit 0a2ef1d

File tree

4 files changed

+56
-0
lines changed

4 files changed

+56
-0
lines changed

ddtrace/_trace/apm_filter.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import os
2+
from typing import List
3+
from typing import Optional
4+
5+
from ddtrace._trace.processor import TraceProcessor
6+
from ddtrace._trace.span import Span
7+
from ddtrace.internal.utils.formats import asbool
8+
9+
10+
class APMTracingEnabledFilter(TraceProcessor):
11+
"""
12+
Trace processor that drops all APM traces when DD_APM_TRACING_ENABLED is set to a falsy value.
13+
"""
14+
15+
def __init__(self) -> None:
16+
super().__init__()
17+
self._apm_tracing_enabled = asbool(os.getenv("DD_APM_TRACING_ENABLED", "true"))
18+
19+
def process_trace(self, trace: List[Span]) -> Optional[List[Span]]:
20+
if not self._apm_tracing_enabled:
21+
return None
22+
return trace

ddtrace/llmobs/_llmobs.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import ddtrace
2121
from ddtrace import config
2222
from ddtrace import patch
23+
from ddtrace._trace.apm_filter import APMTracingEnabledFilter
2324
from ddtrace._trace.context import Context
2425
from ddtrace._trace.span import Span
2526
from ddtrace._trace.tracer import Tracer
@@ -605,6 +606,11 @@ def enable(
605606

606607
# override the default _instance with a new tracer
607608
cls._instance = cls(tracer=_tracer, span_processor=span_processor)
609+
610+
# Add APM trace filter to drop all APM traces when DD_APM_TRACING_ENABLED is falsy
611+
apm_filter = APMTracingEnabledFilter()
612+
cls._instance.tracer._span_aggregator.dd_processors.append(apm_filter)
613+
608614
cls.enabled = True
609615
cls._instance.start()
610616

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
fixes:
3+
- |
4+
LLM Observability: ensures APM is disabled when DD_APM_TRACING_ENABLED=0 when using LLM Observability.

tests/llmobs/test_llmobs.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,3 +656,27 @@ def test_trace_id_propagation_with_non_llm_parent(llmobs, llmobs_events):
656656
# LLMObs trace IDs should be different from APM trace ID
657657
assert first_child_event["trace_id"] != first_child_event["_dd"]["apm_trace_id"]
658658
assert second_child_event["trace_id"] != second_child_event["_dd"]["apm_trace_id"]
659+
660+
661+
@pytest.mark.parametrize("llmobs_env", [{"DD_APM_TRACING_ENABLED": "false"}])
662+
def test_apm_traces_dropped_when_disabled(llmobs, llmobs_events, tracer, llmobs_env):
663+
from tests.utils import DummyWriter
664+
665+
dummy_writer = DummyWriter()
666+
tracer._span_aggregator.writer = dummy_writer
667+
668+
with tracer.trace("apm_span") as apm_span:
669+
apm_span.set_tag("operation", "test")
670+
671+
# Create an LLMObs span (should be sent to LLMObs but not APM)
672+
with llmobs.llm(model_name="test-model") as llm_span:
673+
llmobs.annotate(llm_span, input_data="test input", output_data="test output")
674+
675+
# Check that no APM traces were sent to the writer
676+
assert len(dummy_writer.traces) == 0, "APM traces should be dropped when DD_APM_TRACING_ENABLED=false"
677+
678+
# But LLMObs events should still be sent
679+
assert len(llmobs_events) == 1
680+
llm_event = llmobs_events[0]
681+
assert llm_event["meta"]["span.kind"] == "llm"
682+
assert llm_event["meta"]["model_name"] == "test-model"

0 commit comments

Comments
 (0)