brave.propagation.TraceContextOrSamplingFlags Maven / Gradle / Ivy
/*
* Copyright 2013-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.propagation;
import brave.Tracer;
import brave.internal.InternalPropagation;
import brave.internal.Nullable;
import brave.propagation.TraceContext.Extractor;
import brave.sampler.SamplerFunction;
import java.util.ArrayList;
import java.util.List;
import static brave.internal.InternalPropagation.FLAG_SAMPLED;
import static brave.internal.InternalPropagation.FLAG_SAMPLED_LOCAL;
import static brave.internal.InternalPropagation.FLAG_SAMPLED_SET;
import static brave.internal.collect.Lists.ensureImmutable;
import static brave.propagation.TraceContext.ensureExtraAdded;
import static java.util.Collections.emptyList;
/**
* Union type that contains only one of trace context, trace ID context or sampling flags. This type
* is designed for use with {@link Tracer#nextSpan(TraceContextOrSamplingFlags)}.
*
* Users should not create instances of this, rather use {@link Extractor} provided
* by a {@link Propagation} implementation such as {@link Propagation#B3_STRING}.
*
*
Those implementing {@link Propagation} should use the following advice:
*
* - If you have the trace and span ID, use {@link #create(TraceContext)}
* - If you have only a trace ID, use {@link #create(TraceIdContext)}
* - Otherwise, use {@link #create(SamplingFlags)}
*
* If your propagation implementation needs additional state, append it via {@link * Builder#addExtra(Object)}. * * *
This started as a port of {@code com.github.kristofa.brave.TraceData}, which served the same * purpose. * * @see Extractor * @since 4.0 */ //@Immutable public final class TraceContextOrSamplingFlags { public static final TraceContextOrSamplingFlags EMPTY = new TraceContextOrSamplingFlags(3, SamplingFlags.EMPTY, emptyList()), NOT_SAMPLED = new TraceContextOrSamplingFlags(3, SamplingFlags.NOT_SAMPLED, emptyList()), SAMPLED = new TraceContextOrSamplingFlags(3, SamplingFlags.SAMPLED, emptyList()), DEBUG = new TraceContextOrSamplingFlags(3, SamplingFlags.DEBUG, emptyList()); /** * Used to implement {@link Extractor#extract(Object)} for a format that can extract a complete * {@link TraceContext}, including a {@linkplain TraceContext#traceIdString() trace ID} and * {@linkplain TraceContext#spanIdString() span ID}. * * @see #context() * @see #newBuilder(TraceContext) * @see Extractor#extract(Object) * @since 4.3 */ public static TraceContextOrSamplingFlags create(TraceContext context) { return new TraceContextOrSamplingFlags(1, context, emptyList()); } /** * Used to implement {@link Extractor#extract(Object)} when the format allows extracting a * {@linkplain TraceContext#traceIdString() trace ID} without a {@linkplain * TraceContext#spanIdString() span ID} * * @see #traceIdContext() * @see #newBuilder(TraceIdContext) * @see Extractor#extract(Object) * @since 4.9 */ public static TraceContextOrSamplingFlags create(TraceIdContext traceIdContext) { return new TraceContextOrSamplingFlags(2, traceIdContext, emptyList()); } /** * Used to implement {@link Extractor#extract(Object)} when the format allows extracting only * {@linkplain SamplingFlags sampling flags}. * * @see #samplingFlags() * @see #newBuilder(TraceIdContext) * @see Extractor#extract(Object) * @since 4.3 */ public static TraceContextOrSamplingFlags create(SamplingFlags flags) { // reuses constants to avoid excess allocation if (flags == SamplingFlags.SAMPLED) return SAMPLED; if (flags == SamplingFlags.EMPTY) return EMPTY; if (flags == SamplingFlags.NOT_SAMPLED) return NOT_SAMPLED; if (flags == SamplingFlags.DEBUG) return DEBUG; return new TraceContextOrSamplingFlags(3, flags, emptyList()); } /** * Use when implementing {@link Extractor#extract(Object)} requires {@link Builder#sampledLocal()} * or {@link Builder#addExtra(Object)}. Otherwise, use {@link #create(TraceContext)} as it is more * efficient. * * @see #create(TraceContext) * @see Extractor#extract(Object) * @since 5.12 */ public static Builder newBuilder(TraceContext context) { if (context == null) throw new NullPointerException("context == null"); return new Builder(1, context, context.extra()); } /** * Use when implementing {@link Extractor#extract(Object)} requires {@link Builder#sampledLocal()} * or {@link Builder#addExtra(Object)}. Otherwise, use {@link #create(TraceIdContext)} as it is * more efficient. * * @see #create(TraceIdContext) * @see Extractor#extract(Object) * @since 5.12 */ public static Builder newBuilder(TraceIdContext traceIdContext) { if (traceIdContext == null) throw new NullPointerException("traceIdContext == null"); return new Builder(2, traceIdContext, emptyList()); } /** * Use when implementing {@link Extractor#extract(Object)} requires {@link Builder#sampledLocal()} * or {@link Builder#addExtra(Object)}. Otherwise, use {@link #create(SamplingFlags)} as it is * more efficient. * * @see #create(SamplingFlags) * @see Extractor#extract(Object) * @since 5.12 */ public static Builder newBuilder(SamplingFlags flags) { if (flags == null) throw new NullPointerException("flags == null"); return new Builder(3, flags, emptyList()); } /** * @deprecated Since 5.12, use {@link #newBuilder(TraceContext)}, {@link * #newBuilder(TraceIdContext)} or {@link #newBuilder(SamplingFlags)}. */ @Deprecated public static Builder newBuilder() { return new Builder(0, null, emptyList()); } /** Returns {@link SamplingFlags#sampled()}, regardless of subtype. */ @Nullable public Boolean sampled() { return value.sampled(); } /** Returns {@link SamplingFlags#sampledLocal()}, regardless of subtype. */ public final boolean sampledLocal() { return (value.flags & FLAG_SAMPLED_LOCAL) == FLAG_SAMPLED_LOCAL; } /** @deprecated do not use object variant.. only set when you have a sampling decision */ @Deprecated public TraceContextOrSamplingFlags sampled(@Nullable Boolean sampled) { if (sampled != null) return sampled(sampled.booleanValue()); int flags = value.flags; flags &= ~FLAG_SAMPLED_SET; flags &= ~FLAG_SAMPLED; if (flags == value.flags) return this; // save effort if no change return withFlags(flags); } /** * This is used to apply a {@link SamplerFunction} decision with least overhead. * * Ex. *
{@code * Boolean sampled = extracted.sampled(); * // only recreate the context if the messaging sampler made a decision * if (sampled == null && (sampled = sampler.trySample(request)) != null) { * extracted = extracted.sampled(sampled.booleanValue()); * } * }* * @param sampled decision to apply * @return {@code this} unless {@link #sampled()} differs from the input. * @since 5.2 */ public TraceContextOrSamplingFlags sampled(boolean sampled) { Boolean thisSampled = sampled(); if (thisSampled != null && thisSampled.equals(sampled)) return this; int flags = InternalPropagation.sampled(sampled, value.flags); if (flags == value.flags) return this; // save effort if no change return withFlags(flags); } /** * Returns non-{@code null} when both a {@linkplain TraceContext#traceIdString() trace ID} and * {@linkplain TraceContext#spanIdString() span ID} were {@link Extractor#extract(Object) * extracted} from a request. * *
For example, given the header "b3: 80f198ee56343ba864fe8b2a57d3eff7-e457b5a2e4d86bd1-1", * {@link B3Propagation} extracts the following: *
-
*
- {@link TraceContext#traceIdString()}: "80f198ee56343ba864fe8b2a57d3eff7" *
- {@link TraceContext#spanIdString()}: "e457b5a2e4d86bd1" *
- {@link TraceContext#sampled()}: {@code true} *
For example, given the header "x-amzn-trace-id: Root=1-5759e988-bd862e3fe1be46a994272793", * AWSPropagation * extracts the following: *
-
*
- {@link TraceIdContext#traceIdString()}: "15759e988bd862e3fe1be46a994272793" *
- {@link TraceIdContext#sampled()}: {@code null} *
For example, given the header "b3: 1", {@link B3Propagation} extracts {@link #SAMPLED}. * * @return sampling flags when {@link #context()} and {@link #traceIdContext()} are not {@code * null} * @see #create(SamplingFlags) * @see #newBuilder(SamplingFlags) * @since 4.9 */ @Nullable public SamplingFlags samplingFlags() { return type == 3 ? value : null; } /** * Returns a list of additional state extracted from the request. Will be non-empty when {@link * #context()} is {@code null}. * * @see TraceContext#extra() * @since 4.9 */ public final List