Note: this is a uniform decision for the entire trace. Advanced sampling patterns can + * overlay this via {@link Propagation.Factory#isNoop(TraceContext)}. For example, a noop context + * usually implies sampled is false or unset. However, you can collect data anyway, locally for + * metrics, or to an aggregation stream. */ - @Nullable public abstract Boolean sampled(); + @Nullable public final Boolean sampled() { + return sampled(flags); + } /** * True is a request to store this span even if it overrides sampling policy. Defaults to false. */ - public abstract boolean debug(); + public final boolean debug() { + return debug(flags); + } + + @Override public String toString() { + return "SamplingFlags(sampled=" + sampled() + ", debug=" + debug() + ")"; + } public static final class Builder { - Boolean sampled; - boolean debug = false; + int flags = 0; // bit field for sampled and debug public Builder() { // public constructor instead of static newBuilder which would clash with TraceContext's } public Builder sampled(@Nullable Boolean sampled) { - this.sampled = sampled; + if (sampled == null) { + flags &= ~FLAG_SAMPLED_SET; + flags &= ~FLAG_SAMPLED; + return this; + } + flags |= FLAG_SAMPLED_SET; + if (sampled) { + flags |= FLAG_SAMPLED; + } else { + flags &= ~FLAG_SAMPLED; + } return this; } + /** Ensures sampled is set when debug is */ public Builder debug(boolean debug) { - this.debug = debug; - if (debug) sampled(true); + if (debug) { + flags |= FLAG_DEBUG; + flags |= FLAG_SAMPLED_SET; + flags |= FLAG_SAMPLED; + } else { + flags &= ~FLAG_DEBUG; + } return this; } + /** Allows you to create flags from a boolean value without allocating a builder instance */ public static SamplingFlags build(@Nullable Boolean sampled) { if (sampled != null) return sampled ? SAMPLED : NOT_SAMPLED; @@ -46,47 +85,18 @@ public static SamplingFlags build(@Nullable Boolean sampled) { } public SamplingFlags build() { - if (debug) return DEBUG; - return build(sampled); - } - } - - static final class SamplingFlagsImpl extends SamplingFlags { - final Boolean sampled; - final boolean debug; - - SamplingFlagsImpl(Boolean sampled, boolean debug) { - this.sampled = sampled; - this.debug = debug; - } - - @Override public Boolean sampled() { - return sampled; - } - - @Override public boolean debug() { - return debug; - } - - @Override public String toString() { - return "SamplingFlags(sampled=" + sampled + ", debug=" + debug + ")"; + return flags == 0 ? EMPTY : SamplingFlags.debug(flags) ? DEBUG + : SamplingFlags.sampled(flags) ? SAMPLED : NOT_SAMPLED; } } - SamplingFlags() { - } - - static final int FLAG_SAMPLED = 1 << 1; - static final int FLAG_SAMPLED_SET = 1 << 2; - static final int FLAG_DEBUG = 1 << 3; - - static Boolean sampled(int flags) { + private static Boolean sampled(int flags) { return (flags & FLAG_SAMPLED_SET) == FLAG_SAMPLED_SET ? (flags & FLAG_SAMPLED) == FLAG_SAMPLED : null; } - static boolean debug(int flags) { + private static boolean debug(int flags) { return (flags & FLAG_DEBUG) == FLAG_DEBUG; } } diff --git a/brave/src/main/java/brave/propagation/ThreadLocalSpan.java b/brave/src/main/java/brave/propagation/ThreadLocalSpan.java index 8d92ed1bcf..046ed57cab 100644 --- a/brave/src/main/java/brave/propagation/ThreadLocalSpan.java +++ b/brave/src/main/java/brave/propagation/ThreadLocalSpan.java @@ -5,7 +5,6 @@ import brave.Tracer.SpanInScope; import brave.Tracing; import brave.internal.Nullable; -import com.google.auto.value.AutoValue; import java.util.ArrayDeque; import java.util.Deque; @@ -75,21 +74,21 @@ * } * } */ -@AutoValue -public abstract class ThreadLocalSpan { +public class ThreadLocalSpan { /** * This uses the {@link Tracing#currentTracer()}, which means calls to {@link #next()} may return * null. Use this when you have no other means to get a reference to the tracer. For example, JDBC * connections, as they often initialize prior to the tracing component. */ - public static final ThreadLocalSpan CURRENT_TRACER = new ThreadLocalSpan() { + public static final ThreadLocalSpan CURRENT_TRACER = new ThreadLocalSpan(null) { @Override Tracer tracer() { return Tracing.currentTracer(); } }; public static ThreadLocalSpan create(Tracer tracer) { - return new AutoValue_ThreadLocalSpan(tracer); + if (tracer == null) throw new NullPointerException("tracer == null"); + return new ThreadLocalSpan(tracer); } /** @@ -103,7 +102,15 @@ public static ThreadLocalSpan create(Tracer tracer) { } }; - abstract Tracer tracer(); + final Tracer tracer; + + ThreadLocalSpan(Tracer tracer) { + this.tracer = tracer; + } + + Tracer tracer() { + return tracer; + } /** * Returns the {@link Tracer#nextSpan(TraceContextOrSamplingFlags)} or null if {@link #CURRENT_TRACER} @@ -113,7 +120,7 @@ public static ThreadLocalSpan create(Tracer tracer) { Tracer tracer = tracer(); if (tracer == null) return null; Span next = tracer.nextSpan(extracted); - SpanAndScope spanAndScope = SpanAndScope.create(next, tracer.withSpanInScope(next)); + SpanAndScope spanAndScope = new SpanAndScope(next, tracer.withSpanInScope(next)); currentSpanInScope.get().addFirst(spanAndScope); return next; } @@ -126,7 +133,7 @@ public static ThreadLocalSpan create(Tracer tracer) { Tracer tracer = tracer(); if (tracer == null) return null; Span next = tracer.nextSpan(); - SpanAndScope spanAndScope = SpanAndScope.create(next, tracer.withSpanInScope(next)); + SpanAndScope spanAndScope = new SpanAndScope(next, tracer.withSpanInScope(next)); currentSpanInScope.get().addFirst(spanAndScope); return next; } @@ -144,24 +151,37 @@ public static ThreadLocalSpan create(Tracer tracer) { SpanAndScope scope = currentSpanInScope.get().pollFirst(); if (scope == null) return currentSpan; - scope.scope().close(); - assert scope.span().equals(currentSpan) : - "Misalignment: scoped span " + scope.span() + " != current span " + currentSpan; + scope.scope.close(); + assert scope.span.equals(currentSpan) : + "Misalignment: scoped span " + scope.span + " != current span " + currentSpan; return currentSpan; } - ThreadLocalSpan() { - } - /** Allows state checks when nesting spans */ - @AutoValue - static abstract class SpanAndScope { - static SpanAndScope create(Span span, SpanInScope scope) { - return new AutoValue_ThreadLocalSpan_SpanAndScope(span, scope); + static final class SpanAndScope { + + final Span span; + final SpanInScope scope; + + SpanAndScope(Span span, SpanInScope scope) { + this.span = span; + this.scope = scope; } - abstract Span span(); + @Override public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof SpanAndScope)) return false; + SpanAndScope that = (SpanAndScope) o; + return span.equals(that.span) && scope.equals(that.scope); + } - abstract SpanInScope scope(); + @Override public int hashCode() { + int h = 1; + h *= 1000003; + h ^= span.hashCode(); + h *= 1000003; + h ^= scope.hashCode(); + return h; + } } } diff --git a/brave/src/main/java/brave/propagation/TraceContext.java b/brave/src/main/java/brave/propagation/TraceContext.java index 2d3ca23d6a..9648af5296 100644 --- a/brave/src/main/java/brave/propagation/TraceContext.java +++ b/brave/src/main/java/brave/propagation/TraceContext.java @@ -93,16 +93,6 @@ public long parentIdAsLong() { return parentId; } - /** {@inheritDoc} */ - @Override @Nullable public Boolean sampled() { - return sampled(flags); - } - - /** {@inheritDoc} */ - @Override public boolean debug() { - return debug(flags); - } - /** * Unique 8-byte identifier of this span within a trace. * @@ -240,15 +230,14 @@ public final TraceContext build() { } final long traceIdHigh, traceId, parentId, spanId; - final int flags; // bit field for sampled and debug final List
When present, a link from {@link Tracing.Builder#localServiceName(String)} to this name + * will increment for each traced client call. * *
As this is endpoint-specific, it is typical to create a scoped instance of {@linkplain * HttpTracing} to assign this value. @@ -54,7 +40,9 @@ public static Builder newBuilder(Tracing tracing) { * @see HttpClientAdapter#parseServerAddress(Object, Endpoint.Builder) * @see brave.Span#remoteEndpoint(Endpoint) */ - public abstract String serverName(); + public String serverName() { + return serverName; + } /** * Scopes this component for a client of the indicated server. @@ -65,7 +53,9 @@ public HttpTracing clientOf(String serverName) { return toBuilder().serverName(serverName).build(); } - public abstract HttpServerParser serverParser(); + public HttpServerParser serverParser() { + return serverParser; + } /** * Returns an overriding sampling decision for a new trace. Defaults to ignore the request and use @@ -75,24 +65,83 @@ public HttpTracing clientOf(String serverName) { * making an http request as a part of booting your application. You may want to opt-out of * tracing client requests that did not originate from a server request. */ - public abstract HttpSampler clientSampler(); + public HttpSampler clientSampler() { + return clientSampler; + } /** * Returns an overriding sampling decision for a new trace. Defaults to ignore the request and use * the {@link HttpSampler#TRACE_ID trace ID instead}. * - *
This decision happens when trace IDs were not in headers, or a sampling decision has not yet - * been made. For example, if a trace is already in progress, this function is not called. You can - * implement this to skip paths that you never want to trace. + *
This decision happens when trace IDs were not in headers, or a sampling decision has not
+ * yet been made. For example, if a trace is already in progress, this function is not called. You
+ * can implement this to skip paths that you never want to trace.
*/
- public abstract HttpSampler serverSampler();
+ public HttpSampler serverSampler() {
+ return serverSampler;
+ }
- public abstract Builder toBuilder();
+ public Builder toBuilder() {
+ return new Builder(this);
+ }
+
+ final Tracing tracing;
+ final HttpClientParser clientParser;
+ final String serverName;
+ final HttpServerParser serverParser;
+ final HttpSampler clientSampler, serverSampler;
+
+ HttpTracing(Builder builder) {
+ this.tracing = builder.tracing;
+ this.clientParser = builder.clientParser;
+ this.serverName = builder.serverName;
+ this.serverParser = builder.serverParser;
+ this.clientSampler = builder.clientSampler;
+ this.serverSampler = builder.serverSampler;
+ }
+
+ public static final class Builder {
+ Tracing tracing;
+ HttpClientParser clientParser;
+ String serverName;
+ HttpServerParser serverParser;
+ HttpSampler clientSampler, serverSampler;
+
+ Builder(Tracing tracing) {
+ if (tracing == null) throw new NullPointerException("tracing == null");
+ final ErrorParser errorParser = tracing.errorParser();
+ this.tracing = tracing;
+ this.serverName = "";
+ // override to re-use any custom error parser from the tracing component
+ this.clientParser = new HttpClientParser() {
+ @Override protected ErrorParser errorParser() {
+ return errorParser;
+ }
+ };
+ this.serverParser = new HttpServerParser() {
+ @Override protected ErrorParser errorParser() {
+ return errorParser;
+ }
+ };
+ this.clientSampler = HttpSampler.TRACE_ID;
+ this.serverSampler(HttpSampler.TRACE_ID);
+ }
+
+ Builder(HttpTracing source) {
+ this.tracing = source.tracing;
+ this.clientParser = source.clientParser;
+ this.serverName = source.serverName;
+ this.serverParser = source.serverParser;
+ this.clientSampler = source.clientSampler;
+ this.serverSampler = source.serverSampler;
+ }
- @AutoValue.Builder
- public static abstract class Builder {
/** @see HttpTracing#tracing() */
- public abstract Builder tracing(Tracing tracing);
+ public Builder tracing(Tracing tracing) {
+ if (tracing == null) throw new NullPointerException("tracing == null");
+ this.tracing = tracing;
+ return this;
+ }
/**
* Overrides the tagging policy for http client spans.
@@ -100,7 +149,17 @@ public static abstract class Builder {
* @see HttpParser#errorParser() for advice when making custom types
* @see HttpTracing#clientParser()
*/
- public abstract Builder clientParser(HttpClientParser clientParser);
+ public Builder clientParser(HttpClientParser clientParser) {
+ if (clientParser == null) throw new NullPointerException("clientParser == null");
+ this.clientParser = clientParser;
+ return this;
+ }
+
+ Builder serverName(String serverName) {
+ if (serverName == null) throw new NullPointerException("serverName == null");
+ this.serverName = serverName;
+ return this;
+ }
/**
* Overrides the tagging policy for http client spans.
@@ -108,22 +167,29 @@ public static abstract class Builder {
* @see HttpParser#errorParser() for advice when making custom types
* @see HttpTracing#serverParser()
*/
- public abstract Builder serverParser(HttpServerParser serverParser);
+ public Builder serverParser(HttpServerParser serverParser) {
+ if (serverParser == null) throw new NullPointerException("serverParser == null");
+ this.serverParser = serverParser;
+ return this;
+ }
/** @see HttpTracing#clientSampler() */
- public abstract Builder clientSampler(HttpSampler clientSampler);
-
- /** @see HttpTracing#serverSampler() */
- public abstract Builder serverSampler(HttpSampler serverSampler);
-
- public abstract HttpTracing build();
+ public Builder clientSampler(HttpSampler clientSampler) {
+ if (clientSampler == null) throw new NullPointerException("clientSampler == null");
- abstract Builder serverName(String serverName);
+ this.clientSampler = clientSampler;
+ return this;
+ }
- Builder() {
+ /** @see HttpTracing#serverSampler() */
+ public Builder serverSampler(HttpSampler serverSampler) {
+ if (serverSampler == null) throw new NullPointerException("serverSampler == null");
+ this.serverSampler = serverSampler;
+ return this;
}
- }
- HttpTracing() { // intentionally hidden constructor
+ public HttpTracing build() {
+ return new HttpTracing(this);
+ }
}
}
diff --git a/instrumentation/jaxrs2/pom.xml b/instrumentation/jaxrs2/pom.xml
index 3a016c3efb..58ca3bdd8d 100644
--- a/instrumentation/jaxrs2/pom.xml
+++ b/instrumentation/jaxrs2/pom.xml
@@ -31,6 +31,7 @@