brave.propagation.TraceContext 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.Span;
import brave.internal.InternalPropagation;
import brave.internal.Nullable;
import brave.internal.Platform;
import java.lang.ref.WeakReference;
import java.util.Collections;
import java.util.List;
import static brave.internal.HexCodec.lenientLowerHexToUnsignedLong;
import static brave.internal.HexCodec.toLowerHex;
import static brave.internal.HexCodec.writeHexLong;
import static brave.internal.InternalPropagation.FLAG_LOCAL_ROOT;
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.InternalPropagation.FLAG_SHARED;
import static brave.internal.Lists.ensureImmutable;
import static brave.propagation.TraceIdContext.toTraceIdString;
/**
* Contains trace identifiers and sampling data propagated in and out-of-process.
*
* Particularly, this includes trace identifiers and sampled state.
*
*
The implementation was originally {@code com.github.kristofa.brave.SpanId}, which was a
* port of {@code com.twitter.finagle.tracing.TraceId}. Unlike these mentioned, this type does not
* expose a single binary representation. That's because propagation forms can now vary.
*/
//@Immutable
public final class TraceContext extends SamplingFlags {
/**
* Used to send the trace context downstream. For example, as http headers.
*
*
For example, to put the context on an {@link java.net.HttpURLConnection}, you can do this:
*
{@code
* // in your constructor
* injector = tracing.propagation().injector(URLConnection::setRequestProperty);
*
* // later in your code, reuse the function you created above to add trace headers
* HttpURLConnection connection = (HttpURLConnection) new URL("http://myserver").openConnection();
* injector.inject(span.context(), connection);
* }
*/
public interface Injector {
/**
* Usually calls a setter for each propagation field to send downstream.
*
* @param traceContext possibly unsampled.
* @param carrier holds propagation fields. For example, an outgoing message or http request.
*/
void inject(TraceContext traceContext, C carrier);
}
/**
* Used to continue an incoming trace. For example, by reading http headers.
*
* @see brave.Tracer#nextSpan(TraceContextOrSamplingFlags)
*/
public interface Extractor {
/**
* Returns either a trace context or sampling flags parsed from the carrier. If nothing was
* parsable, sampling flags will be set to {@link SamplingFlags#EMPTY}.
*
* @param carrier holds propagation fields. For example, an incoming message or http request.
*/
TraceContextOrSamplingFlags extract(C carrier);
}
public static Builder newBuilder() {
return new Builder();
}
/** When non-zero, the trace containing this span uses 128-bit trace identifiers. */
public long traceIdHigh() {
return traceIdHigh;
}
/** Unique 8-byte identifier for a trace, set on all spans within it. */
public long traceId() {
return traceId;
}
/**
* Returns the first {@link #spanId()} in a partition of a trace: otherwise known as an entry
* span. This could be a root span or a span representing incoming work (ex {@link
* Span.Kind#SERVER} or {@link Span.Kind#CONSUMER}. Unlike {@link #parentIdAsLong()}, this value
* is inherited to child contexts until the trace exits the process. This value is inherited for
* all child spans until the trace exits the process. This could also be described as an entry
* span.
*
* When {@link #isLocalRoot()}, this ID will be the same as the {@link #spanId() span ID}.
*
*
The local root ID can be used for dependency link processing, skipping data or partitioning
* purposes. For example, one processor could skip all intermediate (local) spans between an
* incoming service call and any outgoing ones.
*
*
This does not group together multiple points of entry in the same trace. For example,
* repetitive consumption of the same incoming message results in different local roots.
*
* @return the {@link #spanId() span ID} of the local root or zero if this context wasn't
* initialized by a {@link brave.Tracer}.
*/
// This is the first span ID that became a Span or ScopedSpan
public long localRootId() {
return localRootId;
}
public boolean isLocalRoot() {
return (flags & FLAG_LOCAL_ROOT) == FLAG_LOCAL_ROOT;
}
/**
* The parent's {@link #spanId} or null if this the root span in a trace.
*
* @see #parentIdAsLong()
*/
@Nullable public final Long parentId() {
return parentId != 0 ? parentId : null;
}
/**
* Like {@link #parentId()} except returns a primitive where zero implies absent.
*
*
Using this method will avoid allocation, so is encouraged when copying data.
*/
public long parentIdAsLong() {
return parentId;
}
/**
* Unique 8-byte identifier of this span within a trace.
*
*
A span is uniquely identified in storage by ({@linkplain #traceId}, {@linkplain #spanId}).
*/
public long spanId() {
return spanId;
}
/**
* True if we are recording a server span with the same span ID parsed from incoming headers.
*
*
Impact on indexing
* When an RPC trace is client-originated, it will be sampled and the same span ID is used for
* the server side. The shared flag helps prioritize timestamp and duration indexing in favor of
* the client. In v1 format, there is no shared flag, so it implies converters should not store
* timestamp and duration on the server span explicitly.
*/
public boolean shared() {
return (flags & FLAG_SHARED) == FLAG_SHARED;
}
/**
* Returns a list of additional data propagated through this trace.
*
*
The contents are intentionally opaque, deferring to {@linkplain Propagation} to define. An
* example implementation could be storing a class containing a correlation value, which is
* extracted from incoming requests and injected as-is onto outgoing requests.
*
*
Implementations are responsible for scoping any data stored here. This can be performed
* when {@link Propagation.Factory#decorate(TraceContext)} is called.
*/
public List