/* * Copyright 2016-2020 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package brave.opentracing; import brave.Span; import brave.baggage.BaggageField; import brave.baggage.BaggagePropagation; import brave.propagation.TraceContext; import brave.propagation.TraceContextOrSamplingFlags; import io.opentracing.SpanContext; import io.opentracing.propagation.Format; import java.util.Map; /** * Holds the {@linkplain TraceContext} used by the underlying {@linkplain brave.Tracer}, or an {link * TraceContextOrSamplingFlags extraction result if an incoming context}. An {@link * TraceContext#sampled() unsampled} context results in a {@link Span#isNoop() noop span}. * * <p>This type also includes hooks to integrate with the underlying {@linkplain brave.Tracer}. Ex * you can access the underlying trace context with {@link #unwrap} */ public abstract class BraveSpanContext implements SpanContext { /** * Returns the underlying trace context for use in Brave apis, or null if this object does not * represent a span. * * <p>When a span context is returned from {@link BraveSpan#context()}, there's no ambiguity. It * represents the current span. However, a span context can be in an intermediate state when * extracted from headers. In other words, unwrap might not have a {@link TraceContext} to * return. * * <p>Why? {@link BraveTracer#extract(Format, Object) Extraction from headers} can return partial * info. For example, in Amazon Web Services, you may be suggested just a trace ID. In other * cases, you might just inherit baggage or a sampling hint. */ public abstract TraceContext unwrap(); /** Returns empty unless {@link BaggagePropagation} is in use */ @Override public abstract Iterable<Map.Entry<String, String>> baggageItems(); static BraveSpanContext create(TraceContext context) { return new Complete(context); } static BraveSpanContext create(TraceContextOrSamplingFlags extractionResult) { return extractionResult.context() != null ? new BraveSpanContext.Complete(extractionResult.context()) : new BraveSpanContext.Incomplete(extractionResult); } static final class Complete extends BraveSpanContext { final TraceContext context; Complete(TraceContext context) { this.context = context; } @Override public TraceContext unwrap() { return context; } // notice: no sampling or parent span ID here! @Override public String toTraceId() { return context.traceIdString(); } @Override public String toSpanId() { return context.spanIdString(); } @Override public Iterable<Map.Entry<String, String>> baggageItems() { return BaggageField.getAllValues(context).entrySet(); } } static final class Incomplete extends BraveSpanContext { final TraceContextOrSamplingFlags extractionResult; Incomplete(TraceContextOrSamplingFlags extractionResult) { this.extractionResult = extractionResult; } TraceContextOrSamplingFlags extractionResult() { // temporarily hidden return extractionResult; } @Override public TraceContext unwrap() { return extractionResult.context(); } // notice: no sampling or parent span ID here! @Override public String toTraceId() { TraceContext context = extractionResult.context(); return context != null ? context.traceIdString() : null; } @Override public String toSpanId() { TraceContext context = extractionResult.context(); return context != null ? context.spanIdString() : null; } /** Returns empty unless {@link BaggagePropagation} is in use */ @Override public Iterable<Map.Entry<String, String>> baggageItems() { return BaggageField.getAllValues(extractionResult).entrySet(); } } volatile Span.Kind kind; BraveSpanContext() { } }