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):
- *
- span.log(
- ImmutableMap.Builder()
- .put("event", "soft error")
- .put("type", "cache timeout")
- .put("waited.millis", 1500)
- .build());
-
- *
- * @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
- *
- *
- span.log(Collections.singletonMap("event", event));
-
- *
- * @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
- *
- *
- span.log(timestampMicroseconds, Collections.singletonMap("event", event));
-
- *
- * @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..caf194ea
--- /dev/null
+++ b/opentracing-api/src/main/java/io/opentracing/Scope.java
@@ -0,0 +1,75 @@
+/*
+ * 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 critical path.
+ */
+public interface Scope extends Closeable {
+ /**
+ * End this {@link Scope}, updating the {@link ScopeManager#active()} in the process.
+ */
+ @Override
+ void close();
+
+ /**
+ * @return the {@link Span} that's been scoped by this {@link Scope}
+ */
+ Span span();
+
+ /**
+ * {@link Observer} is a simple API for observing the opening/closing of {@link Scope} instances.
+ *
+ * @see ScopeManager#activate(Span, Observer)
+ * @see Tracer.SpanBuilder#startActive(Observer)
+ * @see Span#activate(Observer)
+ */
+ interface Observer {
+ /**
+ * A trivial, static {@link Scope.Observer} that finishes the underlying {@link Span} on scope close.
+ */
+ Observer FINISH_ON_CLOSE = new FinishOnCloseScopeObserverImpl();
+
+ /**
+ * Invoked just after the {@link Scope} becomes active.
+ */
+ void onActivate(Scope scope);
+
+ /**
+ * Invoked just before the {@link Scope} closes / is deactivated.
+ */
+ void onClose(Scope scope);
+ }
+}
+
+/**
+ * @see Scope.Observer#FINISH_ON_CLOSE
+ */
+class FinishOnCloseScopeObserverImpl implements Scope.Observer {
+ @Override
+ public void onActivate(Scope scope) {}
+
+ @Override
+ public void onClose(Scope scope) {
+ scope.span().finish();
+ }
+}
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..f112ca1f
--- /dev/null
+++ b/opentracing-api/src/main/java/io/opentracing/ScopeManager.java
@@ -0,0 +1,40 @@
+/*
+ * 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#setScopeManager(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, Scope.Observer scopeObserver);
+
+ /**
+ * @return the currently active {@link Scope} which can be used to access the currently active
+ * {@link Scope#span()}
+ */
+ 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..67003aac 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):
+ *
+ span.log(
+ ImmutableMap.Builder()
+ .put("event", "soft error")
+ .put("type", "cache timeout")
+ .put("waited.millis", 1500)
+ .build());
+
+ *
+ * @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
+ *
+ *
+ span.log(Collections.singletonMap("event", event));
+
+ *
+ * @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
+ *
+ *
+ span.log(timestampMicroseconds, Collections.singletonMap("event", event));
+
+ *
+ * @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.
*
@@ -45,4 +161,11 @@ public interface Span extends BaseSpan {
* @see Span#context()
*/
void finish(long finishMicros);
+
+ /**
+ * Defined as equivalent to calling {@code tracer.scopeManager().activate(this)} on the {@link Tracer} instance
+ * that started this {@link Span} instance.
+ */
+ Scope activate();
+ Scope activate(Scope.Observer observer);
}
diff --git a/opentracing-api/src/main/java/io/opentracing/Tracer.java b/opentracing-api/src/main/java/io/opentracing/Tracer.java
index 25d3d321..286430ef 100644
--- a/opentracing-api/src/main/java/io/opentracing/Tracer.java
+++ b/opentracing-api/src/main/java/io/opentracing/Tracer.java
@@ -18,7 +18,19 @@
/**
* 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();
+
+ /**
+ * Set a new {@link ScopeManager}, presumably as part of initialization. The state of any already active
+ * {@link Scope} instance after this is only defined to do no harm to the process (i.e., not-crash). Again, this is
+ * only intended for use during initialization.
+ */
+ void setScopeManager(ScopeManager scopeManager);
/**
* Return a new SpanBuilder for a Span with the given `operationName`.
@@ -111,7 +123,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
@@ -155,15 +167,15 @@ 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:
*
- * try (ActiveSpan span = tracer.buildSpan("...").startActive()) {
+ * try (ScopeManager.Scope span = tracer.buildSpan("...").startActive()) {
* // (Do work)
* span.setTag( ... ); // etc, etc
- * } // Span finishes automatically unless deferred via {@link ActiveSpan#capture}
+ * } // XXX Span finishes automatically unless deferred via {@link ActiveSpan#capture}
*
*
*
@@ -186,7 +198,8 @@ interface SpanBuilder {
* @see ActiveSpanSource
* @see ActiveSpan
*/
- ActiveSpan startActive();
+ Scope startActive();
+ Scope startActive(Scope.Observer observer);
/**
* Like {@link #startActive()}, but the returned {@link Span} has not been registered via the
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/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-mock/src/main/java/io/opentracing/mock/MockSpan.java b/opentracing-mock/src/main/java/io/opentracing/mock/MockSpan.java
index 859513aa..565cf1a3 100644
--- a/opentracing-mock/src/main/java/io/opentracing/mock/MockSpan.java
+++ b/opentracing-mock/src/main/java/io/opentracing/mock/MockSpan.java
@@ -20,6 +20,7 @@
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
+import io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.SpanContext;
@@ -115,6 +116,16 @@ public synchronized void finish(long finishMicros) {
this.finished = true;
}
+ @Override
+ public Scope activate() {
+ return mockTracer.scopeManager().activate(this);
+ }
+
+ @Override
+ public Scope activate(Scope.Observer observer) {
+ return mockTracer.scopeManager().activate(this, observer);
+ }
+
@Override
public MockSpan setTag(String key, String value) {
return setObjectTag(key, value);
diff --git a/opentracing-mock/src/main/java/io/opentracing/mock/MockTracer.java b/opentracing-mock/src/main/java/io/opentracing/mock/MockTracer.java
index 15e6fcf8..06fe300f 100644
--- a/opentracing-mock/src/main/java/io/opentracing/mock/MockTracer.java
+++ b/opentracing-mock/src/main/java/io/opentracing/mock/MockTracer.java
@@ -13,12 +13,11 @@
*/
package io.opentracing.mock;
-import io.opentracing.ActiveSpan;
-import io.opentracing.ActiveSpanSource;
-import io.opentracing.BaseSpan;
-import io.opentracing.noop.NoopActiveSpanSource;
-import io.opentracing.References;
+import io.opentracing.Scope;
+import io.opentracing.ScopeManager;
import io.opentracing.Span;
+import io.opentracing.noop.NoopScopeManager;
+import io.opentracing.References;
import io.opentracing.SpanContext;
import io.opentracing.Tracer;
import io.opentracing.propagation.Format;
@@ -40,26 +39,18 @@
public class MockTracer implements Tracer {
private List finishedSpans = new ArrayList<>();
private final Propagator propagator;
- private ActiveSpanSource spanSource;
+ private ScopeManager scopeManager;
public MockTracer() {
this(Propagator.PRINTER);
}
- public MockTracer(ActiveSpanSource spanSource) {
- this(spanSource, Propagator.PRINTER);
- }
-
- public MockTracer(ActiveSpanSource spanSource, Propagator propagator) {
- this.propagator = propagator;
- this.spanSource = spanSource;
- }
-
/**
* Create a new MockTracer that passes through any calls to inject() and/or extract().
*/
public MockTracer(Propagator propagator) {
- this(NoopActiveSpanSource.INSTANCE, propagator);
+ this.propagator = propagator;
+ this.scopeManager = NoopScopeManager.INSTANCE;
}
/**
@@ -88,16 +79,6 @@ public synchronized List finishedSpans() {
protected void onSpanFinished(MockSpan mockSpan) {
}
- @Override
- public ActiveSpan activeSpan() {
- return spanSource.activeSpan();
- }
-
- @Override
- public ActiveSpan makeActive(Span span) {
- return spanSource.makeActive(span);
- }
-
/**
* Propagator allows the developer to intercept and verify any calls to inject() and/or extract().
*
@@ -173,17 +154,17 @@ public MockSpan.MockContext extract(Format format, C carrier) {
}
@Override
- public SpanBuilder buildSpan(String operationName) {
- return new SpanBuilder(operationName);
+ public ScopeManager scopeManager() {
+ return this.scopeManager;
}
- private SpanContext activeSpanContext() {
- ActiveSpan handle = this.spanSource.activeSpan();
- if (handle == null) {
- return null;
- }
+ public void setScopeManager(ScopeManager scopeManager) {
+ this.scopeManager = scopeManager;
+ }
- return handle.context();
+ @Override
+ public SpanBuilder buildSpan(String operationName) {
+ return new SpanBuilder(operationName);
}
@Override
@@ -218,7 +199,7 @@ public SpanBuilder asChildOf(SpanContext parent) {
}
@Override
- public SpanBuilder asChildOf(BaseSpan parent) {
+ public SpanBuilder asChildOf(Span parent) {
return addReference(References.CHILD_OF, parent.context());
}
@@ -262,14 +243,18 @@ public SpanBuilder withStartTimestamp(long microseconds) {
}
@Override
- public MockSpan start() {
- return startManual();
+ public Scope startActive() {
+ return MockTracer.this.scopeManager().activate(this.startManual());
}
@Override
- public ActiveSpan startActive() {
- MockSpan span = this.startManual();
- return spanSource.makeActive(span);
+ public Scope startActive(Scope.Observer observer) {
+ return MockTracer.this.scopeManager().activate(this.startManual(), observer);
+ }
+
+ @Override
+ public MockSpan start() {
+ return startManual();
}
@Override
@@ -278,7 +263,10 @@ public MockSpan startManual() {
this.startMicros = MockSpan.nowMicros();
}
if (firstParent == null && !ignoringActiveSpan) {
- firstParent = (MockSpan.MockContext) activeSpanContext();
+ Scope activeScope = scopeManager().active();
+ if (activeScope != null) {
+ firstParent = (MockSpan.MockContext) activeScope.span().context();
+ }
}
return new MockSpan(MockTracer.this, operationName, startMicros, initialTags, firstParent);
}
diff --git a/opentracing-mock/src/test/java/io/opentracing/mock/MockSpanTest.java b/opentracing-mock/src/test/java/io/opentracing/mock/MockSpanTest.java
index b488f657..22992a38 100644
--- a/opentracing-mock/src/test/java/io/opentracing/mock/MockSpanTest.java
+++ b/opentracing-mock/src/test/java/io/opentracing/mock/MockSpanTest.java
@@ -13,11 +13,10 @@
*/
package io.opentracing.mock;
+import io.opentracing.Span;
import org.junit.Assert;
import org.junit.Test;
-import io.opentracing.Span;
-
/**
* @author Pavol Loffay
*/
diff --git a/opentracing-noop/src/main/java/io/opentracing/noop/NoopActiveSpanSource.java b/opentracing-noop/src/main/java/io/opentracing/noop/NoopActiveSpanSource.java
deleted file mode 100644
index ddd150ce..00000000
--- a/opentracing-noop/src/main/java/io/opentracing/noop/NoopActiveSpanSource.java
+++ /dev/null
@@ -1,120 +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.noop;
-
-import io.opentracing.ActiveSpan;
-import io.opentracing.ActiveSpanSource;
-import io.opentracing.Span;
-import io.opentracing.SpanContext;
-
-import java.util.Map;
-
-public interface NoopActiveSpanSource extends ActiveSpanSource {
- NoopActiveSpanSource INSTANCE = new NoopActiveSpanSourceImpl();
-
- interface NoopActiveSpan extends ActiveSpan {
- NoopActiveSpanSource.NoopActiveSpan INSTANCE = new NoopActiveSpanSourceImpl.NoopActiveSpanImpl();
- }
- interface NoopContinuation extends ActiveSpan.Continuation {
- NoopActiveSpanSource.NoopContinuation INSTANCE = new NoopActiveSpanSourceImpl.NoopContinuationImpl();
- }
-}
-
-/**
- * A noop (i.e., cheap-as-possible) implementation of an ActiveSpanSource.
- */
-class NoopActiveSpanSourceImpl implements NoopActiveSpanSource {
- @Override
- public ActiveSpan makeActive(Span span) {
- return NoopActiveSpanSource.NoopActiveSpan.INSTANCE;
- }
-
- @Override
- public ActiveSpan activeSpan() { return null; }
-
- static class NoopActiveSpanImpl implements NoopActiveSpanSource.NoopActiveSpan {
- @Override
- public void deactivate() {}
-
- @Override
- public Continuation capture() {
- return NoopActiveSpanSource.NoopContinuation.INSTANCE;
- }
-
- @Override
- public SpanContext context() {
- return NoopSpanContextImpl.INSTANCE;
- }
-
- @Override
- public void close() {}
-
- @Override
- public NoopActiveSpan setTag(String key, String value) {
- return NoopActiveSpanSource.NoopActiveSpan.INSTANCE;
- }
-
- @Override
- public NoopActiveSpan setTag(String key, boolean value) {
- return NoopActiveSpanSource.NoopActiveSpan.INSTANCE;
- }
-
- @Override
- public NoopActiveSpan setTag(String key, Number value) {
- return NoopActiveSpanSource.NoopActiveSpan.INSTANCE;
- }
-
- @Override
- public NoopActiveSpan log(Map fields) {
- return NoopActiveSpanSource.NoopActiveSpan.INSTANCE;
- }
-
- @Override
- public NoopActiveSpan log(long timestampMicroseconds, Map fields) {
- return NoopActiveSpanSource.NoopActiveSpan.INSTANCE;
- }
-
- @Override
- public NoopActiveSpan log(String event) {
- return NoopActiveSpanSource.NoopActiveSpan.INSTANCE;
- }
-
- @Override
- public NoopActiveSpan log(long timestampMicroseconds, String event) {
- return NoopActiveSpanSource.NoopActiveSpan.INSTANCE;
- }
-
- @Override
- public NoopActiveSpan setBaggageItem(String key, String value) {
- return NoopActiveSpanSource.NoopActiveSpan.INSTANCE;
- }
-
- @Override
- public String getBaggageItem(String key) {
- return null;
- }
-
- @Override
- public NoopActiveSpan setOperationName(String operationName) {
- return NoopActiveSpanSource.NoopActiveSpan.INSTANCE;
- }
- }
-
- static class NoopContinuationImpl implements NoopActiveSpanSource.NoopContinuation {
- @Override
- public ActiveSpan activate() {
- return NoopActiveSpanSource.NoopActiveSpan.INSTANCE;
- }
- }
-}
diff --git a/opentracing-noop/src/main/java/io/opentracing/noop/NoopScopeManager.java b/opentracing-noop/src/main/java/io/opentracing/noop/NoopScopeManager.java
new file mode 100644
index 00000000..e9819663
--- /dev/null
+++ b/opentracing-noop/src/main/java/io/opentracing/noop/NoopScopeManager.java
@@ -0,0 +1,56 @@
+/*
+ * 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.noop;
+
+import io.opentracing.Scope;
+import io.opentracing.ScopeManager;
+import io.opentracing.Span;
+
+/**
+ * Created by bhs on 8/5/17.
+ */
+public interface NoopScopeManager extends ScopeManager {
+ NoopScopeManager INSTANCE = new NoopScopeManagerImpl();
+
+ interface NoopScope extends Scope {
+ NoopScope INSTANCE = new NoopScopeManagerImpl.NoopScopeImpl();
+ }
+}
+
+class NoopScopeManagerImpl implements NoopScopeManager {
+ @Override
+ public Scope activate(Span span) {
+ return NoopScope.INSTANCE;
+ }
+
+ @Override
+ public Scope activate(Span span, Scope.Observer scopeObserver) {
+ return NoopScope.INSTANCE;
+ }
+
+ @Override
+ public Scope active() {
+ return null;
+ }
+
+ static class NoopScopeImpl implements NoopScopeManager.NoopScope {
+ @Override
+ public void close() {}
+
+ @Override
+ public Span span() {
+ return NoopSpan.INSTANCE;
+ }
+ }
+}
diff --git a/opentracing-noop/src/main/java/io/opentracing/noop/NoopSpan.java b/opentracing-noop/src/main/java/io/opentracing/noop/NoopSpan.java
index 7d503066..1b44744c 100644
--- a/opentracing-noop/src/main/java/io/opentracing/noop/NoopSpan.java
+++ b/opentracing-noop/src/main/java/io/opentracing/noop/NoopSpan.java
@@ -13,13 +13,14 @@
*/
package io.opentracing.noop;
+import io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.SpanContext;
import java.util.Map;
public interface NoopSpan extends Span {
- static final NoopSpan INSTANCE = new NoopSpanImpl();
+ NoopSpan INSTANCE = new NoopSpanImpl();
}
final class NoopSpanImpl implements NoopSpan {
@@ -33,6 +34,16 @@ public void finish() {}
@Override
public void finish(long finishMicros) {}
+ @Override
+ public Scope activate() {
+ return NoopScopeManagerImpl.NoopScopeImpl.INSTANCE;
+ }
+
+ @Override
+ public Scope activate(Scope.Observer observer) {
+ return NoopScopeManagerImpl.NoopScopeImpl.INSTANCE;
+ }
+
@Override
public NoopSpan setTag(String key, String value) { return this; }
diff --git a/opentracing-noop/src/main/java/io/opentracing/noop/NoopSpanBuilder.java b/opentracing-noop/src/main/java/io/opentracing/noop/NoopSpanBuilder.java
index 06129830..71fac79b 100644
--- a/opentracing-noop/src/main/java/io/opentracing/noop/NoopSpanBuilder.java
+++ b/opentracing-noop/src/main/java/io/opentracing/noop/NoopSpanBuilder.java
@@ -13,8 +13,7 @@
*/
package io.opentracing.noop;
-import io.opentracing.ActiveSpan;
-import io.opentracing.BaseSpan;
+import io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.SpanContext;
import io.opentracing.Tracer;
@@ -42,7 +41,7 @@ public Tracer.SpanBuilder asChildOf(SpanContext parent) {
public Tracer.SpanBuilder ignoreActiveSpan() { return this; }
@Override
- public Tracer.SpanBuilder asChildOf(BaseSpan parent) {
+ public Tracer.SpanBuilder asChildOf(Span parent) {
return this;
}
@@ -67,13 +66,18 @@ public Tracer.SpanBuilder withStartTimestamp(long microseconds) {
}
@Override
- public Span start() {
- return startManual();
+ public Scope startActive() {
+ return NoopScopeManager.NoopScope.INSTANCE;
}
@Override
- public ActiveSpan startActive() {
- return NoopActiveSpanSource.NoopActiveSpan.INSTANCE;
+ public Scope startActive(Scope.Observer observer) {
+ return NoopScopeManager.NoopScope.INSTANCE;
+ }
+
+ @Override
+ public Span start() {
+ return startManual();
}
@Override
diff --git a/opentracing-noop/src/main/java/io/opentracing/noop/NoopTracer.java b/opentracing-noop/src/main/java/io/opentracing/noop/NoopTracer.java
index 678a302a..4d79b8bd 100644
--- a/opentracing-noop/src/main/java/io/opentracing/noop/NoopTracer.java
+++ b/opentracing-noop/src/main/java/io/opentracing/noop/NoopTracer.java
@@ -13,8 +13,7 @@
*/
package io.opentracing.noop;
-import io.opentracing.ActiveSpan;
-import io.opentracing.Span;
+import io.opentracing.ScopeManager;
import io.opentracing.SpanContext;
import io.opentracing.Tracer;
import io.opentracing.propagation.Format;
@@ -25,6 +24,15 @@ public interface NoopTracer extends Tracer {
final class NoopTracerImpl implements NoopTracer {
final static NoopTracer INSTANCE = new NoopTracerImpl();
+ @Override
+ public ScopeManager scopeManager() {
+ return null;
+ }
+
+ public void setScopeManager(ScopeManager scopeManager) {
+
+ }
+
@Override
public SpanBuilder buildSpan(String operationName) { return NoopSpanBuilderImpl.INSTANCE; }
@@ -36,15 +44,5 @@ public void inject(SpanContext spanContext, Format format, C carrier) {}
@Override
public String toString() { return NoopTracer.class.getSimpleName(); }
-
- @Override
- public ActiveSpan activeSpan() {
- return null;
- }
-
- @Override
- public ActiveSpan makeActive(Span span) {
- return NoopActiveSpanSource.NoopActiveSpan.INSTANCE;
- }
}
diff --git a/opentracing-usecases/pom.xml b/opentracing-usecases/pom.xml
new file mode 100644
index 00000000..8faccb33
--- /dev/null
+++ b/opentracing-usecases/pom.xml
@@ -0,0 +1,50 @@
+
+
+
+4.0.0
+
+
+ io.opentracing
+ parent
+ 0.30.1-SNAPSHOT
+
+
+opentracing-usecases
+OpenTracing-UseCases
+OpenTracing use cases for new API/feature development
+
+
+ ${project.basedir}/..
+ 1.8
+
+
+
+
+ ${project.groupId}
+ opentracing-api
+
+
+ ${project.groupId}
+ opentracing-util
+
+
+ ${project.groupId}
+ opentracing-mock
+ test
+
+
+
diff --git a/opentracing-usecases/src/main/java/io/opentracing/usecases/AutoFinishScopeManager.java b/opentracing-usecases/src/main/java/io/opentracing/usecases/AutoFinishScopeManager.java
new file mode 100644
index 00000000..33e1f5f3
--- /dev/null
+++ b/opentracing-usecases/src/main/java/io/opentracing/usecases/AutoFinishScopeManager.java
@@ -0,0 +1,77 @@
+/*
+ * 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.usecases;
+
+import io.opentracing.Scope;
+import io.opentracing.ScopeManager;
+import io.opentracing.Span;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Created by bhs on 8/5/17.
+ */
+public class AutoFinishScopeManager implements ScopeManager {
+ final ThreadLocal tlsScope = new ThreadLocal();
+
+ @Override
+ public AutoFinishScope activate(Span span) {
+ return new AutoFinishScope(new AtomicInteger(1), span);
+ }
+
+ @Override
+ public AutoFinishScope active() {
+ return tlsScope.get();
+ }
+
+ public class AutoFinishScope implements Scope {
+ final AtomicInteger refCount;
+ private final Span wrapped;
+ private final AutoFinishScope toRestore;
+
+ AutoFinishScope(AtomicInteger refCount, Span wrapped) {
+ this.refCount = refCount;
+ this.wrapped = wrapped;
+ this.toRestore = AutoFinishScopeManager.this.tlsScope.get();
+ tlsScope.set(this);
+ }
+
+ public class Continuation {
+ public Continuation() {
+ refCount.incrementAndGet();
+ }
+
+ public AutoFinishScope activate() {
+ return new AutoFinishScope(refCount, wrapped);
+ }
+ }
+
+ public Continuation defer() {
+ return new Continuation();
+ }
+
+ @Override
+ public void close() {
+ if (refCount.decrementAndGet() == 0) {
+ wrapped.finish();
+ }
+ tlsScope.set(toRestore);
+ }
+
+ @Override
+ public Span span() {
+ return wrapped;
+ }
+ }
+}
diff --git a/opentracing-usecases/src/test/java/io/opentracing/usecases/AutoFinishScopeManagerTest.java b/opentracing-usecases/src/test/java/io/opentracing/usecases/AutoFinishScopeManagerTest.java
new file mode 100644
index 00000000..e244da91
--- /dev/null
+++ b/opentracing-usecases/src/test/java/io/opentracing/usecases/AutoFinishScopeManagerTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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.usecases;
+
+import io.opentracing.Scope;
+import io.opentracing.Span;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+public class AutoFinishScopeManagerTest {
+ private AutoFinishScopeManager autoFinishActivator;
+
+ @Before
+ public void before() throws Exception {
+ autoFinishActivator = new AutoFinishScopeManager();
+ }
+
+ @Test
+ public void missingActiveSpan() throws Exception {
+ Scope missingScope = autoFinishActivator.active();
+ Assert.assertNull(missingScope);
+ }
+
+ @Test
+ public void makeActiveSpan() throws Exception {
+ Span span = Mockito.mock(Span.class);
+
+ try (AutoFinishScopeManager.AutoFinishScope scope = autoFinishActivator.activate(span)) {
+ Assert.assertNotNull(scope);
+ Scope otherScope = autoFinishActivator.active();
+ Assert.assertEquals(otherScope, scope);
+ }
+
+ // Make sure the Span got finish()ed.
+ Mockito.verify(span).finish();
+
+ // And now it's gone:
+ Scope missingScope = autoFinishActivator.active();
+ Assert.assertNull(missingScope);
+ }
+
+ @Test
+ public void deferring() throws Exception {
+ Span span = Mockito.mock(Span.class);
+
+ AutoFinishScopeManager.AutoFinishScope.Continuation continuation = null;
+ {
+ // We can't use 1.7 features like try-with-resources in this repo without meddling with pom details for tests.
+ try (AutoFinishScopeManager.AutoFinishScope scope = autoFinishActivator.activate(span)) {
+ // Take a reference...
+ continuation = scope.defer();
+ Assert.assertNotNull(scope);
+ Scope otherScope = autoFinishActivator.active();
+ Assert.assertEquals(otherScope, scope);
+ }
+ }
+
+ // Make sure the Span has not been finish()ed yet.
+ Mockito.verify(span, Mockito.never()).finish();
+
+ // Activate the Continuation and close that second reference.
+ try (AutoFinishScopeManager.AutoFinishScope reactivated = continuation.activate()) {
+ // Nothing to do.
+ }
+
+ // Make sure the Span got finish()ed this time.
+ Mockito.verify(span).finish();
+
+ // And now it's gone:
+ Scope missingScope = autoFinishActivator.active();
+ Assert.assertNull(missingScope);
+ }
+
+}
diff --git a/opentracing-util/src/main/java/io/opentracing/util/GlobalTracer.java b/opentracing-util/src/main/java/io/opentracing/util/GlobalTracer.java
index 89b6f073..a1f49be4 100644
--- a/opentracing-util/src/main/java/io/opentracing/util/GlobalTracer.java
+++ b/opentracing-util/src/main/java/io/opentracing/util/GlobalTracer.java
@@ -13,10 +13,9 @@
*/
package io.opentracing.util;
-import io.opentracing.ActiveSpan;
+import io.opentracing.ScopeManager;
import io.opentracing.noop.NoopTracer;
import io.opentracing.noop.NoopTracerFactory;
-import io.opentracing.Span;
import io.opentracing.SpanContext;
import io.opentracing.Tracer;
import io.opentracing.propagation.Format;
@@ -123,6 +122,15 @@ public static synchronized boolean isRegistered() {
return !(GlobalTracer.tracer instanceof NoopTracer);
}
+ @Override
+ public ScopeManager scopeManager() {
+ return tracer.scopeManager();
+ }
+
+ public void setScopeManager(ScopeManager scopeManager) {
+ tracer.setScopeManager(scopeManager);
+ }
+
@Override
public SpanBuilder buildSpan(String operationName) {
return tracer.buildSpan(operationName);
@@ -142,14 +150,4 @@ public SpanContext extract(Format format, C carrier) {
public String toString() {
return GlobalTracer.class.getSimpleName() + '{' + tracer + '}';
}
-
- @Override
- public ActiveSpan activeSpan() {
- return tracer.activeSpan();
- }
-
- @Override
- public ActiveSpan makeActive(Span span) {
- return tracer.makeActive(span);
- }
}
diff --git a/opentracing-util/src/main/java/io/opentracing/util/ThreadLocalActiveSpan.java b/opentracing-util/src/main/java/io/opentracing/util/ThreadLocalActiveSpan.java
deleted file mode 100644
index ba90ca43..00000000
--- a/opentracing-util/src/main/java/io/opentracing/util/ThreadLocalActiveSpan.java
+++ /dev/null
@@ -1,149 +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.util;
-
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import io.opentracing.ActiveSpan;
-import io.opentracing.ActiveSpanSource;
-import io.opentracing.Span;
-import io.opentracing.SpanContext;
-import io.opentracing.Tracer;
-
-/**
- * {@link ThreadLocalActiveSpan} is a simple {@link ActiveSpan} implementation that relies on Java's
- * thread-local storage primitive.
- *
- * @see ActiveSpanSource
- * @see Tracer#activeSpan()
- */
-public class ThreadLocalActiveSpan implements ActiveSpan {
- private final ThreadLocalActiveSpanSource source;
- private final Span wrapped;
- private final ThreadLocalActiveSpan toRestore;
- private final AtomicInteger refCount;
-
- ThreadLocalActiveSpan(ThreadLocalActiveSpanSource source, Span wrapped, AtomicInteger refCount) {
- this.source = source;
- this.refCount = refCount;
- this.wrapped = wrapped;
- this.toRestore = source.tlsSnapshot.get();
- source.tlsSnapshot.set(this);
- }
-
- @Override
- public void deactivate() {
- if (source.tlsSnapshot.get() != this) {
- // This shouldn't happen if users call methods in the expected order. Bail out.
- return;
- }
- source.tlsSnapshot.set(toRestore);
-
- if (0 == refCount.decrementAndGet()) {
- wrapped.finish();
- }
- }
-
- @Override
- public Continuation capture() {
- return new ThreadLocalActiveSpan.Continuation();
- }
-
- @Override
- public SpanContext context() {
- return wrapped.context();
- }
-
- @Override
- public ThreadLocalActiveSpan setTag(String key, String value) {
- wrapped.setTag(key, value);
- return this;
- }
-
- @Override
- public ThreadLocalActiveSpan setTag(String key, boolean value) {
- wrapped.setTag(key, value);
- return this;
- }
-
- @Override
- public ThreadLocalActiveSpan setTag(String key, Number value) {
- wrapped.setTag(key, value);
- return this;
- }
-
- @Override
- public ThreadLocalActiveSpan log(Map fields) {
- wrapped.log(fields);
- return this;
- }
-
- @Override
- public ThreadLocalActiveSpan log(long timestampMicroseconds, Map fields) {
- wrapped.log(timestampMicroseconds, fields);
- return this;
- }
-
- @Override
- public ThreadLocalActiveSpan log(String event) {
- wrapped.log(event);
- return this;
- }
-
- @Override
- public ThreadLocalActiveSpan log(long timestampMicroseconds, String event) {
- wrapped.log(timestampMicroseconds, event);
- return this;
- }
-
- @Override
- public ThreadLocalActiveSpan setBaggageItem(String key, String value) {
- wrapped.setBaggageItem(key, value);
- return this;
- }
-
- @Override
- public String getBaggageItem(String key) {
- return wrapped.getBaggageItem(key);
- }
-
- @Override
- public ThreadLocalActiveSpan setOperationName(String operationName) {
- wrapped.setOperationName(operationName);
- return this;
- }
-
- @Override
- public void close() {
- deactivate();
- }
-
- @Override
- public String toString() {
- return wrapped.toString();
- }
-
- private final class Continuation implements ActiveSpan.Continuation {
- Continuation() {
- refCount.incrementAndGet();
- }
-
- @Override
- public ThreadLocalActiveSpan activate() {
- return new ThreadLocalActiveSpan(source, wrapped, refCount);
- }
- }
-
-}
diff --git a/opentracing-util/src/main/java/io/opentracing/util/ThreadLocalActiveSpanSource.java b/opentracing-util/src/main/java/io/opentracing/util/ThreadLocalActiveSpanSource.java
deleted file mode 100644
index 2cd7e6e2..00000000
--- a/opentracing-util/src/main/java/io/opentracing/util/ThreadLocalActiveSpanSource.java
+++ /dev/null
@@ -1,42 +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.util;
-
-import io.opentracing.ActiveSpan;
-import io.opentracing.ActiveSpanSource;
-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();
-
- @Override
- public ThreadLocalActiveSpan activeSpan() {
- return tlsSnapshot.get();
- }
-
- @Override
- public ActiveSpan makeActive(Span span) {
- return new ThreadLocalActiveSpan(this, span, new AtomicInteger(1));
- }
-
-}
diff --git a/opentracing-util/src/main/java/io/opentracing/util/ThreadLocalScopeManager.java b/opentracing-util/src/main/java/io/opentracing/util/ThreadLocalScopeManager.java
new file mode 100644
index 00000000..b6511f57
--- /dev/null
+++ b/opentracing-util/src/main/java/io/opentracing/util/ThreadLocalScopeManager.java
@@ -0,0 +1,69 @@
+/*
+ * 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.util;
+
+import io.opentracing.Scope;
+import io.opentracing.ScopeManager;
+import io.opentracing.Span;
+
+/**
+ * Created by bhs on 8/1/17.
+ */
+public class ThreadLocalScopeManager implements ScopeManager {
+ final ThreadLocal tlsScope = new ThreadLocal();
+
+ public class ThreadLocalScope implements Scope {
+ private final Span wrapped;
+ private final ThreadLocalScope toRestore;
+ private final Scope.Observer scopeObserver;
+
+ ThreadLocalScope(Span wrapped, Scope.Observer scopeObserver) {
+ this.wrapped = wrapped;
+ this.toRestore = ThreadLocalScopeManager.this.tlsScope.get();
+ this.scopeObserver = scopeObserver;
+ tlsScope.set(this);
+ if (this.scopeObserver != null) {
+ this.scopeObserver.onActivate(this);
+ }
+ }
+
+ @Override
+ public void close() {
+ if (this.scopeObserver != null) {
+ this.scopeObserver.onClose(this);
+ }
+ tlsScope.set(toRestore);
+ }
+
+ @Override
+ public Span span() {
+ return wrapped;
+ }
+ }
+
+ @Override
+ public Scope activate(Span span) {
+ return new ThreadLocalScope(span, null);
+ }
+
+ @Override
+ public Scope activate(Span span, Scope.Observer scopeObserver) {
+ return new ThreadLocalScope(span, scopeObserver);
+ }
+
+ @Override
+ public Scope active() {
+ return tlsScope.get();
+ }
+}
diff --git a/opentracing-util/src/test/java/io/opentracing/util/ThreadLocalActiveSpanTest.java b/opentracing-util/src/test/java/io/opentracing/util/ThreadLocalActiveSpanTest.java
deleted file mode 100644
index 06d49093..00000000
--- a/opentracing-util/src/test/java/io/opentracing/util/ThreadLocalActiveSpanTest.java
+++ /dev/null
@@ -1,114 +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.util;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import io.opentracing.ActiveSpan;
-import io.opentracing.Span;
-import org.junit.Before;
-import org.junit.Test;
-
-public class ThreadLocalActiveSpanTest {
- private ThreadLocalActiveSpanSource source;
-
- @Before
- public void before() throws Exception {
- source = new ThreadLocalActiveSpanSource();
- }
-
- @Test
- public void continuation() throws Exception {
- Span span = mock(Span.class);
-
- // Quasi try-with-resources (this is 1.6).
- ActiveSpan activeSpan = source.makeActive(span);
- ActiveSpan.Continuation continued = null;
- try {
- assertNotNull(activeSpan);
- continued = activeSpan.capture();
- } finally {
- activeSpan.close();
- }
-
- // Make sure the Span was not finished since there was a capture().
- verify(span, never()).finish();
-
- // Activate the continuation.
- try {
- activeSpan = continued.activate();
- } finally {
- activeSpan.close();
- }
-
- // Now the Span should be finished.
- verify(span, times(1)).finish();
-
- // And now it's no longer active.
- ActiveSpan missingSpan = source.activeSpan();
- assertNull(missingSpan);
- }
-
- @Test
- public void implicitSpanStack() throws Exception {
- Span backgroundSpan = mock(Span.class);
- Span foregroundSpan = mock(Span.class);
-
- // Quasi try-with-resources (this is 1.6).
- ActiveSpan backgroundActive = source.makeActive(backgroundSpan);
- try {
- assertNotNull(backgroundActive);
-
- // Activate a new ActiveSpan on top of the background one.
- ActiveSpan foregroundActive = source.makeActive(foregroundSpan);
- try {
- ActiveSpan shouldBeForeground = source.activeSpan();
- assertEquals(foregroundActive, shouldBeForeground);
- } finally {
- foregroundActive.close();
- }
-
- // And now the backgroundActive should be reinstated.
- ActiveSpan shouldBeBackground = source.activeSpan();
- assertEquals(backgroundActive, shouldBeBackground);
- } finally {
- backgroundActive.close();
- }
-
- // The background and foreground Spans should be finished.
- verify(backgroundSpan, times(1)).finish();
- verify(foregroundSpan, times(1)).finish();
-
- // And now nothing is active.
- ActiveSpan missingSpan = source.activeSpan();
- assertNull(missingSpan);
- }
-
- @Test
- public void testDeactivateWhenDifferentSpanIsActive() {
- Span span = mock(Span.class);
-
- ActiveSpan activeSpan = source.makeActive(span);
- source.makeActive(mock(Span.class));
- activeSpan.deactivate();
-
- verify(span, times(0)).finish();
- }
-}
diff --git a/opentracing-util/src/test/java/io/opentracing/util/ThreadLocalActiveSpanSourceTest.java b/opentracing-util/src/test/java/io/opentracing/util/ThreadLocalScopeManagerTest.java
similarity index 67%
rename from opentracing-util/src/test/java/io/opentracing/util/ThreadLocalActiveSpanSourceTest.java
rename to opentracing-util/src/test/java/io/opentracing/util/ThreadLocalScopeManagerTest.java
index 180662ee..5fd527a8 100644
--- a/opentracing-util/src/test/java/io/opentracing/util/ThreadLocalActiveSpanSourceTest.java
+++ b/opentracing-util/src/test/java/io/opentracing/util/ThreadLocalScopeManagerTest.java
@@ -13,26 +13,28 @@
*/
package io.opentracing.util;
-import io.opentracing.ActiveSpan;
+import io.opentracing.Scope;
import io.opentracing.Span;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
-public class ThreadLocalActiveSpanSourceTest {
- private ThreadLocalActiveSpanSource source;
+public class ThreadLocalScopeManagerTest {
+ private ThreadLocalScopeManager source;
+
@Before
public void before() throws Exception {
- source = new ThreadLocalActiveSpanSource();
+ source = new ThreadLocalScopeManager();
}
@Test
public void missingActiveSpan() throws Exception {
- ActiveSpan missingSpan = source.activeSpan();
- assertNull(missingSpan);
+ Scope missingScope = source.active();
+ assertNull(missingScope);
}
@Test
@@ -40,21 +42,21 @@ public void makeActiveSpan() throws Exception {
Span span = mock(Span.class);
// We can't use 1.7 features like try-with-resources in this repo without meddling with pom details for tests.
- ActiveSpan activeSpan = source.makeActive(span);
+ Scope scope = source.activate(span);
try {
- assertNotNull(activeSpan);
- ActiveSpan otherActiveSpan = source.activeSpan();
- assertEquals(otherActiveSpan, activeSpan);
+ assertNotNull(scope);
+ Scope otherScope = source.active();
+ assertEquals(otherScope, scope);
} finally {
- activeSpan.close();
+ scope.close();
}
// Make sure the Span got finish()ed.
- verify(span).finish();
+ verify(span, never()).finish();
// And now it's gone:
- ActiveSpan missingSpan = source.activeSpan();
- assertNull(missingSpan);
+ Scope missingScope = source.active();
+ assertNull(missingScope);
}
-}
\ No newline at end of file
+}
diff --git a/pom.xml b/pom.xml
index a2e5e1af..e68a7c0a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -27,6 +27,7 @@
opentracing-noop
opentracing-mock
opentracing-util
+ opentracing-usecases