class Tracer {

  public Span nextSpan(TraceContextOrSamplingFlags extracted) {
    if (extracted == null) throw new NullPointerException("extracted == null");
    TraceContext context = extracted.context();
    if (context != null) return newChild(context);

    TraceIdContext traceIdContext = extracted.traceIdContext();
    if (traceIdContext != null) {
      return _toSpan(null, decorateContext(
        InternalPropagation.instance.flags(extracted.traceIdContext()),
        traceIdContext.traceIdHigh(),
        traceIdContext.traceId(),
        0L,
        0L,
        0L,
        extracted.extra()
      ));
    }

    SamplingFlags samplingFlags = extracted.samplingFlags();
    List<Object> extra = extracted.extra();

    TraceContext parent = currentTraceContext.get();
    int flags;
    long traceIdHigh = 0L, traceId = 0L, localRootId = 0L, spanId = 0L;
    if (parent != null) {
      // At this point, we didn't extract trace IDs, but do have a trace in progress. Since typical
      // trace sampling is up front, we retain the decision from the parent.
      flags = InternalPropagation.instance.flags(parent);
      traceIdHigh = parent.traceIdHigh();
      traceId = parent.traceId();
      localRootId = parent.localRootId();
      spanId = parent.spanId();
      extra = concat(extra, parent.extra());
    } else {
      flags = InternalPropagation.instance.flags(samplingFlags);
    }
    return _toSpan(parent,
      decorateContext(flags, traceIdHigh, traceId, localRootId, spanId, 0L, extra));
  }

    Tracer(
    Clock clock,
    Propagation.Factory propagationFactory,
    SpanHandler spanHandler,
    PendingSpans pendingSpans,
    Sampler sampler,
    CurrentTraceContext currentTraceContext,
    boolean traceId128Bit,
    boolean supportsJoin,
    boolean alwaysSampleLocal,
    AtomicBoolean noop
  );

}