Repository navigation
Drop APM traces when APM tracing is disabled and keep LLM Observability working #12473
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
gh-worker-dd-mergequeue-cf854d
merged 20 commits into
master
from
nicole.cybul/llmobs-apm-tracing-disabled
Oct 14, 2026
Merged
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
6b02ea9
Drop APM traces when APM tracing is disabled and keep LLM Observabili…
ncybul 5e30ea9
Clarify why the tracer-disabled and drop-all-traces branches exist
ncybul 5923093
Drop the LLMObs smoke tests and cover the behavior in SamplerTest
ncybul 6f19b69
Merge branch 'master' into nicole.cybul/llmobs-apm-tracing-disabled
ncybul 9179365
Ignore the upstream sampling priority when APM tracing is disabled an…
ncybul 80e580e
Start LLM Observability when CI Visibility installs the tracer
ncybul fe764e7
Dispatch the secondary queue before a flush completes
ncybul a2a2a57
Keep the standalone ASM trickle when AppSec activates at runtime
ncybul a153f2d
Let the APM traces drop override a manual.keep when APM tracing is di…
ncybul 5a9d467
Keep the APM traces drop from overriding a Data Jobs keep
ncybul 16e1082
Clarify that the CI Visibility carve-out only guarantees a live tracer
ncybul 6a1ee87
Test that sampled-out traces still deliver LLMObs spans
ncybul b154556
Match the extraction priority reset to TraceCollector's product check
ncybul ec10186
Shorten comments to the why
ncybul c0b43f1
Test canAvoidSamplingPriorityLock with Data Jobs and APM tracing enabled
ncybul 56f612a
Keep only one standalone ASM trace per minute when traces share a mil…
ncybul c8b2677
Merge branch 'master' into nicole.cybul/llmobs-apm-tracing-disabled
ncybul a946fca
Merge branch 'master' into nicole.cybul/llmobs-apm-tracing-disabled
ncybul 1163902
Merge branch 'master' into nicole.cybul/llmobs-apm-tracing-disabled
ncybul 2f3dea3
Stub isApmTracingEnabled in W3COtelTraceStateContinuationTest mocks
ncybul File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
48 changes: 48 additions & 0 deletions
48
dd-java-agent/agent-llmobs/src/test/java/datadog/trace/llmobs/LLMObsSystemTest.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| package datadog.trace.llmobs; | ||
|
|
||
| import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_ENABLED; | ||
| import static datadog.trace.api.config.LlmObsConfig.LLMOBS_ENABLED; | ||
| import static datadog.trace.api.config.TraceInstrumentationConfig.TRACE_ENABLED; | ||
| import static org.junit.jupiter.api.Assertions.assertSame; | ||
| import static org.junit.jupiter.api.Assertions.assertThrows; | ||
|
|
||
| import datadog.trace.api.llmobs.LLMObs; | ||
| import datadog.trace.api.llmobs.noop.NoOpLLMObsSpan; | ||
| import datadog.trace.test.junit.utils.config.WithConfig; | ||
| import datadog.trace.test.util.DDJavaSpecification; | ||
| import org.junit.jupiter.api.Test; | ||
|
|
||
| class LLMObsSystemTest extends DDJavaSpecification { | ||
|
|
||
| /** | ||
| * LLM Observability spans are backed by tracer spans, so the subsystem must stay off when tracing | ||
| * is disabled. Starting it would install the real SDK implementation on top of the no-op tracer, | ||
| * whose {@code buildSpan()} returns null, and every span-starting call would throw. | ||
| */ | ||
| @WithConfig(key = LLMOBS_ENABLED, value = "true") | ||
| @WithConfig(key = TRACE_ENABLED, value = "false") | ||
| @Test | ||
| void staysNoOpWhenTracingIsDisabled() { | ||
| // The null SharedCommunicationObjects doubles as an assertion that start() returns before | ||
| // touching it: any use would throw. | ||
| LLMObsSystem.start(null, null); | ||
|
|
||
| assertSame( | ||
| NoOpLLMObsSpan.INSTANCE, LLMObs.startLLMSpan("span", "model", "provider", null, null)); | ||
| } | ||
|
|
||
| /** | ||
| * CI Visibility installs a {@code CoreTracer} even with tracing disabled (see {@code | ||
| * TracerInstaller#installGlobalTracer}), so the guard above must not fire in that combination — | ||
| * the tracer LLM Observability needs does exist. | ||
| */ | ||
| @WithConfig(key = LLMOBS_ENABLED, value = "true") | ||
| @WithConfig(key = TRACE_ENABLED, value = "false") | ||
| @WithConfig(key = CIVISIBILITY_ENABLED, value = "true") | ||
| @Test | ||
| void startsWhenCiVisibilityInstallsTheTracer() { | ||
| // Reaching the null SharedCommunicationObjects is the assertion: start() only dereferences it | ||
| // after the guard, so the NPE proves the subsystem was not short-circuited. | ||
| assertThrows(NullPointerException.class, () -> LLMObsSystem.start(null, null)); | ||
| } | ||
| } |
43 changes: 43 additions & 0 deletions
43
dd-trace-core/src/main/java/datadog/trace/common/sampling/ApmTracingDisabledSampler.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| package datadog.trace.common.sampling; | ||
|
|
||
| import datadog.trace.api.sampling.PrioritySampling; | ||
| import datadog.trace.api.sampling.SamplingMechanism; | ||
| import datadog.trace.bootstrap.ActiveSubsystems; | ||
| import datadog.trace.core.CoreSpan; | ||
| import java.time.Clock; | ||
|
|
||
| /** | ||
| * Drops APM traces for {@code dd.apm.tracing.enabled=false}. If Remote Configuration activates | ||
| * AppSec at runtime, falls back to the standalone ASM trickle of 1 APM trace per minute, so it | ||
| * checks {@link ActiveSubsystems#APPSEC_ACTIVE} per trace. | ||
| */ | ||
| public class ApmTracingDisabledSampler implements Sampler, PrioritySampler { | ||
|
|
||
| private final AsmStandaloneSampler asmStandaloneSampler; | ||
| private final ForcePrioritySampler dropSampler; | ||
|
|
||
| public ApmTracingDisabledSampler(final Clock clock) { | ||
| this.asmStandaloneSampler = new AsmStandaloneSampler(clock); | ||
| this.dropSampler = | ||
| new ForcePrioritySampler(PrioritySampling.SAMPLER_DROP, SamplingMechanism.DEFAULT); | ||
| } | ||
|
|
||
| @Override | ||
| public <T extends CoreSpan<T>> boolean sample(final T span) { | ||
| // Both delegates keep sending the trace to the agent so it can collect stats on dropped traces. | ||
| return isAsmActive() ? asmStandaloneSampler.sample(span) : dropSampler.sample(span); | ||
| } | ||
|
|
||
| @Override | ||
| public <T extends CoreSpan<T>> void setSamplingPriority(final T span) { | ||
| if (isAsmActive()) { | ||
| asmStandaloneSampler.setSamplingPriority(span); | ||
| } else { | ||
| dropSampler.setSamplingPriority(span); | ||
| } | ||
| } | ||
|
|
||
| private static boolean isAsmActive() { | ||
| return ActiveSubsystems.APPSEC_ACTIVE; | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.