diff --git a/opentracing-api/src/main/java/io/opentracing/ActiveSpan.java b/opentracing-api/src/main/java/io/opentracing/ActiveSpan.java
deleted file mode 100644
index 46e09d08..00000000
--- a/opentracing-api/src/main/java/io/opentracing/ActiveSpan.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright 2016-2017 The OpenTracing 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 io.opentracing;
-
-import java.io.Closeable;
-
-/**
- * {@link ActiveSpan} inherits all of the OpenTracing functionality in {@link BaseSpan} and layers on in-process
- * propagation capabilities.
- *
- *
- * In any given thread there is at most one {@link ActiveSpan "active" span} primarily responsible for the work
- * accomplished by the surrounding application code. That {@link ActiveSpan} may be accessed via the
- * {@link ActiveSpanSource#activeSpan()} method. If the application needs to defer work that should be part of
- * the same Span, the Source provides a {@link ActiveSpan#capture} method that returns a {@link Continuation};
- * this continuation may be used to re-activate and continue the {@link Span} in that other asynchronous executor
- * and/or thread.
- *
- *
- * {@link ActiveSpan}s are created via {@link Tracer.SpanBuilder#startActive()} or, less commonly,
- * {@link ActiveSpanSource#makeActive}. Per the above, they can be {@link ActiveSpan#capture()}ed as
- * {@link ActiveSpan.Continuation}s, then re-{@link Continuation#activate()}d later.
- *
- *
- * NOTE: {@link ActiveSpan} extends {@link Closeable} rather than {@code AutoCloseable} in order to preserve support
- * for JDK1.6.
- *
- * @see Tracer.SpanBuilder#startActive()
- * @see Continuation#activate()
- * @see ActiveSpanSource
- * @see BaseSpan
- * @see Span
- */
-public interface ActiveSpan extends Closeable, BaseSpan {
- /**
- * Mark the end of the active period for the current thread and {@link ActiveSpan}. When the last
- * {@link ActiveSpan} is deactivated for a given {@link Span}, it is automatically {@link Span#finish()}ed.
- *
- *
- * NOTE: Calling {@link #deactivate} more than once on a single {@link ActiveSpan} instance leads to undefined
- * behavior.
- *
- * @see Closeable#close() {@link ActiveSpan}s are auto-closeable and may be used in try-with-resources blocks
- */
- void deactivate();
-
- /**
- * A synonym for {@link #deactivate()} that can be used in try-with-resources blocks.
- */
- @Override
- void close();
-
- /**
- * "Capture" a new {@link Continuation} associated with this {@link ActiveSpan} and {@link Span}, as well as any
- * 3rd-party execution context of interest. The {@link Continuation} may be used as data in a closure or callback
- * function where the {@link ActiveSpan} may be resumed and reactivated.
- *
- *
- * IMPORTANT: the caller MUST {@link Continuation#activate()} and {@link ActiveSpan#deactivate()} the
- * returned {@link Continuation} or the associated {@link Span} will never automatically {@link Span#finish()}.
- * That is, calling {@link #capture()} increments a refcount that must be decremented somewhere else.
- *
- *
- * The associated {@link Span} will not {@link Span#finish()} while a {@link Continuation} is outstanding; in
- * this way, it provides a reference/pin just like an {@link ActiveSpan} does.
- *
- * @return a new {@link Continuation} to {@link Continuation#activate()} at the appropriate time.
- */
- Continuation capture();
-
- /**
- * A {@link Continuation} can be used once to activate a Span along with any non-OpenTracing execution
- * context (e.g., MDC), then deactivate when processing activity moves on to another Span. (In practice, this
- * active period typically extends for the length of a deferred async closure invocation.)
- *
- *
- * Most users do not directly interact with {@link Continuation}, {@link Continuation#activate()} or
- * {@link ActiveSpan#deactivate()}, but rather use {@link ActiveSpanSource}-aware Runnables/Callables/Executors.
- * Those higher-level primitives do not need to be defined within the OpenTracing core API, and so
- * they are not.
- *
- * @see ActiveSpanSource#makeActive(Span)
- */
- interface Continuation {
- /**
- * Make the Span (and other execution context) encapsulated by this {@link Continuation} active and
- * return it.
- *
- *
- * NOTE: It is an error to call activate() more than once on a single Continuation instance.
- *
- * @see ActiveSpanSource#makeActive(Span)
- * @return a handle to the newly-activated {@link ActiveSpan}
- */
- ActiveSpan activate();
- }
-
-}
diff --git a/opentracing-api/src/main/java/io/opentracing/ActiveSpanSource.java b/opentracing-api/src/main/java/io/opentracing/ActiveSpanSource.java
deleted file mode 100644
index 334d00e8..00000000
--- a/opentracing-api/src/main/java/io/opentracing/ActiveSpanSource.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2016-2017 The OpenTracing 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 io.opentracing;
-
-/**
- * {@link ActiveSpanSource} allows an existing (possibly thread-local-aware) execution context provider to act as a
- * source for an actively-scheduled OpenTracing Span.
- *
- *
- * {@link ActiveSpanSource} is a super-interface to {@link Tracer}, so note that all {@link Tracer}s fulfill the
- * {@link ActiveSpanSource} contract.
- *
- * @see ActiveSpan
- */
-public interface ActiveSpanSource {
-
- /**
- * Return the {@link ActiveSpan active span}. This does not affect the internal reference count for the
- * {@link ActiveSpan}.
- *
- *
- * If there is an {@link ActiveSpan active span}, it becomes an implicit parent of any newly-created
- * {@link BaseSpan span} at {@link Tracer.SpanBuilder#startActive()} time (rather than at
- * {@link Tracer#buildSpan(String)} time).
- *
- * @return the {@link ActiveSpan active span}, or null if none could be found.
- */
- ActiveSpan activeSpan();
-
- /**
- * Wrap and "make active" a {@link Span} by encapsulating it – and any active state (e.g., MDC state) in the
- * current thread – in a new {@link ActiveSpan}.
- *
- * @param span the Span to wrap in an {@link ActiveSpan}
- * @return an {@link ActiveSpan} that encapsulates the given {@link Span} and any other
- * {@link ActiveSpanSource}-specific context (e.g., the MDC context map)
- */
- ActiveSpan makeActive(Span span);
-}
diff --git a/opentracing-api/src/main/java/io/opentracing/BaseSpan.java b/opentracing-api/src/main/java/io/opentracing/BaseSpan.java
deleted file mode 100644
index b83bc190..00000000
--- a/opentracing-api/src/main/java/io/opentracing/BaseSpan.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright 2016-2017 The OpenTracing 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 io.opentracing;
-
-import java.util.Map;
-
-/**
- * {@link BaseSpan} represents the OpenTracing specification's span contract with the exception of methods to finish
- * said span. For those, either use {@link Span#finish()} or {@link ActiveSpan#deactivate()} depending on the
- * programming model.
- *
- * @see Span
- * @see ActiveSpan
- * @see Tracer.SpanBuilder#startManual()
- * @see Tracer.SpanBuilder#startActive()
- */
-public interface BaseSpan {
- /**
- * Retrieve the associated SpanContext.
- *
- * This may be called at any time, including after calls to finish().
- *
- * @return the SpanContext that encapsulates Span state that should propagate across process boundaries.
- */
- SpanContext context();
-
- /**
- * Set a key:value tag on the Span.
- */
- S setTag(String key, String value);
-
- /** Same as {@link #setTag(String, String)}, but for boolean values. */
- S setTag(String key, boolean value);
-
- /** Same as {@link #setTag(String, String)}, but for numeric values. */
- S setTag(String key, Number value);
-
- /**
- * Log key:value pairs to the Span with the current walltime timestamp.
- *
- *
CAUTIONARY NOTE: not all Tracer implementations support key:value log fields end-to-end.
- * Caveat emptor.
- *
- *
A contrived example (using Guava, which is not required):
- *
- *
- * @param fields key:value log fields. Tracer implementations should support String, numeric, and boolean values;
- * some may also support arbitrary Objects.
- * @return the Span, for chaining
- * @see Span#log(String)
- */
- S log(Map fields);
-
- /**
- * Like log(Map<String, Object>), but with an explicit timestamp.
- *
- *
CAUTIONARY NOTE: not all Tracer implementations support key:value log fields end-to-end.
- * Caveat emptor.
- *
- * @param timestampMicroseconds The explicit timestamp for the log record. Must be greater than or equal to the
- * Span's start timestamp.
- * @param fields key:value log fields. Tracer implementations should support String, numeric, and boolean values;
- * some may also support arbitrary Objects.
- * @return the Span, for chaining
- * @see Span#log(long, String)
- */
- S log(long timestampMicroseconds, Map fields);
-
- /**
- * Record an event at the current walltime timestamp.
- *
- * Shorthand for
- *
- *
- *
- * @param event the event value; often a stable identifier for a moment in the Span lifecycle
- * @return the Span, for chaining
- */
- S log(String event);
-
- /**
- * Record an event at a specific timestamp.
- *
- * Shorthand for
- *
- *
- *
- * @param timestampMicroseconds The explicit timestamp for the log record. Must be greater than or equal to the
- * Span's start timestamp.
- * @param event the event value; often a stable identifier for a moment in the Span lifecycle
- * @return the Span, for chaining
- */
- S log(long timestampMicroseconds, String event);
-
- /**
- * Sets a baggage item in the Span (and its SpanContext) as a key/value pair.
- *
- * Baggage enables powerful distributed context propagation functionality where arbitrary application data can be
- * carried along the full path of request execution throughout the system.
- *
- * Note 1: Baggage is only propagated to the future (recursive) children of this SpanContext.
- *
- * Note 2: Baggage is sent in-band with every subsequent local and remote calls, so this feature must be used with
- * care.
- *
- * @return this Span instance, for chaining
- */
- S setBaggageItem(String key, String value);
-
- /**
- * @return the value of the baggage item identified by the given key, or null if no such item could be found
- */
- String getBaggageItem(String key);
-
- /**
- * Sets the string name for the logical operation this span represents.
- *
- * @return this Span instance, for chaining
- */
- S setOperationName(String operationName);
-}
diff --git a/opentracing-api/src/main/java/io/opentracing/Scope.java b/opentracing-api/src/main/java/io/opentracing/Scope.java
new file mode 100644
index 00000000..dd997647
--- /dev/null
+++ b/opentracing-api/src/main/java/io/opentracing/Scope.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2016-2017 The OpenTracing 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 io.opentracing;
+
+import java.io.Closeable;
+
+/**
+ * A {@link Scope} formalizes the activation and deactivation of a {@link Span}, usually from a CPU standpoint.
+ *
+ *
+ * Many times a {@link Span} will be extant (in that {@link Span#finish()} has not been called) despite being in a
+ * non-runnable state from a CPU/scheduler standpoint. For instance, a {@link Span} representing the client side of an
+ * RPC will be unfinished but blocked on IO while the RPC is still outstanding. A {@link Scope} defines when a given
+ * {@link Span} is scheduled and on the path.
+ */
+public interface Scope extends Closeable {
+ /**
+ * Mark the end of the active period for the current thread and {@link Scope},
+ * updating the {@link ScopeManager#active()} in the process.
+ *
+ *
+ * NOTE: Calling {@link #close} more than once on a single {@link Scope} instance leads to undefined
+ * behavior.
+ */
+ @Override
+ void close();
+
+ /**
+ * @return the {@link Span} that's been scoped by this {@link Scope}
+ */
+ Span span();
+}
diff --git a/opentracing-api/src/main/java/io/opentracing/ScopeManager.java b/opentracing-api/src/main/java/io/opentracing/ScopeManager.java
new file mode 100644
index 00000000..b37f634f
--- /dev/null
+++ b/opentracing-api/src/main/java/io/opentracing/ScopeManager.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2016-2017 The OpenTracing 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 io.opentracing;
+
+/**
+ * The {@link ScopeManager} interface abstracts both the activation of {@link Span} instances (via
+ * {@link ScopeManager#activate(Span)}) and access to an active {@link Span}/{@link Scope}
+ * (via {@link ScopeManager#active()}).
+ *
+ * @see Scope
+ * @see Tracer#scopeManager()
+ */
+public interface ScopeManager {
+ /**
+ * Make a {@link Span} instance active.
+ *
+ * @param span the {@link Span} that should become the {@link #active()}
+ * @return a {@link Scope} instance to control the end of the active period for the {@link Span}. It is a
+ * programming error to neglect to call {@link Scope#close()} on the returned instance.
+ */
+ Scope activate(Span span);
+ Scope activate(Span span, boolean finishOnClose);
+
+ /**
+ * Return the currently active {@link Scope} which can be used to access the currently active
+ * {@link Scope#span()}.
+ *
+ *
+ * If there is an {@link Scope non-null scope}, its wrapped {@link Span} becomes an implicit parent of any
+ * newly-created {@link Span} at {@link Tracer.SpanBuilder#startActive()} time (rather than at
+ * {@link Tracer#buildSpan(String)} time).
+ *
+ * @return the {@link Scope active scope}, or null if none could be found.
+ */
+ Scope active();
+}
diff --git a/opentracing-api/src/main/java/io/opentracing/Span.java b/opentracing-api/src/main/java/io/opentracing/Span.java
index 026c4ce5..548ac4f8 100644
--- a/opentracing-api/src/main/java/io/opentracing/Span.java
+++ b/opentracing-api/src/main/java/io/opentracing/Span.java
@@ -13,16 +13,132 @@
*/
package io.opentracing;
+import java.util.Map;
+
/**
- * Represents an in-flight Span that's manually propagated within the given process. Most of
- * the API lives in {@link BaseSpan}.
- *
- *
{@link Span}s are created by the {@link Tracer.SpanBuilder#startManual} method; see {@link ActiveSpan} for
- * a {@link BaseSpan} extension designed for automatic in-process propagation.
+ * {@link Span} represents the OpenTracing specification's Span contract.
*
- * @see ActiveSpan for automatic propagation (recommended for most intstrumentation!)
+ * @see Scope
+ * @see ScopeManager
+ * @see Tracer.SpanBuilder#startManual()
+ * @see Tracer.SpanBuilder#startActive()
*/
-public interface Span extends BaseSpan {
+public interface Span {
+ /**
+ * Retrieve the associated SpanContext.
+ *
+ * This may be called at any time, including after calls to finish().
+ *
+ * @return the SpanContext that encapsulates Span state that should propagate across process boundaries.
+ */
+ SpanContext context();
+
+ /**
+ * Set a key:value tag on the Span.
+ */
+ Span setTag(String key, String value);
+
+ /** Same as {@link #setTag(String, String)}, but for boolean values. */
+ Span setTag(String key, boolean value);
+
+ /** Same as {@link #setTag(String, String)}, but for numeric values. */
+ Span setTag(String key, Number value);
+
+ /**
+ * Log key:value pairs to the Span with the current walltime timestamp.
+ *
+ *
CAUTIONARY NOTE: not all Tracer implementations support key:value log fields end-to-end.
+ * Caveat emptor.
+ *
+ *
A contrived example (using Guava, which is not required):
+ *
+ *
+ * @param fields key:value log fields. Tracer implementations should support String, numeric, and boolean values;
+ * some may also support arbitrary Objects.
+ * @return the Span, for chaining
+ * @see Span#log(String)
+ */
+ Span log(Map fields);
+
+ /**
+ * Like log(Map<String, Object>), but with an explicit timestamp.
+ *
+ *
CAUTIONARY NOTE: not all Tracer implementations support key:value log fields end-to-end.
+ * Caveat emptor.
+ *
+ * @param timestampMicroseconds The explicit timestamp for the log record. Must be greater than or equal to the
+ * Span's start timestamp.
+ * @param fields key:value log fields. Tracer implementations should support String, numeric, and boolean values;
+ * some may also support arbitrary Objects.
+ * @return the Span, for chaining
+ * @see Span#log(long, String)
+ */
+ Span log(long timestampMicroseconds, Map fields);
+
+ /**
+ * Record an event at the current walltime timestamp.
+ *
+ * Shorthand for
+ *
+ *
+ *
+ * @param event the event value; often a stable identifier for a moment in the Span lifecycle
+ * @return the Span, for chaining
+ */
+ Span log(String event);
+
+ /**
+ * Record an event at a specific timestamp.
+ *
+ * Shorthand for
+ *
+ *
+ *
+ * @param timestampMicroseconds The explicit timestamp for the log record. Must be greater than or equal to the
+ * Span's start timestamp.
+ * @param event the event value; often a stable identifier for a moment in the Span lifecycle
+ * @return the Span, for chaining
+ */
+ Span log(long timestampMicroseconds, String event);
+
+ /**
+ * Sets a baggage item in the Span (and its SpanContext) as a key/value pair.
+ *
+ * Baggage enables powerful distributed context propagation functionality where arbitrary application data can be
+ * carried along the full path of request execution throughout the system.
+ *
+ * Note 1: Baggage is only propagated to the future (recursive) children of this SpanContext.
+ *
+ * Note 2: Baggage is sent in-band with every subsequent local and remote calls, so this feature must be used with
+ * care.
+ *
+ * @return this Span instance, for chaining
+ */
+ Span setBaggageItem(String key, String value);
+
+ /**
+ * @return the value of the baggage item identified by the given key, or null if no such item could be found
+ */
+ String getBaggageItem(String key);
+
+ /**
+ * Sets the string name for the logical operation this span represents.
+ *
+ * @return this Span instance, for chaining
+ */
+ Span setOperationName(String operationName);
+
/**
* Sets the end timestamp to now and records the span.
*
diff --git a/opentracing-api/src/main/java/io/opentracing/Tracer.java b/opentracing-api/src/main/java/io/opentracing/Tracer.java
index 25d3d321..ab6da828 100644
--- a/opentracing-api/src/main/java/io/opentracing/Tracer.java
+++ b/opentracing-api/src/main/java/io/opentracing/Tracer.java
@@ -18,7 +18,12 @@
/**
* Tracer is a simple, thin interface for Span creation and propagation across arbitrary transports.
*/
-public interface Tracer extends ActiveSpanSource {
+public interface Tracer {
+
+ /**
+ * @return the current {@link ScopeManager}, which may be a noop but may not be null.
+ */
+ ScopeManager scopeManager();
/**
* Return a new SpanBuilder for a Span with the given `operationName`.
@@ -29,14 +34,14 @@ public interface Tracer extends ActiveSpanSource {
*
* Tracer tracer = ...
*
- * // Note: if there is a `tracer.activeSpan()`, it will be used as the target of an implicit CHILD_OF
- * // Reference for "workSpan" when `startActive()` is invoked.
- * try (ActiveSpan workSpan = tracer.buildSpan("DoWork").startActive()) {
- * workSpan.setTag("...", "...");
+ * // Note: if there is a `tracer.active()` Scope, its `span()` will be used as the target
+ * // of an implicit CHILD_OF Reference for "workScope.span()" when `startActive()` is invoked.
+ * try (Scope workScope = tracer.buildSpan("DoWork").startActive()) {
+ * workScope.span().setTag("...", "...");
* // etc, etc
* }
*
- * // It's also possible to create Spans manually, bypassing the ActiveSpanSource activation.
+ * // It's also possible to create Spans manually, bypassing the ScopeManager activation.
* Span http = tracer.buildSpan("HandleHTTPRequest")
* .asChildOf(rpcSpanContext) // an explicit parent
* .withTag("user_agent", req.UserAgent)
@@ -111,7 +116,7 @@ interface SpanBuilder {
*
* If parent==null, this is a noop.
*/
- SpanBuilder asChildOf(BaseSpan> parent);
+ SpanBuilder asChildOf(Span parent);
/**
* Add a reference from the Span being built to a distinct (usually parent) Span. May be called multiple times
@@ -120,12 +125,12 @@ interface SpanBuilder {
*
* If
*
- *
the {@link Tracer}'s {@link ActiveSpanSource#activeSpan()} is not null, and
+ *
the {@link Tracer}'s {@link ScopeManager#active()} is not null, and
*
no explicit references are added via {@link SpanBuilder#addReference}, and
*
{@link SpanBuilder#ignoreActiveSpan()} is not invoked,
*
* ... then an inferred {@link References#CHILD_OF} reference is created to the
- * {@link ActiveSpanSource#activeSpan()} {@link SpanContext} when either {@link SpanBuilder#startActive()} or
+ * {@link ScopeManager#active()} {@link SpanContext} when either {@link SpanBuilder#startActive()} or
* {@link SpanBuilder#startManual} is invoked.
*
* @param referenceType the reference type, typically one of the constants defined in References
@@ -138,7 +143,7 @@ interface SpanBuilder {
SpanBuilder addReference(String referenceType, SpanContext referencedContext);
/**
- * Do not create an implicit {@link References#CHILD_OF} reference to the {@link ActiveSpanSource#activeSpan}).
+ * Do not create an implicit {@link References#CHILD_OF} reference to the {@link ScopeManager#active()}).
*/
SpanBuilder ignoreActiveSpan();
@@ -155,46 +160,47 @@ interface SpanBuilder {
SpanBuilder withStartTimestamp(long microseconds);
/**
- * Returns a newly started and activated {@link ActiveSpan}.
+ * Returns a newly started and activated {@link Scope}.
*
*
- * The returned {@link ActiveSpan} supports try-with-resources. For example:
+ * The returned {@link Scope} supports try-with-resources. For example:
*
the {@link Tracer}'s {@link ActiveSpanSource#activeSpan()} is not null, and
+ *
the {@link Tracer}'s {@link ScopeManager#active()} is not null, and
*
no explicit references are added via {@link SpanBuilder#addReference}, and
*
{@link SpanBuilder#ignoreActiveSpan()} is not invoked,
*
* ... then an inferred {@link References#CHILD_OF} reference is created to the
- * {@link ActiveSpanSource#activeSpan()}'s {@link SpanContext} when either
+ * {@link ScopeManager#active()}'s {@link SpanContext} when either
* {@link SpanBuilder#startManual()} or {@link SpanBuilder#startActive} is invoked.
*
*
* Note: {@link SpanBuilder#startActive()} is a shorthand for
- * {@code tracer.makeActive(spanBuilder.startManual())}.
+ * {@code tracer.scopeManager().activate(spanBuilder.startManual())}.
*
- * @return an {@link ActiveSpan}, already registered via the {@link ActiveSpanSource}
+ * @return an {@link Scope}, already registered via the {@link ScopeManager}
*
- * @see ActiveSpanSource
- * @see ActiveSpan
+ * @see ScopeManager
+ * @see Scope
*/
- ActiveSpan startActive();
+ Scope startActive();
+ Scope startActive(boolean finishOnClose);
/**
* Like {@link #startActive()}, but the returned {@link Span} has not been registered via the
- * {@link ActiveSpanSource}.
+ * {@link ScopeManager}.
*
* @see SpanBuilder#startActive()
* @return the newly-started Span instance, which has *not* been automatically registered
- * via the {@link ActiveSpanSource}
+ * via the {@link ScopeManager}
*/
Span startManual();
diff --git a/opentracing-api/src/main/java/io/opentracing/tag/AbstractTag.java b/opentracing-api/src/main/java/io/opentracing/tag/AbstractTag.java
index 4fed5c18..792ca636 100644
--- a/opentracing-api/src/main/java/io/opentracing/tag/AbstractTag.java
+++ b/opentracing-api/src/main/java/io/opentracing/tag/AbstractTag.java
@@ -13,7 +13,7 @@
*/
package io.opentracing.tag;
-import io.opentracing.BaseSpan;
+import io.opentracing.Span;
public abstract class AbstractTag {
protected final String key;
@@ -26,5 +26,5 @@ public String getKey() {
return key;
}
- protected abstract void set(BaseSpan> span, T tagValue);
+ protected abstract void set(Span span, T tagValue);
}
diff --git a/opentracing-api/src/main/java/io/opentracing/tag/BooleanTag.java b/opentracing-api/src/main/java/io/opentracing/tag/BooleanTag.java
index f9be1ee3..8168d422 100644
--- a/opentracing-api/src/main/java/io/opentracing/tag/BooleanTag.java
+++ b/opentracing-api/src/main/java/io/opentracing/tag/BooleanTag.java
@@ -13,7 +13,7 @@
*/
package io.opentracing.tag;
-import io.opentracing.BaseSpan;
+import io.opentracing.Span;
public class BooleanTag extends AbstractTag {
public BooleanTag(String key) {
@@ -21,7 +21,7 @@ public BooleanTag(String key) {
}
@Override
- public void set(BaseSpan> span, Boolean tagValue) {
+ public void set(Span span, Boolean tagValue) {
span.setTag(super.key, tagValue);
}
}
diff --git a/opentracing-api/src/main/java/io/opentracing/tag/IntOrStringTag.java b/opentracing-api/src/main/java/io/opentracing/tag/IntOrStringTag.java
index e173b842..1ea09cbf 100644
--- a/opentracing-api/src/main/java/io/opentracing/tag/IntOrStringTag.java
+++ b/opentracing-api/src/main/java/io/opentracing/tag/IntOrStringTag.java
@@ -13,14 +13,14 @@
*/
package io.opentracing.tag;
-import io.opentracing.BaseSpan;
+import io.opentracing.Span;
public class IntOrStringTag extends IntTag {
public IntOrStringTag(String key) {
super(key);
}
- public void set(BaseSpan> span, String tagValue) {
+ public void set(Span span, String tagValue) {
span.setTag(super.key, tagValue);
}
}
diff --git a/opentracing-api/src/main/java/io/opentracing/tag/IntTag.java b/opentracing-api/src/main/java/io/opentracing/tag/IntTag.java
index 48f4ae71..cb126492 100644
--- a/opentracing-api/src/main/java/io/opentracing/tag/IntTag.java
+++ b/opentracing-api/src/main/java/io/opentracing/tag/IntTag.java
@@ -13,7 +13,7 @@
*/
package io.opentracing.tag;
-import io.opentracing.BaseSpan;
+import io.opentracing.Span;
public class IntTag extends AbstractTag {
public IntTag(String key) {
@@ -21,7 +21,7 @@ public IntTag(String key) {
}
@Override
- public void set(BaseSpan> span, Integer tagValue) {
+ public void set(Span span, Integer tagValue) {
span.setTag(super.key, tagValue);
}
}
diff --git a/opentracing-api/src/main/java/io/opentracing/tag/StringTag.java b/opentracing-api/src/main/java/io/opentracing/tag/StringTag.java
index 1fdba21a..65cfd59e 100644
--- a/opentracing-api/src/main/java/io/opentracing/tag/StringTag.java
+++ b/opentracing-api/src/main/java/io/opentracing/tag/StringTag.java
@@ -13,7 +13,7 @@
*/
package io.opentracing.tag;
-import io.opentracing.BaseSpan;
+import io.opentracing.Span;
public class StringTag extends AbstractTag {
public StringTag(String key) {
@@ -21,11 +21,11 @@ public StringTag(String key) {
}
@Override
- public void set(BaseSpan> span, String tagValue) {
+ public void set(Span span, String tagValue) {
span.setTag(super.key, tagValue);
}
- public void set(BaseSpan> span, StringTag tag) {
+ public void set(Span span, StringTag tag) {
span.setTag(super.key, tag.key);
}
}
diff --git a/opentracing-api/src/test/java/io/opentracing/tag/AbstractTagTest.java b/opentracing-api/src/test/java/io/opentracing/tag/AbstractTagTest.java
index 816e259f..f327851e 100644
--- a/opentracing-api/src/test/java/io/opentracing/tag/AbstractTagTest.java
+++ b/opentracing-api/src/test/java/io/opentracing/tag/AbstractTagTest.java
@@ -17,10 +17,8 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
-import org.junit.Test;
-
-import io.opentracing.ActiveSpan;
import io.opentracing.Span;
+import org.junit.Test;
/**
* @author Pavol Loffay
@@ -45,16 +43,4 @@ public void testSetTagOnSpan() {
verify(activeSpan).setTag(key, value);
}
-
- @Test
- public void testSetTagOnActiveSpan() {
- String value = "foo";
- String key = "bar";
-
- ActiveSpan activeSpan = mock(ActiveSpan.class);
- StringTag tag = new StringTag(key);
- tag.set(activeSpan, value);
-
- verify(activeSpan).setTag(key, value);
- }
}
diff --git a/opentracing-examples/src/test/java/io/opentracing/examples/AutoFinishScope.java b/opentracing-examples/src/test/java/io/opentracing/examples/AutoFinishScope.java
new file mode 100644
index 00000000..0010a54e
--- /dev/null
+++ b/opentracing-examples/src/test/java/io/opentracing/examples/AutoFinishScope.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2016-2017 The OpenTracing 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 io.opentracing.examples;
+
+import io.opentracing.Scope;
+import io.opentracing.Span;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class AutoFinishScope implements Scope {
+ final AutoFinishScopeManager manager;
+ final AtomicInteger refCount;
+ private final Span wrapped;
+ private final AutoFinishScope toRestore;
+
+ AutoFinishScope(AutoFinishScopeManager manager, AtomicInteger refCount, Span wrapped) {
+ this.manager = manager;
+ this.refCount = refCount;
+ this.wrapped = wrapped;
+ this.toRestore = manager.tlsScope.get();
+ manager.tlsScope.set(this);
+ }
+
+ public class Continuation {
+ public Continuation() {
+ refCount.incrementAndGet();
+ }
+
+ public AutoFinishScope activate() {
+ return new AutoFinishScope(manager, refCount, wrapped);
+ }
+ }
+
+ public Continuation capture() {
+ return new Continuation();
+ }
+
+ @Override
+ public void close() {
+ if (manager.tlsScope.get() != this) {
+ return;
+ }
+
+ if (refCount.decrementAndGet() == 0) {
+ wrapped.finish();
+ }
+
+ manager.tlsScope.set(toRestore);
+ }
+
+ @Override
+ public Span span() {
+ return wrapped;
+ }
+}
diff --git a/opentracing-util/src/main/java/io/opentracing/util/ThreadLocalActiveSpanSource.java b/opentracing-examples/src/test/java/io/opentracing/examples/AutoFinishScopeManager.java
similarity index 51%
rename from opentracing-util/src/main/java/io/opentracing/util/ThreadLocalActiveSpanSource.java
rename to opentracing-examples/src/test/java/io/opentracing/examples/AutoFinishScopeManager.java
index 2cd7e6e2..bfb578bd 100644
--- a/opentracing-util/src/main/java/io/opentracing/util/ThreadLocalActiveSpanSource.java
+++ b/opentracing-examples/src/test/java/io/opentracing/examples/AutoFinishScopeManager.java
@@ -11,32 +11,29 @@
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
-package io.opentracing.util;
+package io.opentracing.examples;
-import io.opentracing.ActiveSpan;
-import io.opentracing.ActiveSpanSource;
+import io.opentracing.ScopeManager;
import io.opentracing.Span;
-import io.opentracing.Tracer;
import java.util.concurrent.atomic.AtomicInteger;
-/**
- * A simple {@link ActiveSpanSource} implementation built on top of Java's thread-local storage primitive.
- *
- * @see ThreadLocalActiveSpan
- * @see Tracer#activeSpan()
- */
-public class ThreadLocalActiveSpanSource implements ActiveSpanSource {
- final ThreadLocal tlsSnapshot = new ThreadLocal();
+public class AutoFinishScopeManager implements ScopeManager {
+ final ThreadLocal tlsScope = new ThreadLocal();
+
+ @Override
+ public AutoFinishScope activate(Span span) {
+ return new AutoFinishScope(this, new AtomicInteger(1), span);
+ }
@Override
- public ThreadLocalActiveSpan activeSpan() {
- return tlsSnapshot.get();
+ public AutoFinishScope activate(Span span, boolean finishOnClose) {
+ return new AutoFinishScope(this, new AtomicInteger(1), span);
}
@Override
- public ActiveSpan makeActive(Span span) {
- return new ThreadLocalActiveSpan(this, span, new AtomicInteger(1));
+ public AutoFinishScope active() {
+ return tlsScope.get();
}
}
diff --git a/opentracing-examples/src/test/java/io/opentracing/examples/activate_deactivate/RunnableAction.java b/opentracing-examples/src/test/java/io/opentracing/examples/activate_deactivate/RunnableAction.java
index fab14632..bda704d3 100644
--- a/opentracing-examples/src/test/java/io/opentracing/examples/activate_deactivate/RunnableAction.java
+++ b/opentracing-examples/src/test/java/io/opentracing/examples/activate_deactivate/RunnableAction.java
@@ -13,8 +13,8 @@
*/
package io.opentracing.examples.activate_deactivate;
-import io.opentracing.ActiveSpan;
-import io.opentracing.ActiveSpan.Continuation;
+import io.opentracing.examples.AutoFinishScope;
+import io.opentracing.examples.AutoFinishScope.Continuation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -30,8 +30,8 @@ public class RunnableAction implements Runnable {
private final Continuation continuation;
- RunnableAction(ActiveSpan activeSpan) {
- continuation = activeSpan.capture();
+ RunnableAction(AutoFinishScope scope) {
+ continuation = scope.capture();
logger.info("Action created");
}
@@ -42,7 +42,7 @@ public class RunnableAction implements Runnable {
@Override
public void run() {
logger.info("Action started");
- ActiveSpan activeSpan = continuation.activate();
+ AutoFinishScope scope = continuation.activate();
try {
TimeUnit.SECONDS.sleep(1); // without sleep first action can finish before second is started
@@ -51,9 +51,9 @@ public void run() {
}
// set random tag starting with 'test_tag_' to test that finished span has all of them
- activeSpan.setTag("test_tag_" + ThreadLocalRandom.current().nextInt(), "random");
+ scope.span().setTag("test_tag_" + ThreadLocalRandom.current().nextInt(), "random");
- activeSpan.deactivate();
+ scope.close();
logger.info("Action finished");
}
}
diff --git a/opentracing-examples/src/test/java/io/opentracing/examples/activate_deactivate/ScheduledActionsTest.java b/opentracing-examples/src/test/java/io/opentracing/examples/activate_deactivate/ScheduledActionsTest.java
index c42ad772..cc5307c2 100644
--- a/opentracing-examples/src/test/java/io/opentracing/examples/activate_deactivate/ScheduledActionsTest.java
+++ b/opentracing-examples/src/test/java/io/opentracing/examples/activate_deactivate/ScheduledActionsTest.java
@@ -13,11 +13,12 @@
*/
package io.opentracing.examples.activate_deactivate;
-import io.opentracing.ActiveSpan;
+import io.opentracing.Scope;
+import io.opentracing.examples.AutoFinishScope;
+import io.opentracing.examples.AutoFinishScopeManager;
import io.opentracing.mock.MockSpan;
import io.opentracing.mock.MockTracer;
import io.opentracing.mock.MockTracer.Propagator;
-import io.opentracing.util.ThreadLocalActiveSpanSource;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -37,7 +38,7 @@ public class ScheduledActionsTest {
private static final Logger logger = LoggerFactory.getLogger(ScheduledActionsTest.class);
- private final MockTracer tracer = new MockTracer(new ThreadLocalActiveSpanSource(),
+ private final MockTracer tracer = new MockTracer(new AutoFinishScopeManager(),
Propagator.TEXT_MAP);
private final ScheduledExecutorService service = Executors.newScheduledThreadPool(10);
@@ -88,8 +89,8 @@ private Thread entryThread() {
@Override
public void run() {
logger.info("Entry thread started");
- try (ActiveSpan activeSpan = tracer.buildSpan("parent").startActive()) {
- Runnable action = new RunnableAction(activeSpan);
+ try (Scope scope = tracer.buildSpan("parent").startActive()) {
+ Runnable action = new RunnableAction((AutoFinishScope)scope);
// Action is executed at some time and we are not able to check status
service.schedule(action, 500, TimeUnit.MILLISECONDS);
@@ -107,9 +108,9 @@ private Thread entryThreadWithTwoActions() {
@Override
public void run() {
logger.info("Entry thread 2x started");
- try (ActiveSpan activeSpan = tracer.buildSpan("parent").startActive()) {
- Runnable action = new RunnableAction(activeSpan);
- Runnable action2 = new RunnableAction(activeSpan);
+ try (Scope scope = tracer.buildSpan("parent").startActive()) {
+ Runnable action = new RunnableAction((AutoFinishScope)scope);
+ Runnable action2 = new RunnableAction((AutoFinishScope)scope);
Random random = new Random();
diff --git a/opentracing-examples/src/test/java/io/opentracing/examples/active_span_replacement/ActiveSpanReplacementTest.java b/opentracing-examples/src/test/java/io/opentracing/examples/active_span_replacement/ActiveSpanReplacementTest.java
index 7c907014..72cb979b 100644
--- a/opentracing-examples/src/test/java/io/opentracing/examples/active_span_replacement/ActiveSpanReplacementTest.java
+++ b/opentracing-examples/src/test/java/io/opentracing/examples/active_span_replacement/ActiveSpanReplacementTest.java
@@ -13,11 +13,12 @@
*/
package io.opentracing.examples.active_span_replacement;
-import io.opentracing.ActiveSpan;
+import io.opentracing.Scope;
+import io.opentracing.Span;
import io.opentracing.mock.MockSpan;
import io.opentracing.mock.MockTracer;
import io.opentracing.mock.MockTracer.Propagator;
-import io.opentracing.util.ThreadLocalActiveSpanSource;
+import io.opentracing.util.ThreadLocalScopeManager;
import org.junit.Test;
import java.util.List;
@@ -35,7 +36,7 @@
public class ActiveSpanReplacementTest {
- private final MockTracer tracer = new MockTracer(new ThreadLocalActiveSpanSource(),
+ private final MockTracer tracer = new MockTracer(new ThreadLocalScopeManager(),
Propagator.TEXT_MAP);
private final ExecutorService executor = Executors.newCachedThreadPool();
@@ -43,8 +44,9 @@ public class ActiveSpanReplacementTest {
@Test
public void test() throws Exception {
// Start an isolated task and query for its result in another task/thread
- try (ActiveSpan span = tracer.buildSpan("initial").startActive()) {
- submitAnotherTask(span);
+ try (Scope scope = tracer.buildSpan("initial").startActive(false)) {
+ // Explicitly pass a Span to be finished once a late calculation is done.
+ submitAnotherTask(scope.span());
}
await().atMost(15, TimeUnit.SECONDS).until(finishedSpansSize(tracer), equalTo(3));
@@ -63,25 +65,25 @@ public void test() throws Exception {
assertNotEquals(spans.get(0).context().traceId(), spans.get(1).context().traceId());
assertEquals(0, spans.get(0).parentId());
- assertNull(tracer.activeSpan());
+ assertNull(tracer.scopeManager().active());
}
- private void submitAnotherTask(ActiveSpan span) {
- final ActiveSpan.Continuation cont = span.capture();
+ private void submitAnotherTask(final Span initialSpan) {
executor.submit(new Runnable() {
@Override
public void run() {
// Create a new Span for this task
- try (ActiveSpan taskSpan = tracer.buildSpan("task").startActive()) {
+ try (Scope taskScope = tracer.buildSpan("task").startActive()) {
// Simulate work strictly related to the initial Span
- try (ActiveSpan initialSpan = cont.activate()) {
+ // and finish it.
+ try (Scope initialScope = tracer.scopeManager().activate(initialSpan)) {
sleep(50);
}
// Restore the span for this task and create a subspan
- try (ActiveSpan subTask = tracer.buildSpan("subtask").startActive()) {
+ try (Scope subTaskScope = tracer.buildSpan("subtask").startActive()) {
}
}
}
diff --git a/opentracing-examples/src/test/java/io/opentracing/examples/async_propagation/Actor.java b/opentracing-examples/src/test/java/io/opentracing/examples/async_propagation/Actor.java
new file mode 100644
index 00000000..d36c1885
--- /dev/null
+++ b/opentracing-examples/src/test/java/io/opentracing/examples/async_propagation/Actor.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2016-2017 The OpenTracing 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 io.opentracing.examples.async_propagation;
+
+import io.opentracing.Scope;
+import io.opentracing.Span;
+import io.opentracing.mock.MockTracer;
+import io.opentracing.tag.Tags;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.Phaser;
+
+/** @author tylerbenson */
+public class Actor implements AutoCloseable {
+ private final ExecutorService executor;
+ private final MockTracer tracer;
+ private final Phaser phaser;
+
+ public Actor(MockTracer tracer, Phaser phaser) {
+ // Passed along here for testing. Normally should be referenced via GlobalTracer.get().
+ this.tracer = tracer;
+
+ this.phaser = phaser;
+ executor = Executors.newSingleThreadExecutor();
+ }
+
+ @Override
+ public void close() {
+ executor.shutdown();
+ }
+
+ public void tell(final String message) {
+ final Span span = tracer.scopeManager().active().span();
+ phaser.register();
+ executor.submit(
+ new Runnable() {
+ @Override
+ public void run() {
+ try (Scope parent = tracer.scopeManager().activate(span)) {
+ try (Scope child =
+ tracer
+ .buildSpan("sent")
+ .asChildOf(parent.span())
+ .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CONSUMER)
+ .startActive()) {
+ phaser.arriveAndAwaitAdvance(); // child tracer started
+ System.out.println("received " + message);
+ phaser.arriveAndAwaitAdvance(); // assert size
+ }
+ phaser.arriveAndAwaitAdvance(); // child tracer finished
+ phaser.arriveAndAwaitAdvance(); // assert size
+ }
+ phaser.arriveAndAwaitAdvance(); // parent tracer finished
+ phaser.arriveAndDeregister(); // assert size
+ }
+ });
+ }
+
+ public Future ask(final String message) {
+ final Span span = tracer.scopeManager().active().span();
+ phaser.register();
+ Future future =
+ executor.submit(
+ new Callable() {
+ @Override
+ public String call() throws Exception {
+ try (Scope parent = tracer.scopeManager().activate(span)) {
+ try (Scope child =
+ tracer
+ .buildSpan("sent")
+ .asChildOf(parent.span())
+ .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CONSUMER)
+ .startActive()) {
+ phaser.arriveAndAwaitAdvance(); // child tracer started
+ phaser.arriveAndAwaitAdvance(); // assert size
+ return "received " + message;
+ } finally {
+ phaser.arriveAndAwaitAdvance(); // child tracer finished
+ phaser.arriveAndAwaitAdvance(); // assert size
+ }
+ } finally {
+ phaser.arriveAndAwaitAdvance(); // parent tracer finished
+ phaser.arriveAndDeregister(); // assert size
+ }
+ }
+ });
+ return future;
+ }
+}
diff --git a/opentracing-examples/src/test/java/io/opentracing/examples/async_propagation/AsyncPropagationTest.java b/opentracing-examples/src/test/java/io/opentracing/examples/async_propagation/AsyncPropagationTest.java
new file mode 100644
index 00000000..1888d682
--- /dev/null
+++ b/opentracing-examples/src/test/java/io/opentracing/examples/async_propagation/AsyncPropagationTest.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright 2016-2017 The OpenTracing 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 io.opentracing.examples.async_propagation;
+
+import io.opentracing.Scope;
+import io.opentracing.examples.AutoFinishScope;
+import io.opentracing.examples.AutoFinishScopeManager;
+import io.opentracing.mock.MockSpan;
+import io.opentracing.mock.MockTracer;
+import io.opentracing.mock.MockTracer.Propagator;
+import io.opentracing.tag.Tags;
+import io.opentracing.util.ThreadLocalScopeManager;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.Phaser;
+import java.util.concurrent.atomic.AtomicReference;
+
+import static io.opentracing.examples.TestUtils.getOneByTag;
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * These tests are intended to simulate the kind of async models that are common in java async
+ * frameworks.
+ *
+ *
+ *
Actor ask/tell
+ *
Promises with callbacks
+ *
Work split by suspend/resume
+ *
+ *
+ * For improved readability, ignore the phaser lines as those are there to ensure deterministic
+ * execution for the tests without sleeps.
+ *
+ * @author tylerbenson
+ */
+public class AsyncPropagationTest {
+
+ private final MockTracer tracer =
+ new MockTracer(new ThreadLocalScopeManager(), Propagator.TEXT_MAP);
+ private final MockTracer autoTracer =
+ new MockTracer(new AutoFinishScopeManager(), Propagator.TEXT_MAP);
+ private Phaser phaser;
+
+ @Before
+ public void before() {
+ phaser = new Phaser();
+ }
+
+ @Test
+ public void testActorTell() {
+ try (Actor actor = new Actor(tracer, phaser)) {
+ phaser.register();
+ try (Scope parent =
+ tracer
+ .buildSpan("actorTell")
+ .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_PRODUCER)
+ .withTag(Tags.COMPONENT.getKey(), "example-actor")
+ .startActive(false)) {
+ actor.tell("my message");
+ }
+ phaser.arriveAndAwaitAdvance(); // child tracer started
+ assertThat(tracer.finishedSpans().size()).isEqualTo(0);
+ phaser.arriveAndAwaitAdvance(); // continue...
+
+ phaser.arriveAndAwaitAdvance(); // child tracer finished
+ assertThat(tracer.finishedSpans().size()).isEqualTo(1);
+ assertThat(getOneByTag(tracer.finishedSpans(), Tags.SPAN_KIND, Tags.SPAN_KIND_CONSUMER))
+ .isNotNull();
+ phaser.arriveAndAwaitAdvance(); // continue...
+
+ phaser.arriveAndAwaitAdvance(); // parent tracer finished
+ List finished = tracer.finishedSpans();
+ phaser.arriveAndDeregister(); // continue...
+
+ assertThat(finished.size()).isEqualTo(2);
+ assertThat(finished.get(0).context().traceId())
+ .isEqualTo(finished.get(1).context().traceId());
+ assertThat(getOneByTag(finished, Tags.SPAN_KIND, Tags.SPAN_KIND_CONSUMER)).isNotNull();
+ assertThat(getOneByTag(finished, Tags.SPAN_KIND, Tags.SPAN_KIND_PRODUCER)).isNotNull();
+ assertThat(tracer.scopeManager().active()).isNull();
+ }
+ }
+
+ @Test
+ public void testActorAsk() throws ExecutionException, InterruptedException {
+ try (Actor actor = new Actor(tracer, phaser)) {
+ phaser.register();
+ Future future;
+ try (Scope parent =
+ tracer
+ .buildSpan("actorAsk")
+ .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_PRODUCER)
+ .withTag(Tags.COMPONENT.getKey(), "example-actor")
+ .startActive(false)) {
+ future = actor.ask("my message");
+ }
+ phaser.arriveAndAwaitAdvance(); // child tracer started
+ assertThat(tracer.finishedSpans().size()).isEqualTo(0);
+ phaser.arriveAndAwaitAdvance(); // continue...
+
+ phaser.arriveAndAwaitAdvance(); // child tracer finished
+ assertThat(tracer.finishedSpans().size()).isEqualTo(1);
+ assertThat(getOneByTag(tracer.finishedSpans(), Tags.SPAN_KIND, Tags.SPAN_KIND_CONSUMER))
+ .isNotNull();
+ phaser.arriveAndAwaitAdvance(); // continue...
+
+ phaser.arriveAndAwaitAdvance(); // parent tracer finished
+ List finished = tracer.finishedSpans();
+ phaser.arriveAndDeregister(); // continue...
+
+ String message = future.get(); // This really should be a non-blocking callback...
+ assertThat(message).isEqualTo("received my message");
+ assertThat(finished.size()).isEqualTo(2);
+ assertThat(finished.get(0).context().traceId())
+ .isEqualTo(finished.get(1).context().traceId());
+ assertThat(getOneByTag(finished, Tags.SPAN_KIND, Tags.SPAN_KIND_CONSUMER)).isNotNull();
+ assertThat(getOneByTag(finished, Tags.SPAN_KIND, Tags.SPAN_KIND_PRODUCER)).isNotNull();
+ assertThat(tracer.scopeManager().active()).isNull();
+ }
+ }
+
+ @Test
+ public void testPromiseCallback() {
+ phaser.register(); // register test thread
+ final AtomicReference successResult = new AtomicReference<>();
+ final AtomicReference errorResult = new AtomicReference<>();
+ try (PromiseContext context = new PromiseContext(phaser, 2)) {
+ try (Scope parent =
+ autoTracer
+ .buildSpan("promises")
+ .withTag(Tags.COMPONENT.getKey(), "example-promises")
+ .startActive()) {
+
+ Promise promise1 = new Promise<>(context, autoTracer);
+
+ promise1.onSuccess(
+ new Promise.SuccessCallback() {
+ @Override
+ public void accept(String s) {
+ successResult.set(s);
+ phaser.arriveAndAwaitAdvance(); // result set
+ }
+ });
+
+ Promise promise2 = new Promise(context, autoTracer);
+
+ promise2.onError(
+ new Promise.ErrorCallback() {
+ @Override
+ public void accept(Throwable t) {
+ errorResult.set(t);
+ phaser.arriveAndAwaitAdvance(); // result set
+ }
+ });
+ assertThat(autoTracer.finishedSpans().size()).isEqualTo(0);
+ promise1.success("success!");
+ promise2.error(new Exception("some error."));
+ }
+
+ phaser.arriveAndAwaitAdvance(); // wait for results to be set
+ assertThat(successResult.get()).isEqualTo("success!");
+ assertThat(errorResult.get()).hasMessage("some error.");
+
+ phaser.arriveAndAwaitAdvance(); // wait for traces to be reported
+ List finished = autoTracer.finishedSpans();
+ assertThat(finished.size()).isEqualTo(3);
+ assertThat(getOneByTag(finished, Tags.COMPONENT, "example-promises")).isNotNull();
+ assertThat(getOneByTag(finished, Tags.COMPONENT, "example-promises").parentId()).isEqualTo(0);
+ long parentId = getOneByTag(finished, Tags.COMPONENT, "example-promises").context().spanId();
+ assertThat(getOneByTag(finished, Tags.COMPONENT, "success")).isNotNull();
+ assertThat(getOneByTag(finished, Tags.COMPONENT, "success").parentId()).isEqualTo(parentId);
+ assertThat(getOneByTag(finished, Tags.COMPONENT, "error")).isNotNull();
+ assertThat(getOneByTag(finished, Tags.COMPONENT, "error").parentId()).isEqualTo(parentId);
+ }
+ }
+
+ @Test
+ public void testContinuationInterleaving() {
+ SuspendResume job1 = new SuspendResume(1, tracer);
+ SuspendResume job2 = new SuspendResume(2, tracer);
+
+ // Pretend that the framework is controlling actual execution here.
+ job1.doPart("some work for 1");
+ job2.doPart("some work for 2");
+ job1.doPart("other work for 1");
+ job2.doPart("other work for 2");
+ job2.doPart("more work for 2");
+ job1.doPart("more work for 1");
+
+ job1.done();
+ job2.done();
+
+ List finished = tracer.finishedSpans();
+ assertThat(finished.size()).isEqualTo(2);
+
+ assertThat(finished.get(0).operationName()).isEqualTo("job 1");
+ assertThat(finished.get(1).operationName()).isEqualTo("job 2");
+
+ assertThat(finished.get(0).parentId()).isEqualTo(0);
+ assertThat(finished.get(1).parentId()).isEqualTo(0);
+ }
+}
diff --git a/opentracing-examples/src/test/java/io/opentracing/examples/async_propagation/Promise.java b/opentracing-examples/src/test/java/io/opentracing/examples/async_propagation/Promise.java
new file mode 100644
index 00000000..7919d7c4
--- /dev/null
+++ b/opentracing-examples/src/test/java/io/opentracing/examples/async_propagation/Promise.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2016-2017 The OpenTracing 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 io.opentracing.examples.async_propagation;
+
+import io.opentracing.Scope;
+import io.opentracing.examples.AutoFinishScope;
+import io.opentracing.examples.AutoFinishScope.Continuation;
+import io.opentracing.mock.MockTracer;
+import io.opentracing.tag.Tags;
+
+import java.util.Collection;
+import java.util.LinkedList;
+
+/** @author tylerbenson */
+public class Promise {
+ private final PromiseContext context;
+ private final MockTracer tracer;
+ private final Scope scope;
+
+ private final Collection>> successCallbacks = new LinkedList<>();
+ private final Collection> errorCallbacks = new LinkedList<>();
+
+ public Promise(PromiseContext context, MockTracer tracer) {
+ this.context = context;
+
+ // Passed along here for testing. Normally should be referenced via GlobalTracer.get().
+ this.tracer = tracer;
+ scope = tracer.scopeManager().active();
+ }
+
+ public void onSuccess(SuccessCallback successCallback) {
+ Continuation capture = ((AutoFinishScope)scope).capture();
+ successCallbacks.add(new Pair<>(capture, successCallback));
+ }
+
+ public void onError(ErrorCallback errorCallback) {
+ Continuation capture = ((AutoFinishScope)scope).capture();
+ errorCallbacks.add(new Pair<>(capture, errorCallback));
+ }
+
+ public void success(final T result) {
+ for (final Pair> pair : successCallbacks) {
+ context.submit(
+ new Runnable() {
+ @Override
+ public void run() {
+ try (Scope parent = pair.capture.activate()) {
+ try (Scope child =
+ tracer
+ .buildSpan("success")
+ .withTag(Tags.COMPONENT.getKey(), "success")
+ .asChildOf(parent.span())
+ .startActive()) {
+ pair.callback.accept(result);
+ }
+ }
+ context.getPhaser().arriveAndAwaitAdvance(); // trace reported
+ }
+ });
+ }
+ }
+
+ public void error(final Throwable error) {
+ for (final Pair pair : errorCallbacks) {
+ context.submit(
+ new Runnable() {
+ @Override
+ public void run() {
+ try (Scope parent = pair.capture.activate()) {
+ try (Scope child =
+ tracer
+ .buildSpan("error")
+ .withTag(Tags.COMPONENT.getKey(), "error")
+ .asChildOf(parent.span())
+ .startActive()) {
+ pair.callback.accept(error);
+ }
+ }
+ context.getPhaser().arriveAndAwaitAdvance(); // trace reported
+ }
+ });
+ }
+ }
+
+ public interface SuccessCallback {
+ /** @param t the result of the promise */
+ void accept(T t);
+ }
+
+ public interface ErrorCallback {
+ /** @param t the error result of the promise */
+ void accept(Throwable t);
+ }
+
+ private class Pair {
+
+ final Continuation capture;
+ final C callback;
+
+ public Pair(Continuation capture, C callback) {
+ this.capture = capture;
+ this.callback = callback;
+ }
+ }
+}
diff --git a/opentracing-examples/src/test/java/io/opentracing/examples/async_propagation/PromiseContext.java b/opentracing-examples/src/test/java/io/opentracing/examples/async_propagation/PromiseContext.java
new file mode 100644
index 00000000..8951e0d3
--- /dev/null
+++ b/opentracing-examples/src/test/java/io/opentracing/examples/async_propagation/PromiseContext.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2016-2017 The OpenTracing 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 io.opentracing.examples.async_propagation;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Phaser;
+
+/** @author tylerbenson */
+public class PromiseContext implements AutoCloseable {
+
+ private final Phaser phaser;
+ private final ExecutorService executor;
+
+ public PromiseContext(Phaser phaser, int concurrency) {
+ this.phaser = phaser;
+ executor = Executors.newFixedThreadPool(concurrency);
+ }
+
+ @Override
+ public void close() {
+ executor.shutdown();
+ }
+
+ public void submit(Runnable runnable) {
+ phaser.register(); // register the work to be done on the executor
+ executor.submit(runnable);
+ }
+
+ public Phaser getPhaser() {
+ return phaser;
+ }
+}
diff --git a/opentracing-examples/src/test/java/io/opentracing/examples/async_propagation/SuspendResume.java b/opentracing-examples/src/test/java/io/opentracing/examples/async_propagation/SuspendResume.java
new file mode 100644
index 00000000..02cb87c9
--- /dev/null
+++ b/opentracing-examples/src/test/java/io/opentracing/examples/async_propagation/SuspendResume.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2016-2017 The OpenTracing 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 io.opentracing.examples.async_propagation;
+
+import io.opentracing.Scope;
+import io.opentracing.Span;
+import io.opentracing.mock.MockTracer;
+import io.opentracing.tag.Tags;
+
+/** @author tylerbenson */
+public class SuspendResume {
+
+ private final int id;
+ private final MockTracer tracer;
+ private Span span;
+
+ public SuspendResume(int id, MockTracer tracer) {
+ this.id = id;
+
+ // Passed along here for testing. Normally should be referenced via GlobalTracer.get().
+ this.tracer = tracer;
+
+ try (Scope scope =
+ tracer
+ .buildSpan("job " + id)
+ .withTag(Tags.COMPONENT.getKey(), "suspend-resume")
+ .startActive(false)) {
+ span = scope.span();
+ }
+ }
+
+ public void doPart(String name) {
+ try (Scope scope = tracer.scopeManager().activate(span, false)) {
+ scope.span().log("part: " + name);
+ }
+ }
+
+ public void done() {
+ span.finish();
+ }
+}
diff --git a/opentracing-examples/src/test/java/io/opentracing/examples/client_server/Client.java b/opentracing-examples/src/test/java/io/opentracing/examples/client_server/Client.java
index 15554a08..2954ab33 100644
--- a/opentracing-examples/src/test/java/io/opentracing/examples/client_server/Client.java
+++ b/opentracing-examples/src/test/java/io/opentracing/examples/client_server/Client.java
@@ -13,7 +13,7 @@
*/
package io.opentracing.examples.client_server;
-import io.opentracing.ActiveSpan;
+import io.opentracing.Scope;
import io.opentracing.Tracer;
import io.opentracing.propagation.Format.Builtin;
import io.opentracing.propagation.TextMapInjectAdapter;
@@ -34,11 +34,11 @@ public Client(ArrayBlockingQueue queue, Tracer tracer) {
public void send() throws InterruptedException {
Message message = new Message();
- try (ActiveSpan activeSpan = tracer.buildSpan("send")
+ try (Scope scope = tracer.buildSpan("send")
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT)
.withTag(Tags.COMPONENT.getKey(), "example-client")
.startActive()) {
- tracer.inject(activeSpan.context(), Builtin.TEXT_MAP, new TextMapInjectAdapter(message));
+ tracer.inject(scope.span().context(), Builtin.TEXT_MAP, new TextMapInjectAdapter(message));
queue.put(message);
}
}
diff --git a/opentracing-examples/src/test/java/io/opentracing/examples/client_server/Server.java b/opentracing-examples/src/test/java/io/opentracing/examples/client_server/Server.java
index 2067ee2d..240445ea 100644
--- a/opentracing-examples/src/test/java/io/opentracing/examples/client_server/Server.java
+++ b/opentracing-examples/src/test/java/io/opentracing/examples/client_server/Server.java
@@ -13,7 +13,7 @@
*/
package io.opentracing.examples.client_server;
-import io.opentracing.ActiveSpan;
+import io.opentracing.Scope;
import io.opentracing.SpanContext;
import io.opentracing.Tracer;
import io.opentracing.propagation.Format.Builtin;
@@ -34,7 +34,7 @@ public Server(ArrayBlockingQueue queue, Tracer tracer) {
private void process(Message message) {
SpanContext context = tracer.extract(Builtin.TEXT_MAP, new TextMapExtractAdapter(message));
- try (ActiveSpan activeSpan = tracer.buildSpan("receive")
+ try (Scope scope = tracer.buildSpan("receive")
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_SERVER)
.withTag(Tags.COMPONENT.getKey(), "example-server")
.asChildOf(context).startActive()) {
diff --git a/opentracing-examples/src/test/java/io/opentracing/examples/client_server/TestClientServerTest.java b/opentracing-examples/src/test/java/io/opentracing/examples/client_server/TestClientServerTest.java
index 489b98b6..a289cc06 100644
--- a/opentracing-examples/src/test/java/io/opentracing/examples/client_server/TestClientServerTest.java
+++ b/opentracing-examples/src/test/java/io/opentracing/examples/client_server/TestClientServerTest.java
@@ -17,7 +17,7 @@
import io.opentracing.mock.MockTracer;
import io.opentracing.mock.MockTracer.Propagator;
import io.opentracing.tag.Tags;
-import io.opentracing.util.ThreadLocalActiveSpanSource;
+import io.opentracing.util.ThreadLocalScopeManager;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -36,7 +36,7 @@
public class TestClientServerTest {
- private final MockTracer tracer = new MockTracer(new ThreadLocalActiveSpanSource(),
+ private final MockTracer tracer = new MockTracer(new ThreadLocalScopeManager(),
Propagator.TEXT_MAP);
private final ArrayBlockingQueue queue = new ArrayBlockingQueue<>(10);
private Server server;
@@ -65,6 +65,6 @@ public void test() throws Exception {
assertEquals(finished.get(0).context().traceId(), finished.get(1).context().traceId());
assertNotNull(getOneByTag(finished, Tags.SPAN_KIND, Tags.SPAN_KIND_CLIENT));
assertNotNull(getOneByTag(finished, Tags.SPAN_KIND, Tags.SPAN_KIND_SERVER));
- assertNull(tracer.activeSpan());
+ assertNull(tracer.scopeManager().active());
}
}
diff --git a/opentracing-examples/src/test/java/io/opentracing/examples/common_request_handler/HandlerTest.java b/opentracing-examples/src/test/java/io/opentracing/examples/common_request_handler/HandlerTest.java
index 189ae1de..3e487d4c 100644
--- a/opentracing-examples/src/test/java/io/opentracing/examples/common_request_handler/HandlerTest.java
+++ b/opentracing-examples/src/test/java/io/opentracing/examples/common_request_handler/HandlerTest.java
@@ -13,12 +13,12 @@
*/
package io.opentracing.examples.common_request_handler;
-import io.opentracing.ActiveSpan;
+import io.opentracing.Scope;
import io.opentracing.mock.MockSpan;
import io.opentracing.mock.MockTracer;
import io.opentracing.mock.MockTracer.Propagator;
import io.opentracing.tag.Tags;
-import io.opentracing.util.ThreadLocalActiveSpanSource;
+import io.opentracing.util.ThreadLocalScopeManager;
import org.junit.Before;
import org.junit.Test;
@@ -39,7 +39,7 @@
*/
public class HandlerTest {
- private final MockTracer tracer = new MockTracer(new ThreadLocalActiveSpanSource(),
+ private final MockTracer tracer = new MockTracer(new ThreadLocalScopeManager(),
Propagator.TEXT_MAP);
private final Client client = new Client(new RequestHandler(tracer));
@@ -67,7 +67,7 @@ public void two_requests() throws Exception {
assertEquals(0, finished.get(0).parentId());
assertEquals(0, finished.get(1).parentId());
- assertNull(tracer.activeSpan());
+ assertNull(tracer.scopeManager().active());
}
/**
@@ -75,7 +75,7 @@ public void two_requests() throws Exception {
*/
@Test
public void parent_not_picked_up() throws Exception {
- try (ActiveSpan parent = tracer.buildSpan("parent").startActive()) {
+ try (Scope parent = tracer.buildSpan("parent").startActive()) {
String response = client.send("no_parent").get(15, TimeUnit.SECONDS);
assertEquals("no_parent:response", response);
}
@@ -102,8 +102,8 @@ public void parent_not_picked_up() throws Exception {
@Test
public void bad_solution_to_set_parent() throws Exception {
Client client;
- try (ActiveSpan parent = tracer.buildSpan("parent").startActive()) {
- client = new Client(new RequestHandler(tracer, parent.context()));
+ try (Scope parent = tracer.buildSpan("parent").startActive()) {
+ client = new Client(new RequestHandler(tracer, parent.span().context()));
String response = client.send("correct_parent").get(15, TimeUnit.SECONDS);
assertEquals("correct_parent:response", response);
}
diff --git a/opentracing-examples/src/test/java/io/opentracing/examples/late_span_finish/LateSpanFinishTest.java b/opentracing-examples/src/test/java/io/opentracing/examples/late_span_finish/LateSpanFinishTest.java
index 9fc043a0..60260771 100644
--- a/opentracing-examples/src/test/java/io/opentracing/examples/late_span_finish/LateSpanFinishTest.java
+++ b/opentracing-examples/src/test/java/io/opentracing/examples/late_span_finish/LateSpanFinishTest.java
@@ -13,12 +13,12 @@
*/
package io.opentracing.examples.late_span_finish;
-import io.opentracing.ActiveSpan;
+import io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.mock.MockSpan;
import io.opentracing.mock.MockTracer;
import io.opentracing.mock.MockTracer.Propagator;
-import io.opentracing.util.ThreadLocalActiveSpanSource;
+import io.opentracing.util.ThreadLocalScopeManager;
import org.junit.Test;
import java.util.List;
@@ -33,7 +33,7 @@
public class LateSpanFinishTest {
- private final MockTracer tracer = new MockTracer(new ThreadLocalActiveSpanSource(),
+ private final MockTracer tracer = new MockTracer(new ThreadLocalScopeManager(),
Propagator.TEXT_MAP);
private final ExecutorService executor = Executors.newCachedThreadPool();
@@ -58,7 +58,7 @@ public void test() throws Exception {
assertSameTrace(spans);
- assertNull(tracer.activeSpan());
+ assertNull(tracer.scopeManager().active());
}
@@ -72,11 +72,10 @@ private void submitTasks(final Span parentSpan) {
@Override
public void run() {
// Alternative to calling makeActive() is to pass it manually to asChildOf() for each created Span.
- try (ActiveSpan span = tracer.makeActive(parentSpan)) {
- try (ActiveSpan childSpan1 = tracer.buildSpan("task1").startActive()) {
+ try (Scope scope = tracer.scopeManager().activate(parentSpan, false)) {
+ try (Scope childScope1 = tracer.buildSpan("task1").startActive()) {
sleep(55);
}
- span.capture(); // Workaround, prevent parentSpan from being finished here.
}
}
});
@@ -84,11 +83,10 @@ public void run() {
executor.submit(new Runnable() {
@Override
public void run() {
- try (ActiveSpan span = tracer.makeActive(parentSpan)) {
- try (ActiveSpan childSpan1 = tracer.buildSpan("task2").startActive()) {
+ try (Scope span = tracer.scopeManager().activate(parentSpan, false)) {
+ try (Scope childScope2 = tracer.buildSpan("task2").startActive()) {
sleep(85);
}
- span.capture(); // Workaround, prevent parentSpan from being finished here.
}
}
});
diff --git a/opentracing-examples/src/test/java/io/opentracing/examples/listener_per_request/ListenerTest.java b/opentracing-examples/src/test/java/io/opentracing/examples/listener_per_request/ListenerTest.java
index 0d8646cb..4afd3b0e 100644
--- a/opentracing-examples/src/test/java/io/opentracing/examples/listener_per_request/ListenerTest.java
+++ b/opentracing-examples/src/test/java/io/opentracing/examples/listener_per_request/ListenerTest.java
@@ -17,7 +17,7 @@
import io.opentracing.mock.MockTracer;
import io.opentracing.mock.MockTracer.Propagator;
import io.opentracing.tag.Tags;
-import io.opentracing.util.ThreadLocalActiveSpanSource;
+import io.opentracing.util.ThreadLocalScopeManager;
import org.junit.Test;
import java.util.List;
@@ -32,7 +32,7 @@
*/
public class ListenerTest {
- private final MockTracer tracer = new MockTracer(new ThreadLocalActiveSpanSource(),
+ private final MockTracer tracer = new MockTracer(new ThreadLocalScopeManager(),
Propagator.TEXT_MAP);
@Test
@@ -44,6 +44,6 @@ public void test() throws Exception {
List finished = tracer.finishedSpans();
assertEquals(1, finished.size());
assertNotNull(getOneByTag(finished, Tags.SPAN_KIND, Tags.SPAN_KIND_CLIENT));
- assertNull(tracer.activeSpan());
+ assertNull(tracer.scopeManager().active());
}
}
diff --git a/opentracing-examples/src/test/java/io/opentracing/examples/multiple_callbacks/Client.java b/opentracing-examples/src/test/java/io/opentracing/examples/multiple_callbacks/Client.java
index 0a7c9858..6be803f5 100644
--- a/opentracing-examples/src/test/java/io/opentracing/examples/multiple_callbacks/Client.java
+++ b/opentracing-examples/src/test/java/io/opentracing/examples/multiple_callbacks/Client.java
@@ -13,8 +13,10 @@
*/
package io.opentracing.examples.multiple_callbacks;
-import io.opentracing.ActiveSpan;
+import io.opentracing.Scope;
import io.opentracing.Tracer;
+import io.opentracing.examples.AutoFinishScope;
+import io.opentracing.examples.AutoFinishScope.Continuation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -36,15 +38,17 @@ public Client(Tracer tracer) {
this.tracer = tracer;
}
- public Future