Repository: open-telemetry/opentelemetry-java
File: sdk/trace/src/main/java/io/opentelemetry/sdk/trace/SdkSpanBuilder.java (Java)

Code before:
  @Nullable private List<LinkData> links;
  private int totalNumberOfLinksAdded = 0;
  private long startEpochNanos = 0;

  SdkSpanBuilder(
      String spanName,
      InstrumentationScopeInfo instrumentationScopeInfo,
      TracerSharedState tracerSharedState,
      SpanLimits spanLimits) {
    this.spanName = spanName;
    this.instrumentationScopeInfo = instrumentationScopeInfo;
    this.tracerSharedState = tracerSharedState;
    this.spanLimits = spanLimits;
    this.rootContextWithRandomTraceIdBit =
        preparePrimordialContext(
            Context.root(),
            TraceFlags.getDefault().withRandomTraceIdBit(),
            TraceState.getDefault());
  }

  /*
   * A primordial context can be passed as the parent context for a root span
   * if a non-default TraceFlags or TraceState need to be passed to the sampler
   */
  private static Context preparePrimordialContext(
      Context parentContext, TraceFlags traceFlags, TraceState traceState) {
    SpanContext spanContext =
        SpanContext.create(TraceId.getInvalid(), SpanId.getInvalid(), traceFlags, traceState);
    Span span = Span.wrap(spanContext);
    return span.storeInContext(parentContext);
  }

  @Override
  public SpanBuilder setParent(Context context) {
    if (context == null) {
      return this;
    }
    this.parent = context;
    return this;
  }

  @Override
  public SpanBuilder setNoParent() {
    this.parent = Context.root();
    return this;
  }

  @Override
  public SpanBuilder setSpanKind(SpanKind spanKind) {
    if (spanKind == null) {
      return this;

Review comment (suggestion):
I see this is private. I'm aware of an underspecified region in the OTel specification. Should there be a specified way to create these "primordial" contexts with control over the root trace state?

In the Go SDK, asking for a new root gets you an empty context: https://github.com/open-telemetry/opentelemetry-go/blob/8d3b4cb2501dec9f1c5373123e425f109c43b8d2/sdk/trace/tracer.go#L92

It's not clear whether users are able to setup a context with control over TraceState at the root. We write:

> Root Samplers MAY insert an explicit randomness value into the
OpenTelemetry TraceState value in cases where an explicit
randomness value is not already set.

It doesn't actually require SDKs provide a way to set explicit randomness for the root span, it just refers to the potential scenario.

Code after:
  @Nullable private Context parent; // null means: Use current context.
  private SpanKind spanKind = SpanKind.INTERNAL;
  @Nullable private AttributesMap attributes;
  @Nullable private List<LinkData> links;
  private int totalNumberOfLinksAdded = 0;
  private long startEpochNanos = 0;

  SdkSpanBuilder(
      String spanName,
      InstrumentationScopeInfo instrumentationScopeInfo,
      TracerSharedState tracerSharedState,
      SpanLimits spanLimits) {
    this.spanName = spanName;
    this.instrumentationScopeInfo = instrumentationScopeInfo;
    this.tracerSharedState = tracerSharedState;
    this.spanLimits = spanLimits;
  }

  /*
   * A primordial context can be passed as the parent context for a root span
   * if a non-default TraceFlags or TraceState need to be passed to the sampler
   */
  private static Context preparePrimordialContext(TraceFlags traceFlags, TraceState traceState) {
    SpanContext spanContext =
        SpanContext.create(TraceId.getInvalid(), SpanId.getInvalid(), traceFlags, traceState);
    Span span = Span.wrap(spanContext);
    return span.storeInContext(Context.root());
  }

  @Override
  public SpanBuilder setParent(Context context) {
    if (context == null) {
      return this;
    }
    this.parent = context;
    return this;
  }

  @Override
  public SpanBuilder setNoParent() {
    this.parent = Context.root();
    return this;
  }

  @Override
  public SpanBuilder setSpanKind(SpanKind spanKind) {
    if (spanKind == null) {
      return this;
    }
    this.spanKind = spanKind;
    return this;