From 02d094fa168febaeceba61cb0c9e03a1e91be1d0 Mon Sep 17 00:00:00 2001 From: Douglas Q Hawkins Date: Wed, 1 Jul 2026 16:35:03 -0400 Subject: [PATCH] Thread SpanPrototype through CoreSpanBuilder (increment 2a: seed plumbing) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Threads a spanPrototype through the span builder exactly like tagLedger — field + startImpl + both startSpan overloads + buildSpan + buildSpanContext + reset — and applies it at buildSpanContext right after defaultSpanTags (before the per-span ledger, so per-span tags override the prototype's constants). Adds CoreSpanBuilder.withSpanPrototype(...) as the setter. Additive: defaults to SpanPrototype.NONE at every site, so the applied branch is skipped and every existing span-creation path is byte-for-byte unchanged. CoreSpanBuilderTest (25) + CoreTracerTest2 (15) green. Next: public startSpan/buildSpan(SpanPrototype, ...) entry points + the old-vs-new SpanStartBenchmark (which exercises the seeding end-to-end). Co-Authored-By: Claude Opus 4.8 --- .../java/datadog/trace/core/CoreTracer.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java b/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java index 28f9e39c710..e7a344baa1b 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java @@ -72,6 +72,7 @@ import datadog.trace.bootstrap.instrumentation.api.ProfilingContextIntegration; import datadog.trace.bootstrap.instrumentation.api.SpanAttributes; import datadog.trace.bootstrap.instrumentation.api.SpanLink; +import datadog.trace.bootstrap.instrumentation.api.SpanPrototype; import datadog.trace.bootstrap.instrumentation.api.TagContext; import datadog.trace.bootstrap.instrumentation.api.Tags; import datadog.trace.civisibility.interceptor.CiVisibilityApmProtocolInterceptor; @@ -1583,6 +1584,7 @@ public abstract static class CoreSpanBuilder implements AgentTracer.SpanBuilder // Builder attributes // Make sure any fields added here are also reset properly in ReusableSingleSpanBuilder.reset protected TagMap.Ledger tagLedger; + protected SpanPrototype spanPrototype = SpanPrototype.NONE; protected long timestampMicro; protected AgentSpanContext parent; protected String serviceName; @@ -1621,6 +1623,7 @@ protected static final DDSpan buildSpan( boolean errorFlag, CharSequence spanType, TagMap.Ledger tagLedger, + SpanPrototype spanPrototype, List links, Object builderRequestContextDataAppSec, Object builderRequestContextDataIast, @@ -1640,6 +1643,7 @@ protected static final DDSpan buildSpan( errorFlag, spanType, tagLedger, + spanPrototype, links, builderRequestContextDataAppSec, builderRequestContextDataIast, @@ -1725,6 +1729,7 @@ protected AgentSpan startImpl() { this.errorFlag, this.spanType, this.tagLedger, + this.spanPrototype, this.links, this.builderRequestContextDataAppSec, this.builderRequestContextDataIast, @@ -1751,6 +1756,7 @@ protected static final AgentSpan startSpan( false /* errorFlag */, null /* spanType */, null /* tagLedger */, + SpanPrototype.NONE /* spanPrototype */, null /* links */, null /* appSec */, null /* iast */, @@ -1770,6 +1776,7 @@ protected static final AgentSpan startSpan( boolean errorFlag, CharSequence spanType, TagMap.Ledger tagLedger, + SpanPrototype spanPrototype, List links, Object builderRequestContextDataAppSec, Object builderRequestContextDataIast, @@ -1820,6 +1827,7 @@ protected static final AgentSpan startSpan( errorFlag, spanType, tagLedger, + spanPrototype, links, builderRequestContextDataAppSec, builderRequestContextDataIast, @@ -1908,6 +1916,11 @@ public final CoreSpanBuilder withTag(final String tag, final Object value) { return this; } + public final CoreSpanBuilder withSpanPrototype(final SpanPrototype spanPrototype) { + this.spanPrototype = (spanPrototype == null) ? SpanPrototype.NONE : spanPrototype; + return this; + } + @Override public final AgentTracer.SpanBuilder withRequestContextData( RequestContextSlot slot, T data) { @@ -1958,6 +1971,7 @@ protected static final DDSpanContext buildSpanContext( boolean errorFlag, CharSequence spanType, TagMap.Ledger tagLedger, + SpanPrototype spanPrototype, List links, Object builderRequestContextDataAppSec, Object builderRequestContextDataIast, @@ -2196,6 +2210,9 @@ protected static final DDSpanContext buildSpanContext( // the builder. This is the order that the tags were added previously, but maybe the `tags` // set in the builder should come last, so that they override other tags. context.setAllTags(mergedTracerTags, mergedTracerTagsNeedsIntercept); + if (spanPrototype != SpanPrototype.NONE) { + context.setAllTags(spanPrototype.tags()); + } context.setAllTags(tagLedger); context.setAllTags(coreTags, coreTagsNeedsIntercept); context.setAllTags(rootSpanTags, rootSpanTagsNeedsIntercept); @@ -2276,6 +2293,7 @@ final boolean reset(String instrumentationName, CharSequence operationName) { this.operationName = operationName; if (this.tagLedger != null) this.tagLedger.reset(); + this.spanPrototype = SpanPrototype.NONE; this.timestampMicro = 0L; this.parent = null; this.serviceName = null;