diff --git a/opentracing-api/src/main/java/io/opentracing/Span.java b/opentracing-api/src/main/java/io/opentracing/Span.java
index 548ac4f8..f515a064 100644
--- a/opentracing-api/src/main/java/io/opentracing/Span.java
+++ b/opentracing-api/src/main/java/io/opentracing/Span.java
@@ -161,4 +161,21 @@ public interface Span {
* @see Span#context()
*/
void finish(long finishMicros);
+
+ /**
+ * Returns an object that is an instance of the given class to allow access to non-standard methods.
+ *
+ *
Using this method is highly preferred to type casts, especially because there might be a hierarchy of wrapper
+ * objects.
+ *
+ * If the class implementing this interface is an instance of the provided class, the this
+ * reference is returned. Otherwise, if the receiver is a wrapper, return the the result of calling
+ * unwrap
recursively on the wrapped object. If the receiver is not a wrapper and is not an instance of
+ * the provided class, then null
is returned.
+ *
+ * @param clazz The Class that the result must be an instance of.
+ * @return an object that is an instance of the provided class, or null
if there is no such class in
+ * the wrapper hierarchy.
+ */
+ T unwrap(java.lang.Class clazz);
}
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..ffd7f6e6 100644
--- a/opentracing-mock/src/main/java/io/opentracing/mock/MockSpan.java
+++ b/opentracing-mock/src/main/java/io/opentracing/mock/MockSpan.java
@@ -115,6 +115,15 @@ public synchronized void finish(long finishMicros) {
this.finished = true;
}
+ @Override
+ public T unwrap(Class clazz) {
+ if (clazz.isInstance(this)) {
+ return clazz.cast(this);
+ } else {
+ return null;
+ }
+ }
+
@Override
public MockSpan setTag(String key, String value) {
return setObjectTag(key, value);
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..b258b8ac 100644
--- a/opentracing-mock/src/test/java/io/opentracing/mock/MockSpanTest.java
+++ b/opentracing-mock/src/test/java/io/opentracing/mock/MockSpanTest.java
@@ -17,6 +17,8 @@
import org.junit.Test;
import io.opentracing.Span;
+import io.opentracing.Tracer;
+import io.opentracing.noop.NoopSpan;
/**
* @author Pavol Loffay
@@ -78,4 +80,18 @@ public void testAddBaggageAfterFinish() {
}
Assert.assertEquals(1, tracer.finishedSpans().get(0).generatedErrors().size());
}
+
+ @Test
+ public void testUnwrap() throws Exception {
+ Tracer tracer = new MockTracer();
+ Span span = tracer.buildSpan("foo").startManual();
+ Assert.assertSame(span, span.unwrap(MockSpan.class));
+ }
+
+ @Test
+ public void testUnwrapWrongInstance() throws Exception {
+ Tracer tracer = new MockTracer();
+ Span span = tracer.buildSpan("foo").startManual();
+ Assert.assertNull(span.unwrap(NoopSpan.class));
+ }
}
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..ec09dca7 100644
--- a/opentracing-noop/src/main/java/io/opentracing/noop/NoopSpan.java
+++ b/opentracing-noop/src/main/java/io/opentracing/noop/NoopSpan.java
@@ -13,11 +13,11 @@
*/
package io.opentracing.noop;
+import java.util.Map;
+
import io.opentracing.Span;
import io.opentracing.SpanContext;
-import java.util.Map;
-
public interface NoopSpan extends Span {
static final NoopSpan INSTANCE = new NoopSpanImpl();
}
@@ -33,6 +33,15 @@ public void finish() {}
@Override
public void finish(long finishMicros) {}
+ @Override
+ public T unwrap(Class clazz) {
+ if (clazz.isInstance(this)) {
+ return clazz.cast(this);
+ } else {
+ return null;
+ }
+ }
+
@Override
public NoopSpan setTag(String key, String value) { return this; }