From 3d3f731c127d44f6cd341ccff869cb6c9f490506 Mon Sep 17 00:00:00 2001 From: Pavel Date: Wed, 8 Jul 2026 10:37:45 +0300 Subject: [PATCH 1/2] Expose isFinished() on AgentSpan Add a non-breaking default boolean isFinished() to the AgentSpan interface (internal-api), surfacing the finished state DDSpan already tracks (durationNano != 0) so other modules can query it without reaching into dd-trace-core. DDSpan's existing method overrides the default; the TrackingSpanDecorator test wrapper delegates; leaf/synthetic spans (NoopSpan etc.) keep the false default. Adds a DDSpanTest case covering false-before / true-after-finish via the interface. Motivated by the FFE span-enrichment interceptor (PR #11658), which needs to distinguish a truly-finished local root from a still-running one (long-running traces) and resolve it in O(1); that consumer lands in a separate follow-up. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../trace/agent/test/TrackingSpanDecorator.groovy | 5 +++++ .../src/test/java/datadog/trace/core/DDSpanTest.java | 10 ++++++++++ .../trace/bootstrap/instrumentation/api/AgentSpan.java | 8 ++++++++ 3 files changed, 23 insertions(+) diff --git a/dd-java-agent/instrumentation-testing/src/main/groovy/datadog/trace/agent/test/TrackingSpanDecorator.groovy b/dd-java-agent/instrumentation-testing/src/main/groovy/datadog/trace/agent/test/TrackingSpanDecorator.groovy index b9de4adad0e..53d5ad5d9de 100644 --- a/dd-java-agent/instrumentation-testing/src/main/groovy/datadog/trace/agent/test/TrackingSpanDecorator.groovy +++ b/dd-java-agent/instrumentation-testing/src/main/groovy/datadog/trace/agent/test/TrackingSpanDecorator.groovy @@ -414,4 +414,9 @@ class TrackingSpanDecorator implements AgentSpan { boolean isOutbound() { return delegate.isOutbound() } + + @Override + boolean isFinished() { + return delegate.isFinished() + } } diff --git a/dd-trace-core/src/test/java/datadog/trace/core/DDSpanTest.java b/dd-trace-core/src/test/java/datadog/trace/core/DDSpanTest.java index a05e9d982c4..b3103f7f161 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/DDSpanTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/DDSpanTest.java @@ -26,6 +26,7 @@ import datadog.trace.api.datastreams.NoopPathwayContext; import datadog.trace.api.gateway.RequestContextSlot; import datadog.trace.api.sampling.PrioritySampling; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.AgentSpanContext; import datadog.trace.bootstrap.instrumentation.api.ErrorPriorities; import datadog.trace.bootstrap.instrumentation.api.TagContext; @@ -61,6 +62,15 @@ void setup() { tracer = tracerBuilder().writer(writer).sampler(new RateByServiceTraceSampler()).build(); } + @Test + void isFinishedReflectsSpanCompletion() { + // Exercised via the AgentSpan interface to prove the new default resolves to DDSpan's override. + AgentSpan span = tracer.buildSpan("datadog", "finishTest").start(); + assertFalse(span.isFinished(), "span must not report finished before finish()"); + span.finish(); + assertTrue(span.isFinished(), "span must report finished after finish()"); + } + @Test void gettersAndSetters() { DDSpan span = diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentSpan.java b/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentSpan.java index 0eb67f3ad52..da752125170 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentSpan.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentSpan.java @@ -213,6 +213,14 @@ default AgentSpan asAgentSpan() { return this; } + /** + * @return {@code true} once this span has finished (its duration is set). Implementations that do + * not track finish state return the default. + */ + default boolean isFinished() { + return false; + } + default void copyPropagationAndBaggage(final AgentSpan source) { // no op default } From abd6fab3ba7b90bf1f7ff4e0983a7d01acd7fd01 Mon Sep 17 00:00:00 2001 From: Pavel Date: Wed, 8 Jul 2026 15:40:04 +0300 Subject: [PATCH 2/2] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../datadog/trace/bootstrap/instrumentation/api/AgentSpan.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentSpan.java b/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentSpan.java index da752125170..cf36a646fa3 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentSpan.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentSpan.java @@ -215,7 +215,7 @@ default AgentSpan asAgentSpan() { /** * @return {@code true} once this span has finished (its duration is set). Implementations that do - * not track finish state return the default. + * not track finish state always return {@code false}. */ default boolean isFinished() { return false;