fields) {
if (finishCalled) return this;
diff --git a/src/main/java/brave/opentracing/BraveSpanBuilder.java b/src/main/java/brave/opentracing/BraveSpanBuilder.java
index 7699a5d..b17f00d 100644
--- a/src/main/java/brave/opentracing/BraveSpanBuilder.java
+++ b/src/main/java/brave/opentracing/BraveSpanBuilder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-2018 The OpenZipkin Authors
+ * Copyright 2016-2019 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
@@ -16,10 +16,10 @@
import brave.propagation.TraceContext;
import brave.sampler.Sampler;
import io.opentracing.References;
-import io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.SpanContext;
import io.opentracing.Tracer;
+import io.opentracing.tag.Tag;
import io.opentracing.tag.Tags;
import java.util.LinkedHashMap;
import java.util.Map;
@@ -34,21 +34,18 @@
* Brave does not support multiple parents so this has been implemented to use the first parent
* defined.
*/
-public final class BraveSpanBuilder implements Tracer.SpanBuilder {
+public class BraveSpanBuilder implements Tracer.SpanBuilder {
+ final brave.Tracer tracer;
+ final Map tags = new LinkedHashMap<>();
- private final Tracer tracer;
- private final brave.Tracer braveTracer;
- private final Map tags = new LinkedHashMap<>();
+ String operationName;
+ long timestamp;
+ int remotePort;
+ BraveSpanContext reference;
+ boolean ignoreActiveSpan = false;
- private String operationName;
- private long timestamp;
- private int remotePort;
- private BraveSpanContext reference;
- private boolean ignoreActiveSpan = false;
-
- BraveSpanBuilder(Tracer tracer, brave.Tracer braveTracer, String operationName) {
+ BraveSpanBuilder(brave.Tracer tracer, String operationName) {
this.tracer = tracer;
- this.braveTracer = braveTracer;
this.operationName = operationName;
}
@@ -61,9 +58,7 @@ public final class BraveSpanBuilder implements Tracer.SpanBuilder {
}
@Override public BraveSpanBuilder addReference(String type, SpanContext context) {
- if (reference != null || context == null) {
- return this;
- }
+ if (reference != null || context == null) return this;
if (References.CHILD_OF.equals(type) || References.FOLLOWS_FROM.equals(type)) {
this.reference = (BraveSpanContext) context;
}
@@ -88,25 +83,20 @@ public final class BraveSpanBuilder implements Tracer.SpanBuilder {
return withTag(key, value.toString());
}
+ @Override public BraveSpanBuilder withTag(Tag tag, T value) {
+ if (tag == null) throw new NullPointerException("tag == null");
+ if (value == null) throw new NullPointerException("value == null");
+ if (value instanceof String) return withTag(tag.getKey(), (String) value);
+ if (value instanceof Number) return withTag(tag.getKey(), (Number) value);
+ if (value instanceof Boolean) return withTag(tag.getKey(), (Boolean) value);
+ throw new IllegalArgumentException("tag value not a string, number or boolean: " + value);
+ }
+
@Override public BraveSpanBuilder withStartTimestamp(long microseconds) {
this.timestamp = microseconds;
return this;
}
- @Override @Deprecated public BraveSpan startManual() {
- return start();
- }
-
- @Override public Scope startActive(boolean finishSpanOnClose) {
- if (!ignoreActiveSpan) {
- Scope parent = tracer.scopeManager().active();
- if (parent != null) {
- asChildOf(parent.span());
- }
- }
- return tracer.scopeManager().activate(start(), finishSpanOnClose);
- }
-
@Override public BraveSpanBuilder ignoreActiveSpan() {
ignoreActiveSpan = true;
return this;
@@ -117,10 +107,8 @@ public final class BraveSpanBuilder implements Tracer.SpanBuilder {
// Check if active span should be established as CHILD_OF relationship
if (reference == null && !ignoreActiveSpan) {
- Scope parent = tracer.scopeManager().active();
- if (parent != null) {
- asChildOf(parent.span());
- }
+ brave.Span parent = tracer.currentSpan();
+ if (parent != null) asChildOf(BraveSpanContext.create(parent.context()));
}
brave.Span span;
@@ -128,32 +116,32 @@ public final class BraveSpanBuilder implements Tracer.SpanBuilder {
if (reference == null) {
// adjust sampling decision, this reflects Zipkin's "before the fact" sampling policy
// https://github.com/openzipkin/brave/tree/master/brave#sampling
- brave.Tracer scopedBraveTracer = braveTracer;
+ brave.Tracer scopedTracer = tracer;
String sampling = tags.get(Tags.SAMPLING_PRIORITY.getKey());
if (sampling != null) {
try {
Integer samplingPriority = Integer.valueOf(sampling);
if (samplingPriority == 0) {
- scopedBraveTracer = braveTracer.withSampler(Sampler.NEVER_SAMPLE);
+ scopedTracer = tracer.withSampler(Sampler.NEVER_SAMPLE);
} else if (samplingPriority > 0) {
- scopedBraveTracer = braveTracer.withSampler(Sampler.ALWAYS_SAMPLE);
+ scopedTracer = tracer.withSampler(Sampler.ALWAYS_SAMPLE);
}
} catch (NumberFormatException ex) {
// ignore
}
}
- span = scopedBraveTracer.newTrace();
+ span = scopedTracer.newTrace();
} else if ((context = reference.unwrap()) != null) {
// Zipkin's default is to share a span ID between the client and the server in an RPC.
// When we start a server span with a parent, we assume the "parent" is actually the
// client on the other side of the RPC. Accordingly, we join that span instead of fork.
- span = server ? braveTracer.joinSpan(context) : braveTracer.newChild(context);
+ span = server ? tracer.joinSpan(context) : tracer.newChild(context);
} else {
- span = braveTracer.nextSpan(((BraveSpanContext.Incomplete) reference).extractionResult());
+ span = tracer.nextSpan(((BraveSpanContext.Incomplete) reference).extractionResult());
}
if (operationName != null) span.name(operationName);
- BraveSpan result = new BraveSpan(braveTracer, span);
+ BraveSpan result = new BraveSpan(tracer, span);
result.remotePort = remotePort;
for (Map.Entry tag : tags.entrySet()) {
result.setTag(tag.getKey(), tag.getValue());
@@ -167,4 +155,14 @@ public final class BraveSpanBuilder implements Tracer.SpanBuilder {
return result;
}
+
+ /* @Override deprecated 0.32 method: Intentionally no override to ensure 0.33 works! */
+ @Deprecated public BraveSpan startManual() {
+ throw new UnsupportedOperationException("Not supported in OpenTracing 0.33+");
+ }
+
+ /* @Override deprecated 0.32 method: Intentionally no override to ensure 0.33 works! */
+ @Deprecated public BraveScope startActive(boolean finishSpanOnClose) {
+ throw new UnsupportedOperationException("Not supported in OpenTracing 0.33+");
+ }
}
diff --git a/src/main/java/brave/opentracing/BraveSpanContext.java b/src/main/java/brave/opentracing/BraveSpanContext.java
index d295cba..9672c25 100644
--- a/src/main/java/brave/opentracing/BraveSpanContext.java
+++ b/src/main/java/brave/opentracing/BraveSpanContext.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-2018 The OpenZipkin Authors
+ * Copyright 2016-2019 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
@@ -13,6 +13,7 @@
*/
package brave.opentracing;
+import brave.Span;
import brave.propagation.ExtraFieldPropagation;
import brave.propagation.TraceContext;
import brave.propagation.TraceContextOrSamplingFlags;
@@ -22,8 +23,8 @@
/**
* 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 brave.NoopSpan}.
+ * TraceContextOrSamplingFlags extraction result if an incoming context}. An {@link
+ * TraceContext#sampled() unsampled} context results in a {@link Span#isNoop() noop span}.
*
* This type also includes hooks to integrate with the underlying {@linkplain brave.Tracer}. Ex
* you can access the underlying trace context with {@link #unwrap}
@@ -35,11 +36,12 @@ public abstract class BraveSpanContext implements SpanContext {
*
*
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.
+ * extracted from headers. In other words, unwrap might not have a {@link TraceContext} to
+ * return.
*
*
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.
+ * 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();
@@ -67,6 +69,15 @@ static final class Complete extends BraveSpanContext {
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> baggageItems() {
return ExtraFieldPropagation.getAll(context).entrySet();
}
@@ -88,6 +99,17 @@ TraceContextOrSamplingFlags extractionResult() { // temporarily hidden
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 ExtraFieldPropagation} is in use */
@Override public Iterable> baggageItems() {
return ExtraFieldPropagation.getAll(extractionResult).entrySet();
diff --git a/src/main/java/brave/opentracing/BraveTracer.java b/src/main/java/brave/opentracing/BraveTracer.java
index 656ec37..3c46806 100644
--- a/src/main/java/brave/opentracing/BraveTracer.java
+++ b/src/main/java/brave/opentracing/BraveTracer.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-2018 The OpenZipkin Authors
+ * Copyright 2016-2019 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
@@ -14,6 +14,7 @@
package brave.opentracing;
import brave.Tracing;
+import brave.propagation.B3SingleFormat;
import brave.propagation.CurrentTraceContext;
import brave.propagation.ExtraFieldPropagation;
import brave.propagation.Propagation;
@@ -23,12 +24,15 @@
import brave.propagation.TraceContext.Extractor;
import brave.propagation.TraceContext.Injector;
import brave.propagation.TraceContextOrSamplingFlags;
-import io.opentracing.Scope;
import io.opentracing.ScopeManager;
+import io.opentracing.Span;
import io.opentracing.SpanContext;
import io.opentracing.Tracer;
+import io.opentracing.propagation.BinaryExtract;
+import io.opentracing.propagation.BinaryInject;
import io.opentracing.propagation.Format;
import io.opentracing.propagation.TextMap;
+import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
@@ -37,6 +41,12 @@
import java.util.Map;
import java.util.Set;
+import static io.opentracing.propagation.Format.Builtin.BINARY;
+import static io.opentracing.propagation.Format.Builtin.BINARY_EXTRACT;
+import static io.opentracing.propagation.Format.Builtin.BINARY_INJECT;
+import static io.opentracing.propagation.Format.Builtin.TEXT_MAP_EXTRACT;
+import static io.opentracing.propagation.Format.Builtin.TEXT_MAP_INJECT;
+
/**
* Using a tracer, you can create a spans, inject span contexts into a transport, and extract span
* contexts from a transport
@@ -55,13 +65,18 @@
* Span clientSpan = tracer.buildSpan('...').asChildOf(clientContext).start();
*
*
+ * Propagation
+ * This uses the same propagation as defined in zipkin for text formats. B3 Single is used for
+ * binary formats.
+ *
* @see BraveSpan
* @see Propagation
*/
public final class BraveTracer implements Tracer {
-
- private final brave.Tracer brave4;
- private final BraveScopeManager scopeManager;
+ final Tracing tracing;
+ final brave.Tracer delegate;
+ final BraveScopeManager scopeManager;
/**
* Returns an implementation of {@link Tracer} which delegates to the provided Brave {@link
@@ -78,6 +93,16 @@ public static BraveTracer create(Tracing brave4) {
* ScopeManager}.
*/
public static Builder newBuilder(Tracing brave4) {
+ // This is the only public entrypoint into the brave-opentracing bridge. The following will
+ // raise an exception when using an incompatible version of opentracing-api. Notably, this
+ // unwraps ExceptionInInitializerError to avoid confusing users, as this is an implementation
+ // detail of the version singleton.
+ try {
+ OpenTracingVersion.get();
+ } catch (ExceptionInInitializerError e) {
+ if (e.getCause() instanceof RuntimeException) throw (RuntimeException) e.getCause();
+ throw e;
+ }
return new Builder(brave4);
}
@@ -89,6 +114,7 @@ public static final class Builder {
Builder(Tracing tracing) {
if (tracing == null) throw new NullPointerException("brave tracing component == null");
this.tracing = tracing;
+
formatToPropagation.put(Format.Builtin.HTTP_HEADERS, tracing.propagation());
formatToPropagation.put(Format.Builtin.TEXT_MAP, tracing.propagation());
}
@@ -122,16 +148,29 @@ public BraveTracer build() {
}
}
- final Map, Injector> formatToInjector = new LinkedHashMap<>();
- final Map, Extractor> formatToExtractor = new LinkedHashMap<>();
+ final Map, Injector>> formatToInjector = new LinkedHashMap<>();
+ final Map, Extractor>> formatToExtractor = new LinkedHashMap<>();
BraveTracer(Builder b) {
- brave4 = b.tracing.tracer();
- scopeManager = new BraveScopeManager(b.tracing);
+ tracing = b.tracing;
+ delegate = b.tracing.tracer();
+ scopeManager = OpenTracingVersion.get().scopeManager(b.tracing);
for (Map.Entry, Propagation> entry : b.formatToPropagation.entrySet()) {
formatToInjector.put(entry.getKey(), entry.getValue().injector(TEXT_MAP_SETTER));
formatToExtractor.put(entry.getKey(), new TextMapExtractorAdaptor(entry.getValue()));
}
+
+ // Now, go back and make sure the special inject/extract forms work
+ for (Propagation propagation : b.formatToPropagation.values()) {
+ formatToInjector.put(TEXT_MAP_INJECT, propagation.injector(TEXT_MAP_SETTER));
+ formatToExtractor.put(TEXT_MAP_EXTRACT, new TextMapExtractorAdaptor(propagation));
+ }
+
+ // Finally add binary support
+ formatToInjector.put(BINARY, BinaryCodec.INSTANCE);
+ formatToInjector.put(BINARY_INJECT, BinaryCodec.INSTANCE);
+ formatToExtractor.put(BINARY, BinaryCodec.INSTANCE);
+ formatToExtractor.put(BINARY_EXTRACT, BinaryCodec.INSTANCE);
}
@Override public BraveScopeManager scopeManager() {
@@ -139,24 +178,27 @@ public BraveTracer build() {
}
@Override public BraveSpan activeSpan() {
- Scope scope = this.scopeManager.active();
- return scope != null ? (BraveSpan) scope.span() : null;
+ return scopeManager.activeSpan();
+ }
+
+ @Override public BraveScope activateSpan(Span span) {
+ return scopeManager.activate(span);
}
@Override public BraveSpanBuilder buildSpan(String operationName) {
- return new BraveSpanBuilder(this, brave4, operationName);
+ return OpenTracingVersion.get().spanBuilder(this, operationName);
}
/**
* Injects the underlying context using B3 encoding by default.
*/
@Override public void inject(SpanContext spanContext, Format format, C carrier) {
- Injector injector = formatToInjector.get(format);
+ Injector injector = (Injector) formatToInjector.get(format);
if (injector == null) {
throw new UnsupportedOperationException(format + " not in " + formatToInjector.keySet());
}
TraceContext traceContext = ((BraveSpanContext) spanContext).unwrap();
- injector.inject(traceContext, (TextMap) carrier);
+ injector.inject(traceContext, carrier);
}
/**
@@ -164,15 +206,19 @@ public BraveTracer build() {
* encoded context in the carrier, or upon error extracting it.
*/
@Override public BraveSpanContext extract(Format format, C carrier) {
- Extractor extractor = formatToExtractor.get(format);
+ Extractor extractor = (Extractor) formatToExtractor.get(format);
if (extractor == null) {
throw new UnsupportedOperationException(format + " not in " + formatToExtractor.keySet());
}
- TraceContextOrSamplingFlags extractionResult = extractor.extract((TextMap) carrier);
+ TraceContextOrSamplingFlags extractionResult = extractor.extract(carrier);
return BraveSpanContext.create(extractionResult);
}
- static final Setter TEXT_MAP_SETTER = new Setter(){
+ @Override public void close() {
+ tracing.close();
+ }
+
+ static final Setter TEXT_MAP_SETTER = new Setter() {
@Override public void put(TextMap carrier, String key, String value) {
carrier.put(key, value);
}
@@ -231,4 +277,24 @@ static Set lowercaseSet(List fields) {
}
return lcSet;
}
+
+ // Temporary until https://github.com/openzipkin/brave/issues/928
+ enum BinaryCodec implements Injector, Extractor {
+ INSTANCE;
+
+ final Charset ascii = Charset.forName("US-ASCII");
+
+ @Override public TraceContextOrSamplingFlags extract(BinaryExtract binaryExtract) {
+ try {
+ return B3SingleFormat.parseB3SingleFormat(ascii.decode(binaryExtract.extractionBuffer()));
+ } catch (RuntimeException e) {
+ return TraceContextOrSamplingFlags.EMPTY;
+ }
+ }
+
+ @Override public void inject(TraceContext traceContext, BinaryInject binaryInject) {
+ byte[] injected = B3SingleFormat.writeB3SingleFormatAsBytes(traceContext);
+ binaryInject.injectionBuffer(injected.length).put(injected);
+ }
+ }
}
diff --git a/src/main/java/brave/opentracing/OpenTracingVersion.java b/src/main/java/brave/opentracing/OpenTracingVersion.java
new file mode 100644
index 0000000..3846e54
--- /dev/null
+++ b/src/main/java/brave/opentracing/OpenTracingVersion.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2016-2019 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.Tracing;
+import io.opentracing.ScopeManager;
+import io.opentracing.Span;
+
+/**
+ * Access to version-specific features.
+ *
+ * Originally designed by OkHttp team, derived from {@code okhttp3.internal.platform.OpenTracingVersion}
+ */
+abstract class OpenTracingVersion {
+ private static final OpenTracingVersion INSTANCE = findVersion();
+
+ static OpenTracingVersion get() {
+ return INSTANCE;
+ }
+
+ BraveScopeManager scopeManager(Tracing tracing) {
+ return new BraveScopeManager(tracing.tracer());
+ }
+
+ BraveSpanBuilder spanBuilder(BraveTracer braveTracer, String operationName) {
+ return new BraveSpanBuilder(braveTracer.delegate, operationName);
+ }
+
+ /** Attempt to match the host runtime to a capable OpenTracingVersion implementation. */
+ private static OpenTracingVersion findVersion() {
+ if (isV0_31()) {
+ throw new UnsupportedOperationException("OpenTracing 0.31 detected. "
+ + "This version is compatible with io.opentracing:opentracing-api 0.32 or 0.33. "
+ + "io.opentracing.brave:brave-opentracing:0.33.13+ works with version 0.31");
+ }
+
+ OpenTracingVersion version = v0_32.buildIfSupported();
+ if (version != null) return version;
+
+ version = v0_33.buildIfSupported();
+ if (version != null) return version;
+
+ throw new UnsupportedOperationException(
+ "This is only compatible with io.opentracing:opentracing-api 0.32 or 0.33");
+ }
+
+ static boolean isV0_31() {
+ // Find OpenTracing 0.31 method
+ try {
+ if (ScopeManager.class.getMethod("activate", Span.class, boolean.class)
+ .getAnnotation(Deprecated.class) == null) {
+ return true;
+ }
+ } catch (NoSuchMethodException e) {
+ }
+ return false;
+ }
+
+ static class v0_32 extends OpenTracingVersion {
+ static v0_32 buildIfSupported() {
+ // Find OpenTracing 0.32 deprecated method
+ try {
+ if (ScopeManager.class.getMethod("activate", Span.class, boolean.class)
+ .getAnnotation(Deprecated.class) != null) {
+ return new v0_32();
+ }
+ } catch (NoSuchMethodException e) {
+ }
+ return null;
+ }
+
+ @Override BraveScopeManager scopeManager(Tracing tracing) {
+ return new v0_32_BraveScopeManager(tracing.tracer());
+ }
+
+ @Override BraveSpanBuilder spanBuilder(BraveTracer braveTracer, String operationName) {
+ return new v0_32_BraveSpanBuilder(braveTracer.scopeManager, operationName);
+ }
+
+ @Override public String toString() {
+ return "v0_32{}";
+ }
+
+ v0_32() {
+ }
+ }
+
+ static class v0_33 extends OpenTracingVersion {
+ static v0_33 buildIfSupported() {
+ // Find OpenTracing 0.32 new type
+ try {
+ Class.forName("io.opentracing.tag.Tag");
+ return new v0_33();
+ } catch (ClassNotFoundException e) {
+ }
+ return null;
+ }
+
+ @Override public String toString() {
+ return "v0_33{}";
+ }
+
+ v0_33() {
+ }
+ }
+}
diff --git a/src/main/java/brave/opentracing/v0_32_BraveScope.java b/src/main/java/brave/opentracing/v0_32_BraveScope.java
new file mode 100644
index 0000000..24bdd85
--- /dev/null
+++ b/src/main/java/brave/opentracing/v0_32_BraveScope.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2016-2019 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.Tracer.SpanInScope;
+
+final class v0_32_BraveScope extends BraveScope {
+ final v0_32_BraveScopeManager source;
+ final BraveSpan wrapped;
+ final boolean finishSpanOnClose;
+
+ /**
+ * @param delegate a SpanInScope to be closed upon deactivation of this ActiveSpan
+ * @param source the BraveActiveSpanSource that created this BraveActiveSpan
+ * @param wrapped the wrapped BraveSpan to which we will delegate all span operations
+ */
+ v0_32_BraveScope(SpanInScope delegate, v0_32_BraveScopeManager source, BraveSpan wrapped,
+ boolean finishSpanOnClose) {
+ super(delegate);
+ this.source = source;
+ this.wrapped = wrapped;
+ this.finishSpanOnClose = finishSpanOnClose;
+ }
+
+ @Override public void close() {
+ super.close();
+ if (finishSpanOnClose) wrapped.finish();
+ source.deregister(this);
+ }
+
+ @Override @Deprecated public BraveSpan span() {
+ return wrapped;
+ }
+
+ @Override public String toString() {
+ return "BraveScope{scope=" + delegate + ", wrapped=" + wrapped.delegate + '}';
+ }
+}
diff --git a/src/main/java/brave/opentracing/v0_32_BraveScopeManager.java b/src/main/java/brave/opentracing/v0_32_BraveScopeManager.java
new file mode 100644
index 0000000..30db739
--- /dev/null
+++ b/src/main/java/brave/opentracing/v0_32_BraveScopeManager.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2016-2019 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.Tracer;
+import brave.propagation.CurrentTraceContext;
+import io.opentracing.Scope;
+import io.opentracing.Span;
+import java.util.ArrayDeque;
+import java.util.Deque;
+
+/** This integrates with Brave's {@link CurrentTraceContext}. */
+final class v0_32_BraveScopeManager extends BraveScopeManager {
+ // This probably needs to be redesigned to stash the OpenTracing span in brave's .extra()
+ // We wouldn't have to do this if it weren't a requirement to return the same instance...
+ //
+ // When scopes are leaked this thread local will prevent this type from being unloaded. This can
+ // cause problems in redeployment scenarios. https://github.com/openzipkin/brave/issues/785
+ final ThreadLocal> currentScopes =
+ new ThreadLocal>() {
+ @Override protected Deque initialValue() {
+ return new ArrayDeque<>();
+ }
+ };
+
+ v0_32_BraveScopeManager(Tracer tracer) {
+ super(tracer);
+ }
+
+ @Override @Deprecated public Scope active() {
+ BraveSpan span = currentSpan();
+ if (span == null) return null;
+ return new Scope() {
+ @Override public void close() {
+ // no-op
+ }
+
+ /* @Override deprecated 0.32 method: Intentionally no override to ensure 0.33 works! */
+ @Deprecated public Span span() {
+ return span;
+ }
+ };
+ }
+
+ @Override @Deprecated BraveSpan currentSpan() {
+ BraveScope scope = currentScopes.get().peekFirst();
+ if (scope != null) {
+ return scope.span();
+ } else {
+ brave.Span braveSpan = tracer.currentSpan();
+ if (braveSpan != null) {
+ return new BraveSpan(tracer, braveSpan);
+ }
+ }
+ return null;
+ }
+
+ @Override public BraveScope activate(Span span) {
+ return activate(span, false);
+ }
+
+ @Override @Deprecated public BraveScope activate(Span span, boolean finishSpanOnClose) {
+ if (span == null) return null;
+ if (!(span instanceof BraveSpan)) {
+ throw new IllegalArgumentException(
+ "Span must be an instance of brave.opentracing.BraveSpan, but was " + span.getClass());
+ }
+ return newScope((BraveSpan) span, finishSpanOnClose);
+ }
+
+ BraveScope newScope(BraveSpan span, boolean finishSpanOnClose) {
+ v0_32_BraveScope result = new v0_32_BraveScope(
+ tracer.withSpanInScope(span.delegate), this, span, finishSpanOnClose
+ );
+ currentScopes.get().addFirst(result);
+ return result;
+ }
+
+ void deregister(BraveScope span) {
+ currentScopes.get().remove(span);
+ }
+}
diff --git a/src/main/java/brave/opentracing/v0_32_BraveSpanBuilder.java b/src/main/java/brave/opentracing/v0_32_BraveSpanBuilder.java
new file mode 100644
index 0000000..c01f301
--- /dev/null
+++ b/src/main/java/brave/opentracing/v0_32_BraveSpanBuilder.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2016-2019 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;
+
+final class v0_32_BraveSpanBuilder extends BraveSpanBuilder {
+ final BraveScopeManager scopeManager;
+
+ v0_32_BraveSpanBuilder(BraveScopeManager scopeManager, String operationName) {
+ super(scopeManager.tracer, operationName);
+ this.scopeManager = scopeManager;
+ }
+
+ @Override @Deprecated public BraveSpan startManual() {
+ return start();
+ }
+
+ @Override @Deprecated public BraveScope startActive(boolean finishSpanOnClose) {
+ if (!ignoreActiveSpan) {
+ BraveSpan parent = scopeManager.activeSpan();
+ if (parent != null) asChildOf(parent.context());
+ }
+ return scopeManager.activate(start(), finishSpanOnClose);
+ }
+}
diff --git a/src/test/java/brave/opentracing/BraveScopeManagerTest.java b/src/test/java/brave/opentracing/OpenTracing0_32_BraveScopeManagerTest.java
similarity index 94%
rename from src/test/java/brave/opentracing/BraveScopeManagerTest.java
rename to src/test/java/brave/opentracing/OpenTracing0_32_BraveScopeManagerTest.java
index 69f06e5..9052263 100644
--- a/src/test/java/brave/opentracing/BraveScopeManagerTest.java
+++ b/src/test/java/brave/opentracing/OpenTracing0_32_BraveScopeManagerTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-2018 The OpenZipkin Authors
+ * Copyright 2016-2019 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
@@ -25,8 +25,7 @@
import static org.assertj.core.api.Assertions.assertThat;
-public class BraveScopeManagerTest {
-
+public class OpenTracing0_32_BraveScopeManagerTest {
List spans = new ArrayList<>();
Tracing brave = Tracing.newBuilder()
.currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder()
@@ -37,6 +36,10 @@ public class BraveScopeManagerTest {
BraveTracer opentracing = BraveTracer.create(brave);
+ @After public void clear() {
+ brave.close();
+ }
+
@Test public void scopeManagerActive() {
BraveSpan span = opentracing.buildSpan("spanA").start();
@@ -87,9 +90,4 @@ public class BraveScopeManagerTest {
scopeB.close();
}
}
-
- @After public void clear() {
- Tracing current = Tracing.current();
- if (current != null) current.close();
- }
}
diff --git a/src/test/java/brave/opentracing/OpenTracing0_32_BraveTracerTest.java b/src/test/java/brave/opentracing/OpenTracing0_32_BraveTracerTest.java
new file mode 100644
index 0000000..fec4931
--- /dev/null
+++ b/src/test/java/brave/opentracing/OpenTracing0_32_BraveTracerTest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2016-2019 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.Tracing;
+import brave.propagation.B3Propagation;
+import brave.propagation.ExtraFieldPropagation;
+import brave.propagation.StrictScopeDecorator;
+import brave.propagation.ThreadLocalCurrentTraceContext;
+import brave.propagation.TraceContext;
+import io.opentracing.Scope;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import org.junit.After;
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.assertEquals;
+
+public class OpenTracing0_32_BraveTracerTest {
+ List spans = new ArrayList<>();
+ Tracing brave = Tracing.newBuilder()
+ .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder()
+ .addScopeDecorator(StrictScopeDecorator.create())
+ .build())
+ .propagationFactory(ExtraFieldPropagation.newFactoryBuilder(B3Propagation.FACTORY)
+ .addPrefixedFields("baggage-", Arrays.asList("country-code", "user-id"))
+ .build())
+ .spanReporter(spans::add)
+ .build();
+ BraveTracer opentracing = BraveTracer.create(brave);
+
+ @After public void clear() {
+ brave.close();
+ }
+
+ @Test public void versionIsCorrect() {
+ assertThat(OpenTracingVersion.get())
+ .isInstanceOf(OpenTracingVersion.v0_32.class);
+ }
+
+ /** OpenTracing span implements auto-closeable, and implies reporting on close */
+ @Test public void startActive_autoCloseOnTryFinally() {
+ try (Scope scope = opentracing.buildSpan("foo").startActive(true)) {
+ }
+
+ assertThat(spans)
+ .hasSize(1);
+ }
+
+ @Test public void startActive_autoCloseOnTryFinally_doesntReportTwice() {
+ try (Scope scope = opentracing.buildSpan("foo").startActive(true)) {
+ opentracing.activeSpan().finish(); // user closes and also auto-close closes
+ }
+
+ assertThat(spans)
+ .hasSize(1);
+ }
+
+ @Test public void startActive_autoCloseOnTryFinally_dontClose() {
+ try (Scope scope = opentracing.buildSpan("foo").startActive(false)) {
+ }
+
+ assertThat(spans)
+ .isEmpty();
+ }
+
+ @Test public void subsequentChildrenNestProperly_OTStyle() {
+ // this test is semantically identical to subsequentChildrenNestProperly_BraveStyle, but uses
+ // the OpenTracingAPI instead of the Brave API.
+
+ Long idOfSpanA;
+ Long shouldBeIdOfSpanA;
+ Long idOfSpanB;
+ Long shouldBeIdOfSpanB;
+ Long parentIdOfSpanB;
+ Long parentIdOfSpanC;
+
+ try (Scope scopeA = opentracing.buildSpan("spanA").startActive(false)) {
+ idOfSpanA = brave.currentTraceContext().get().spanId();
+ try (Scope scopeB = opentracing.buildSpan("spanB").startActive(false)) {
+ idOfSpanB = brave.currentTraceContext().get().spanId();
+ parentIdOfSpanB = brave.currentTraceContext().get().parentId();
+ shouldBeIdOfSpanB = brave.currentTraceContext().get().spanId();
+ }
+ shouldBeIdOfSpanA = brave.currentTraceContext().get().spanId();
+ try (Scope scopeC = opentracing.buildSpan("spanC").startActive(false)) {
+ parentIdOfSpanC = brave.currentTraceContext().get().parentId();
+ }
+ }
+
+ assertEquals("SpanA should have been active again after closing B", idOfSpanA,
+ shouldBeIdOfSpanA);
+ assertEquals("SpanB should have been active prior to its closure", idOfSpanB,
+ shouldBeIdOfSpanB);
+ assertEquals("SpanB's parent should be SpanA", idOfSpanA, parentIdOfSpanB);
+ assertEquals("SpanC's parent should be SpanA", idOfSpanA, parentIdOfSpanC);
+ }
+
+ @Test public void implicitParentFromSpanManager_startActive() {
+ try (BraveScope scopeA = opentracing.buildSpan("spanA").startActive(true)) {
+ try (BraveScope scopeB = opentracing.buildSpan("spanB").startActive(true)) {
+ TraceContext current = brave.currentTraceContext().get();
+ assertThat(scopeB.span().context().unwrap().parentId())
+ .isEqualTo(scopeA.span().context().unwrap().spanId());
+ }
+ }
+ }
+
+ @Test public void implicitParentFromSpanManager_start() {
+ try (Scope scopeA = opentracing.buildSpan("spanA").startActive(true)) {
+ BraveSpan span = opentracing.buildSpan("spanB").start();
+ assertThat(span.unwrap().context().parentId())
+ .isEqualTo(brave.currentTraceContext().get().spanId());
+ }
+ }
+
+ @Test public void implicitParentFromSpanManager_startActive_ignoreActiveSpan() {
+ try (Scope scopeA = opentracing.buildSpan("spanA").startActive(true)) {
+ try (Scope scopeB = opentracing.buildSpan("spanA")
+ .ignoreActiveSpan().startActive(true)) {
+ assertThat(brave.currentTraceContext().get().parentId())
+ .isNull(); // new trace
+ }
+ }
+ }
+
+ @Test public void implicitParentFromSpanManager_start_ignoreActiveSpan() {
+ try (Scope scopeA = opentracing.buildSpan("spanA").startActive(true)) {
+ BraveSpan span = opentracing.buildSpan("spanB")
+ .ignoreActiveSpan().start();
+ assertThat(span.unwrap().context().parentId())
+ .isNull(); // new trace
+ }
+ }
+}
diff --git a/src/test/java/brave/opentracing/OpenTracing0_33_BraveScopeManagerTest.java b/src/test/java/brave/opentracing/OpenTracing0_33_BraveScopeManagerTest.java
new file mode 100644
index 0000000..000be1f
--- /dev/null
+++ b/src/test/java/brave/opentracing/OpenTracing0_33_BraveScopeManagerTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2016-2019 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.ScopedSpan;
+import brave.Tracing;
+import brave.propagation.StrictScopeDecorator;
+import brave.propagation.ThreadLocalCurrentTraceContext;
+import io.opentracing.Scope;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.After;
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class OpenTracing0_33_BraveScopeManagerTest {
+
+ List spans = new ArrayList<>();
+ Tracing brave = Tracing.newBuilder()
+ .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder()
+ .addScopeDecorator(StrictScopeDecorator.create())
+ .build())
+ .spanReporter(spans::add)
+ .build();
+ BraveTracer opentracing = BraveTracer.create(brave);
+
+ @After public void clear() {
+ brave.close();
+ }
+
+ @Test public void activate() {
+ BraveSpan span = opentracing.buildSpan("spanA").start();
+
+ try (Scope scopeA = opentracing.scopeManager().activate(span)) {
+ assertThat(opentracing.scopeManager().activeSpan().context().unwrap())
+ .isEqualTo(span.context().unwrap());
+ }
+
+ assertThat(opentracing.scopeManager().activeSpan())
+ .isNull();
+ }
+
+ /** This ensures downstream code using OpenTracing api can see Brave's scope */
+ @Test public void activeSpan_bridgesNormalBrave() {
+ ScopedSpan spanInScope = brave.tracer().startScopedSpan("spanA");
+ try {
+ assertThat(opentracing.scopeManager().activeSpan())
+ .extracting("delegate.context")
+ .containsExactly(spanInScope.context());
+ } finally {
+ spanInScope.finish();
+ }
+ }
+
+ @Test public void activate_nested() {
+ BraveSpan spanA = opentracing.buildSpan("spanA").start();
+ BraveSpan spanB = opentracing.buildSpan("spanB").start();
+
+ try (Scope scopeA = opentracing.scopeManager().activate(spanA)) {
+ try (Scope scopeB = opentracing.scopeManager().activate(spanB)) {
+ assertThat(opentracing.scopeManager().activeSpan().context().unwrap())
+ .isEqualTo(spanB.context().unwrap());
+ }
+
+ assertThat(opentracing.scopeManager().activeSpan().context().unwrap())
+ .isEqualTo(spanA.context().unwrap());
+ }
+ }
+}
diff --git a/src/test/java/brave/opentracing/BraveSpanBuilderTest.java b/src/test/java/brave/opentracing/OpenTracing0_33_BraveSpanBuilderTest.java
similarity index 92%
rename from src/test/java/brave/opentracing/BraveSpanBuilderTest.java
rename to src/test/java/brave/opentracing/OpenTracing0_33_BraveSpanBuilderTest.java
index 7bd45e0..cd0b0b4 100644
--- a/src/test/java/brave/opentracing/BraveSpanBuilderTest.java
+++ b/src/test/java/brave/opentracing/OpenTracing0_33_BraveSpanBuilderTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-2018 The OpenZipkin Authors
+ * Copyright 2016-2019 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
@@ -20,7 +20,7 @@
import static org.assertj.core.api.Java6Assertions.assertThat;
-public class BraveSpanBuilderTest {
+public class OpenTracing0_33_BraveSpanBuilderTest {
/** Ensures when the caller invokes with null, nothing happens */
@Test public void asChildOf_nullParentContext_noop() {
@@ -48,6 +48,6 @@ public class BraveSpanBuilderTest {
BraveSpanBuilder newSpanBuilder() {
// hijacking nullability as tracer isn't referenced until build, making easier comparisons
- return new BraveSpanBuilder(null, null, "foo");
+ return new BraveSpanBuilder(null, "foo");
}
}
diff --git a/src/test/java/brave/opentracing/BraveSpanTest.java b/src/test/java/brave/opentracing/OpenTracing0_33_BraveSpanTest.java
similarity index 68%
rename from src/test/java/brave/opentracing/BraveSpanTest.java
rename to src/test/java/brave/opentracing/OpenTracing0_33_BraveSpanTest.java
index 177bc26..70cf176 100644
--- a/src/test/java/brave/opentracing/BraveSpanTest.java
+++ b/src/test/java/brave/opentracing/OpenTracing0_33_BraveSpanTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-2018 The OpenZipkin Authors
+ * Copyright 2016-2019 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
@@ -18,67 +18,55 @@
import brave.propagation.ExtraFieldPropagation;
import brave.propagation.StrictScopeDecorator;
import brave.propagation.ThreadLocalCurrentTraceContext;
+import brave.sampler.Sampler;
import com.tngtech.java.junit.dataprovider.DataProvider;
import com.tngtech.java.junit.dataprovider.DataProviderRunner;
import com.tngtech.java.junit.dataprovider.UseDataProvider;
-import io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.SpanContext;
-import io.opentracing.propagation.Format;
-import io.opentracing.propagation.TextMapExtractAdapter;
-import io.opentracing.propagation.TextMapInjectAdapter;
+import io.opentracing.propagation.TextMapAdapter;
+import io.opentracing.tag.Tag;
import io.opentracing.tag.Tags;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.junit.After;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import zipkin2.Endpoint;
import zipkin2.Span.Kind;
+import static io.opentracing.propagation.Format.Builtin.TEXT_MAP;
import static io.opentracing.tag.Tags.SAMPLING_PRIORITY;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.entry;
@RunWith(DataProviderRunner.class)
-public class BraveSpanTest {
+public class OpenTracing0_33_BraveSpanTest {
List spans = new ArrayList<>();
- BraveTracer tracer = BraveTracer.create(
- Tracing.newBuilder()
- .localServiceName("tracer")
- .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder()
- .addScopeDecorator(StrictScopeDecorator.create())
- .build())
- .propagationFactory(ExtraFieldPropagation.newFactory(B3Propagation.FACTORY, "client-id"))
- .spanReporter(spans::add).build()
- );
-
- /** OpenTracing span implements auto-closeable, and implies reporting on close */
- @Test public void autoCloseOnTryFinally() {
- try (Scope scope = tracer.buildSpan("foo").startActive(true)) {
- }
+ Tracing brave;
+ BraveTracer tracer;
- assertThat(spans)
- .hasSize(1);
+ @Before public void init() {
+ init(Tracing.newBuilder());
}
- @Test public void autoCloseOnTryFinally_doesntReportTwice() {
- try (Scope scope = tracer.buildSpan("foo").startActive(true)) {
- scope.span().finish(); // user closes and also auto-close closes
- }
-
- assertThat(spans)
- .hasSize(1);
+ void init(Tracing.Builder tracingBuilder) {
+ if (brave != null) brave.close();
+ brave = tracingBuilder
+ .localServiceName("tracer")
+ .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder()
+ .addScopeDecorator(StrictScopeDecorator.create())
+ .build())
+ .propagationFactory(ExtraFieldPropagation.newFactory(B3Propagation.FACTORY, "client-id"))
+ .spanReporter(spans::add).build();
+ tracer = BraveTracer.create(brave);
}
- @Test public void autoCloseOnTryFinally_dontClose() {
- try (Scope scope = tracer.buildSpan("foo").startActive(false)) {
- }
-
- assertThat(spans)
- .isEmpty();
+ @After public void clear() {
+ brave.close();
}
@DataProvider
@@ -155,7 +143,7 @@ public void spanKind_afterStart(String tagValue, Kind kind) {
assertThat(spans)
.flatExtracting(s -> s.tags().entrySet())
- .containsExactly(entry("hello", "monster"));
+ .containsOnly(entry("hello", "monster"));
}
@Test public void afterFinish_dataIgnored() {
@@ -178,7 +166,7 @@ public void spanKind_afterStart(String tagValue, Kind kind) {
.start();
Map carrier = new LinkedHashMap<>();
- tracer.inject(spanClient.context(), Format.Builtin.TEXT_MAP, new TextMapInjectAdapter(carrier));
+ tracer.inject(spanClient.context(), TEXT_MAP, new TextMapAdapter(carrier));
BraveTracer tracer2 = BraveTracer.create(
Tracing.newBuilder()
@@ -186,8 +174,7 @@ public void spanKind_afterStart(String tagValue, Kind kind) {
.spanReporter(spans::add).build()
);
- SpanContext extractedContext =
- tracer2.extract(Format.Builtin.TEXT_MAP, new TextMapExtractAdapter(carrier));
+ SpanContext extractedContext = tracer2.extract(TEXT_MAP, new TextMapAdapter(carrier));
Span spanServer = tracer2.buildSpan("foo")
.asChildOf(extractedContext)
@@ -219,7 +206,7 @@ public void spanKind_afterStart(String tagValue, Kind kind) {
carrier.put("client-id", "aloha");
SpanContext extractedContext =
- tracer.extract(Format.Builtin.TEXT_MAP, new TextMapExtractAdapter(carrier));
+ tracer.extract(TEXT_MAP, new TextMapAdapter(carrier));
assertThat(extractedContext.baggageItems())
.contains(entry("client-id", "aloha"));
@@ -235,6 +222,20 @@ public void spanKind_afterStart(String tagValue, Kind kind) {
serverSpan.finish();
}
+ @Test public void samplingPriority_sampledWhenAtStart() {
+ init(Tracing.newBuilder().sampler(Sampler.NEVER_SAMPLE));
+
+ BraveSpan span = tracer.buildSpan("foo")
+ .withTag(SAMPLING_PRIORITY.getKey(), 1)
+ .start();
+
+ assertThat(span.context().unwrap().sampled())
+ .isTrue();
+
+ span.finish();
+ assertThat(spans).hasSize(1);
+ }
+
@Test public void samplingPriority_unsampledWhenAtStart() {
BraveSpan span = tracer.buildSpan("foo")
.withTag(SAMPLING_PRIORITY.getKey(), 0)
@@ -297,8 +298,76 @@ public void spanKind_afterStart(String tagValue, Kind kind) {
.port(8080).build());
}
- @After public void clear() {
- Tracing current = Tracing.current();
- if (current != null) current.close();
+ @Test public void withTag() {
+ tracer.buildSpan("encode")
+ .withTag(Tags.HTTP_METHOD.getKey(), "GET")
+ .withTag(Tags.ERROR.getKey(), true)
+ .withTag(Tags.HTTP_STATUS.getKey(), 404)
+ .start().finish();
+
+ assertContainsTags();
}
+
+ @Test public void withTag_object() {
+ tracer.buildSpan("encode")
+ .withTag(Tags.HTTP_METHOD, "GET")
+ .withTag(Tags.ERROR, true)
+ .withTag(Tags.HTTP_STATUS, 404)
+ .start().finish();
+
+ assertContainsTags();
+ }
+
+ @Test public void setTag() {
+ tracer.buildSpan("encode").start()
+ .setTag(Tags.HTTP_METHOD.getKey(), "GET")
+ .setTag(Tags.ERROR.getKey(), true)
+ .setTag(Tags.HTTP_STATUS.getKey(), 404)
+ .finish();
+
+ assertContainsTags();
+ }
+
+ @Test public void setTag_object() {
+ tracer.buildSpan("encode").start()
+ .setTag(Tags.HTTP_METHOD, "GET")
+ .setTag(Tags.ERROR, true)
+ .setTag(Tags.HTTP_STATUS, 404)
+ .finish();
+
+ assertContainsTags();
+ }
+
+ void assertContainsTags() {
+ assertThat(spans.get(0).tags())
+ .containsEntry("http.method", "GET")
+ .containsEntry("error", "true")
+ .containsEntry("http.status_code", "404");
+ }
+
+ Tag exceptionTag = new Tag() {
+ @Override public String getKey() {
+ return "exception";
+ }
+
+ @Override public void set(Span span, Exception value) {
+ span.setTag(getKey(), value.getClass().getSimpleName());
+ }
+ };
+
+ @Test public void setTag_custom() {
+ tracer.buildSpan("encode").start()
+ .setTag(exceptionTag, new RuntimeException("ice cream")).finish();
+
+ assertThat(spans.get(0).tags())
+ .containsEntry("exception", "RuntimeException");
+ }
+
+ /** There is no javadoc, but we were told only string, bool or number? */
+ @Test(expected = IllegalArgumentException.class)
+ public void withTag_custom_unsupported() {
+ tracer.buildSpan("encode")
+ .withTag(exceptionTag, new RuntimeException("ice cream"));
+ }
+
}
diff --git a/src/test/java/brave/opentracing/BraveTracerTest.java b/src/test/java/brave/opentracing/OpenTracing0_33_BraveTracerTest.java
similarity index 55%
rename from src/test/java/brave/opentracing/BraveTracerTest.java
rename to src/test/java/brave/opentracing/OpenTracing0_33_BraveTracerTest.java
index 5b15165..1b6661f 100644
--- a/src/test/java/brave/opentracing/BraveTracerTest.java
+++ b/src/test/java/brave/opentracing/OpenTracing0_33_BraveTracerTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-2018 The OpenZipkin Authors
+ * Copyright 2016-2019 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
@@ -22,11 +22,16 @@
import brave.propagation.StrictScopeDecorator;
import brave.propagation.ThreadLocalCurrentTraceContext;
import brave.propagation.TraceContext;
+import com.tngtech.java.junit.dataprovider.DataProvider;
+import com.tngtech.java.junit.dataprovider.DataProviderRunner;
+import com.tngtech.java.junit.dataprovider.UseDataProvider;
import io.opentracing.Scope;
+import io.opentracing.propagation.BinaryAdapters;
+import io.opentracing.propagation.BinaryInject;
import io.opentracing.propagation.Format;
import io.opentracing.propagation.TextMap;
-import io.opentracing.propagation.TextMapExtractAdapter;
-import io.opentracing.propagation.TextMapInjectAdapter;
+import io.opentracing.propagation.TextMapAdapter;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
@@ -34,9 +39,20 @@
import java.util.Map;
import org.junit.After;
import org.junit.Test;
+import org.junit.runner.RunWith;
import zipkin2.Annotation;
+import static io.opentracing.propagation.BinaryAdapters.extractionCarrier;
+import static io.opentracing.propagation.BinaryAdapters.injectionCarrier;
+import static io.opentracing.propagation.Format.Builtin.BINARY;
+import static io.opentracing.propagation.Format.Builtin.BINARY_EXTRACT;
+import static io.opentracing.propagation.Format.Builtin.BINARY_INJECT;
+import static io.opentracing.propagation.Format.Builtin.HTTP_HEADERS;
+import static io.opentracing.propagation.Format.Builtin.TEXT_MAP;
+import static io.opentracing.propagation.Format.Builtin.TEXT_MAP_EXTRACT;
+import static io.opentracing.propagation.Format.Builtin.TEXT_MAP_INJECT;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown;
import static org.assertj.core.data.MapEntry.entry;
import static org.junit.Assert.assertEquals;
@@ -44,7 +60,12 @@
* This shows how one might make an OpenTracing adapter for Brave, and how to navigate in and out of
* the core concepts.
*/
-public class BraveTracerTest {
+@RunWith(DataProviderRunner.class)
+public class OpenTracing0_33_BraveTracerTest {
+ TraceContext context = TraceContext.newBuilder()
+ .traceId(1L)
+ .spanId(2L)
+ .sampled(true).build();
List spans = new ArrayList<>();
Tracing brave = Tracing.newBuilder()
@@ -58,6 +79,15 @@ public class BraveTracerTest {
.build();
BraveTracer opentracing = BraveTracer.create(brave);
+ @After public void clear() {
+ brave.close();
+ }
+
+ @Test public void versionIsCorrect() {
+ assertThat(OpenTracingVersion.get())
+ .isInstanceOf(OpenTracingVersion.v0_32.class);
+ }
+
@Test public void startWithOpenTracingAndFinishWithBrave() {
io.opentracing.Span openTracingSpan = opentracing.buildSpan("encode")
.withTag("lc", "codec")
@@ -85,91 +115,91 @@ public class BraveTracerTest {
checkSpanReportedToZipkin();
}
- @Test public void extractTraceContext() throws Exception {
+ @DataProvider public static Object[] dataProviderExtractTextFormats() {
+ return new Object[] {HTTP_HEADERS, TEXT_MAP, TEXT_MAP_EXTRACT};
+ }
+
+ @Test @UseDataProvider("dataProviderExtractTextFormats")
+ public void extractTraceContext(Format format) {
Map map = new LinkedHashMap<>();
map.put("X-B3-TraceId", "0000000000000001");
map.put("X-B3-SpanId", "0000000000000002");
map.put("X-B3-Sampled", "1");
- BraveSpanContext openTracingContext =
- (BraveSpanContext) opentracing.extract(Format.Builtin.HTTP_HEADERS,
- new TextMapExtractAdapter(map));
-
- assertThat(openTracingContext.unwrap())
- .isEqualTo(TraceContext.newBuilder()
- .traceId(1L)
- .spanId(2L)
- .sampled(true).build());
+ assertExtractedContext(format, new TextMapAdapter(map));
}
- @Test public void extractBaggage() throws Exception {
+ @Test @UseDataProvider("dataProviderExtractTextFormats")
+ public void extractBaggage(Format format) {
Map map = new LinkedHashMap<>();
map.put("X-B3-TraceId", "0000000000000001");
map.put("X-B3-SpanId", "0000000000000002");
map.put("X-B3-Sampled", "1");
map.put("baggage-country-code", "FO");
- BraveSpanContext openTracingContext = opentracing.extract(Format.Builtin.HTTP_HEADERS,
- new TextMapExtractAdapter(map));
+ BraveSpanContext otContext = opentracing.extract(format, new TextMapAdapter(map));
- assertThat(openTracingContext.baggageItems())
+ assertThat(otContext.baggageItems())
.containsExactly(entry("country-code", "FO"));
}
- @Test public void extractTraceContextTextMap() throws Exception {
+ @Test @UseDataProvider("dataProviderExtractTextFormats")
+ public void extractOnlyBaggage(Format format) {
+ Map map = new LinkedHashMap<>();
+ map.put("baggage-country-code", "FO");
+
+ BraveSpanContext otContext = opentracing.extract(format, new TextMapAdapter(map));
+
+ assertThat(otContext.toTraceId()).isNull();
+ assertThat(otContext.toSpanId()).isNull();
+ assertThat(otContext.unwrap()).isNull();
+ assertThat(otContext.baggageItems())
+ .containsExactly(entry("country-code", "FO"));
+ }
+
+ @Test @UseDataProvider("dataProviderExtractTextFormats")
+ public void extractOnlySampled(Format format) {
Map map = new LinkedHashMap<>();
- map.put("X-B3-TraceId", "0000000000000001");
- map.put("X-B3-SpanId", "0000000000000002");
map.put("X-B3-Sampled", "1");
- BraveSpanContext openTracingContext =
- (BraveSpanContext) opentracing.extract(Format.Builtin.TEXT_MAP,
- new TextMapExtractAdapter(map));
+ BraveSpanContext otContext = opentracing.extract(format, new TextMapAdapter(map));
- assertThat(openTracingContext.unwrap())
- .isEqualTo(TraceContext.newBuilder()
- .traceId(1L)
- .spanId(2L)
- .sampled(true).build());
+ assertThat(otContext.toTraceId()).isNull();
+ assertThat(otContext.toSpanId()).isNull();
+ assertThat(otContext.unwrap()).isNull();
}
- @Test public void extractTraceContextCaseInsensitive() throws Exception {
+ @Test @UseDataProvider("dataProviderExtractTextFormats")
+ public void extractTraceContextCaseInsensitive(Format format) {
Map map = new LinkedHashMap<>();
map.put("X-B3-TraceId", "0000000000000001");
map.put("x-b3-spanid", "0000000000000002");
map.put("x-b3-SaMpLeD", "1");
map.put("other", "1");
- BraveSpanContext openTracingContext =
- (BraveSpanContext) opentracing.extract(Format.Builtin.HTTP_HEADERS,
- new TextMapExtractAdapter(map));
-
- assertThat(openTracingContext.unwrap())
- .isEqualTo(TraceContext.newBuilder()
- .traceId(1L)
- .spanId(2L)
- .sampled(true).build());
+ assertExtractedContext(format, new TextMapAdapter(map));
}
- @Test public void extractTraceContext_unwrapReturnsNull() throws Exception {
- Map map = new LinkedHashMap<>();
- map.put("other", "1");
-
- BraveSpanContext openTracingContext = opentracing.extract(Format.Builtin.HTTP_HEADERS,
- new TextMapExtractAdapter(map));
+ void assertExtractedContext(Format format, C carrier) {
+ BraveSpanContext otContext = opentracing.extract(format, carrier);
- assertThat(openTracingContext.unwrap()).isNull();
+ assertThat(otContext.toTraceId())
+ .isEqualTo(otContext.unwrap().traceIdString());
+ assertThat(otContext.toSpanId())
+ .isEqualTo(otContext.unwrap().spanIdString());
+ assertThat(otContext.unwrap())
+ .isEqualTo(TraceContext.newBuilder().traceId(1L).spanId(2L).sampled(true).build());
}
- @Test public void injectTraceContext() throws Exception {
- TraceContext context = TraceContext.newBuilder()
- .traceId(1L)
- .spanId(2L)
- .sampled(true).build();
+ @DataProvider public static Object[] dataProviderInjectTextFormats() {
+ return new Object[] {HTTP_HEADERS, TEXT_MAP, TEXT_MAP_INJECT};
+ }
+ @Test @UseDataProvider("dataProviderInjectTextFormats")
+ public void injectTraceContext(Format format) {
Map map = new LinkedHashMap<>();
- TextMapInjectAdapter carrier = new TextMapInjectAdapter(map);
- opentracing.inject(BraveSpanContext.create(context), Format.Builtin.HTTP_HEADERS, carrier);
+ TextMapAdapter carrier = new TextMapAdapter(map);
+ opentracing.inject(BraveSpanContext.create(context), format, carrier);
assertThat(map).containsExactly(
entry("X-B3-TraceId", "0000000000000001"),
@@ -178,54 +208,61 @@ public class BraveTracerTest {
);
}
- @Test public void injectTraceContext_baggage() throws Exception {
+ @Test @UseDataProvider("dataProviderInjectTextFormats")
+ public void injectTraceContext_baggage(Format format) {
BraveSpan span = opentracing.buildSpan("foo").start();
span.setBaggageItem("country-code", "FO");
Map map = new LinkedHashMap<>();
- TextMapInjectAdapter carrier = new TextMapInjectAdapter(map);
- opentracing.inject(span.context(), Format.Builtin.HTTP_HEADERS, carrier);
+ TextMapAdapter carrier = new TextMapAdapter(map);
+ opentracing.inject(span.context(), format, carrier);
assertThat(map).containsEntry("baggage-country-code", "FO");
}
- @Test public void injectTraceContextTextMap() throws Exception {
- TraceContext context = TraceContext.newBuilder()
- .traceId(1L)
- .spanId(2L)
- .sampled(true).build();
-
+ @Test public void unsupportedFormat() {
Map map = new LinkedHashMap<>();
- TextMapInjectAdapter carrier = new TextMapInjectAdapter(map);
- opentracing.inject(BraveSpanContext.create(context), Format.Builtin.TEXT_MAP, carrier);
+ TextMapAdapter carrier = new TextMapAdapter(map);
+ Format B3 = new Format() {
+ };
- assertThat(map).containsExactly(
- entry("X-B3-TraceId", "0000000000000001"),
- entry("X-B3-SpanId", "0000000000000002"),
- entry("X-B3-Sampled", "1")
- );
+ try {
+ opentracing.inject(BraveSpanContext.create(context), B3, carrier);
+ failBecauseExceptionWasNotThrown(UnsupportedOperationException.class);
+ } catch (UnsupportedOperationException e) {
+ }
+
+ try {
+ opentracing.extract(B3, carrier);
+ failBecauseExceptionWasNotThrown(UnsupportedOperationException.class);
+ } catch (UnsupportedOperationException e) {
+ }
}
- @Test public void canUseCustomFormatKeys() throws Exception {
+ @Test public void canUseCustomFormatKeys() {
+ Map map = new LinkedHashMap<>();
+ TextMapAdapter carrier = new TextMapAdapter(map);
Format B3 = new Format() {
};
- opentracing = BraveTracer.newBuilder(brave)
- .textMapPropagation(B3, Propagation.B3_STRING).build();
- TraceContext context = TraceContext.newBuilder()
- .traceId(1L)
- .spanId(2L)
- .sampled(true).build();
+ opentracing = BraveTracer.newBuilder(brave)
+ .textMapPropagation(B3, Propagation.B3_SINGLE_STRING).build();
- Map map = new LinkedHashMap<>();
- TextMapInjectAdapter carrier = new TextMapInjectAdapter(map);
opentracing.inject(BraveSpanContext.create(context), B3, carrier);
- assertThat(map).containsExactly(
- entry("X-B3-TraceId", "0000000000000001"),
- entry("X-B3-SpanId", "0000000000000002"),
- entry("X-B3-Sampled", "1")
- );
+ assertThat(map).containsEntry("b3", "0000000000000001-0000000000000002-1");
+
+ assertExtractedContext(B3, new TextMapAdapter(map));
+ }
+
+ @Test public void binaryFormat() {
+ ByteBuffer buffer = ByteBuffer.allocate(128);
+
+ opentracing.inject(BraveSpanContext.create(context), BINARY_INJECT, injectionCarrier(buffer));
+ buffer.rewind();
+
+ assertThat(opentracing.extract(BINARY_EXTRACT, extractionCarrier(buffer)).unwrap())
+ .isEqualTo(context);
}
void checkSpanReportedToZipkin() {
@@ -252,16 +289,21 @@ void checkSpanReportedToZipkin() {
Long parentIdOfSpanB;
Long parentIdOfSpanC;
- try (Scope scopeA = opentracing.buildSpan("spanA").startActive(false)) {
- idOfSpanA = getTraceContext(scopeA).spanId();
- try (Scope scopeB = opentracing.buildSpan("spanB").startActive(false)) {
- idOfSpanB = getTraceContext(scopeB).spanId();
- parentIdOfSpanB = getTraceContext(scopeB).parentId();
- shouldBeIdOfSpanB = getTraceContext(opentracing.scopeManager().active()).spanId();
+ BraveSpan spanA = opentracing.buildSpan("spanA").start();
+ try (Scope scopeA = opentracing.activateSpan(spanA)) {
+ idOfSpanA = brave.currentTraceContext().get().spanId();
+
+ BraveSpan spanB = opentracing.buildSpan("spanB").start();
+ try (Scope scopeB = opentracing.activateSpan(spanB)) {
+ idOfSpanB = brave.currentTraceContext().get().spanId();
+ parentIdOfSpanB = brave.currentTraceContext().get().parentId();
+ shouldBeIdOfSpanB = brave.currentTraceContext().get().spanId();
}
- shouldBeIdOfSpanA = getTraceContext(opentracing.scopeManager().active()).spanId();
- try (Scope scopeC = opentracing.buildSpan("spanC").startActive(false)) {
- parentIdOfSpanC = getTraceContext(scopeC).parentId();
+ shouldBeIdOfSpanA = brave.currentTraceContext().get().spanId();
+
+ BraveSpan spanC = opentracing.buildSpan("spanC").start();
+ try (Scope scopeC = opentracing.activateSpan(spanC)) {
+ parentIdOfSpanC = brave.currentTraceContext().get().parentId();
}
}
@@ -317,35 +359,26 @@ void checkSpanReportedToZipkin() {
assertEquals("SpanC's parent should be SpanA", idOfSpanA, parentIdOfSpanC);
}
- @Test public void implicitParentFromSpanManager_startActive() {
- try (Scope scopeA = opentracing.buildSpan("spanA").startActive(true)) {
- try (Scope scopeB = opentracing.buildSpan("spanA").startActive(true)) {
- assertThat(getTraceContext(scopeB).parentId())
- .isEqualTo(getTraceContext(scopeA).spanId());
- }
+ @Test public void activeSpan() {
+ BraveSpan spanA = opentracing.buildSpan("spanA").start();
+ try (Scope scopeA = opentracing.activateSpan(spanA)) {
+ assertThat(opentracing.activeSpan())
+ .isEqualToComparingFieldByField(opentracing.scopeManager().activeSpan());
}
}
@Test public void implicitParentFromSpanManager_start() {
- try (Scope scopeA = opentracing.buildSpan("spanA").startActive(true)) {
+ BraveSpan spanA = opentracing.buildSpan("spanA").start();
+ try (Scope scopeA = opentracing.activateSpan(spanA)) {
BraveSpan span = opentracing.buildSpan("spanB").start();
assertThat(span.unwrap().context().parentId())
- .isEqualTo(getTraceContext(scopeA).spanId());
- }
- }
-
- @Test public void implicitParentFromSpanManager_startActive_ignoreActiveSpan() {
- try (Scope scopeA = opentracing.buildSpan("spanA").startActive(true)) {
- try (Scope scopeB = opentracing.buildSpan("spanA")
- .ignoreActiveSpan().startActive(true)) {
- assertThat(getTraceContext(scopeB).parentId())
- .isNull(); // new trace
- }
+ .isEqualTo(brave.currentTraceContext().get().spanId());
}
}
@Test public void implicitParentFromSpanManager_start_ignoreActiveSpan() {
- try (Scope scopeA = opentracing.buildSpan("spanA").startActive(true)) {
+ BraveSpan spanA = opentracing.buildSpan("spanA").start();
+ try (Scope scopeA = opentracing.activateSpan(spanA)) {
BraveSpan span = opentracing.buildSpan("spanB")
.ignoreActiveSpan().start();
assertThat(span.unwrap().context().parentId())
@@ -371,13 +404,4 @@ void checkSpanReportedToZipkin() {
assertThat(spans.get(0).tags())
.isEmpty();
}
-
- private static TraceContext getTraceContext(Scope scope) {
- return ((BraveSpanContext) scope.span().context()).unwrap();
- }
-
- @After public void clear() {
- Tracing current = Tracing.current();
- if (current != null) current.close();
- }
}
diff --git a/src/test/java/brave/opentracing/TextMapSetterTest.java b/src/test/java/brave/opentracing/TextMapSetterTest.java
index f9bd8c7..102cece 100644
--- a/src/test/java/brave/opentracing/TextMapSetterTest.java
+++ b/src/test/java/brave/opentracing/TextMapSetterTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-2018 The OpenZipkin Authors
+ * Copyright 2016-2019 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
@@ -16,14 +16,14 @@
import brave.propagation.Propagation;
import brave.test.propagation.PropagationSetterTest;
import io.opentracing.propagation.TextMap;
-import io.opentracing.propagation.TextMapInjectAdapter;
+import io.opentracing.propagation.TextMapAdapter;
import java.util.Collections;
import java.util.LinkedHashMap;
/** Verifies the method reference {@link TextMap#put} works as a Brave propagation setter */
public class TextMapSetterTest extends PropagationSetterTest {
LinkedHashMap delegate = new LinkedHashMap<>();
- TextMap carrier = new TextMapInjectAdapter(delegate);
+ TextMap carrier = new TextMapAdapter(delegate);
@Override public Propagation.KeyFactory keyFactory() {
return Propagation.KeyFactory.STRING;