1616import io .opentelemetry .api .trace .Span ;
1717import io .opentelemetry .api .trace .SpanBuilder ;
1818import io .opentelemetry .api .trace .SpanContext ;
19+ import io .opentelemetry .api .trace .SpanId ;
1920import io .opentelemetry .api .trace .SpanKind ;
2021import io .opentelemetry .api .trace .TraceFlags ;
22+ import io .opentelemetry .api .trace .TraceId ;
2123import io .opentelemetry .api .trace .TraceState ;
2224import io .opentelemetry .context .Context ;
2325import io .opentelemetry .sdk .common .InstrumentationScopeInfo ;
3537/** {@link SdkSpanBuilder} is SDK implementation of {@link SpanBuilder}. */
3638class SdkSpanBuilder implements SpanBuilder {
3739
40+ private static final Context ROOT_CONTEXT_WITH_RANDOM_TRACE_ID_BIT =
41+ preparePrimordialContext (
42+ TraceFlags .builder ().setRandomTraceId (true ).build (), TraceState .getDefault ());
43+
3844 private final String spanName ;
3945 private final InstrumentationScopeInfo instrumentationScopeInfo ;
4046 private final TracerSharedState tracerSharedState ;
@@ -58,6 +64,17 @@ class SdkSpanBuilder implements SpanBuilder {
5864 this .spanLimits = spanLimits ;
5965 }
6066
67+ /*
68+ * A primordial context can be passed as the parent context for a root span
69+ * if a non-default TraceFlags or TraceState need to be passed to the sampler
70+ */
71+ private static Context preparePrimordialContext (TraceFlags traceFlags , TraceState traceState ) {
72+ SpanContext spanContext =
73+ SpanContext .create (TraceId .getInvalid (), SpanId .getInvalid (), traceFlags , traceState );
74+ Span span = Span .wrap (spanContext );
75+ return span .storeInContext (Context .root ());
76+ }
77+
6178 @ Override
6279 public SpanBuilder setParent (Context context ) {
6380 if (context == null ) {
@@ -170,14 +187,25 @@ public Span startSpan() {
170187 Span parentSpan = Span .fromContext (parentContext );
171188 SpanContext parentSpanContext = parentSpan .getSpanContext ();
172189 String traceId ;
190+ boolean isTraceIdRandom ;
173191 IdGenerator idGenerator = tracerSharedState .getIdGenerator ();
174192 String spanId = idGenerator .generateSpanId ();
193+
194+ Context parentContextForSampler = parentContext ;
175195 if (!parentSpanContext .isValid ()) {
176196 // New root span.
177197 traceId = idGenerator .generateTraceId ();
198+ if (idGenerator .generatesRandomTraceIds ()) {
199+ isTraceIdRandom = true ;
200+ // Replace parentContext for sampling with one with RANDOM_TRACE_ID bit set
201+ parentContextForSampler = ROOT_CONTEXT_WITH_RANDOM_TRACE_ID_BIT ;
202+ } else {
203+ isTraceIdRandom = false ;
204+ }
178205 } else {
179206 // New child span.
180207 traceId = parentSpanContext .getTraceId ();
208+ isTraceIdRandom = parentSpanContext .getTraceFlags ().isTraceIdRandom ();
181209 }
182210 List <LinkData > currentLinks = links ;
183211 List <LinkData > immutableLinks =
@@ -190,7 +218,12 @@ public Span startSpan() {
190218 tracerSharedState
191219 .getSampler ()
192220 .shouldSample (
193- parentContext , traceId , spanName , spanKind , immutableAttributes , immutableLinks );
221+ parentContextForSampler ,
222+ traceId ,
223+ spanName ,
224+ spanKind ,
225+ immutableAttributes ,
226+ immutableLinks );
194227 SamplingDecision samplingDecision = samplingResult .getDecision ();
195228
196229 TraceState samplingResultTraceState =
@@ -199,7 +232,10 @@ public Span startSpan() {
199232 ImmutableSpanContext .create (
200233 traceId ,
201234 spanId ,
202- isSampled (samplingDecision ) ? TraceFlags .getSampled () : TraceFlags .getDefault (),
235+ TraceFlags .builder ()
236+ .setSampled (isSampled (samplingDecision ))
237+ .setRandomTraceId (isTraceIdRandom )
238+ .build (),
203239 samplingResultTraceState ,
204240 /* remote= */ false ,
205241 tracerSharedState .isIdGeneratorSafeToSkipIdValidation ());
0 commit comments