Skip to content
This repository has been archived by the owner on May 23, 2023. It is now read-only.

Add Span#unwrap #211

Open
wants to merge 3 commits into
base: v0.31.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions opentracing-api/src/main/java/io/opentracing/Span.java
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
* <p> Using this method is highly preferred to type casts, especially because there might be a hierarchy of wrapper
* objects. </p>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

based on the two implementations (Mock and Noop), not clear how this is different from cast - is the intention that wrappers will override this method?

Copy link
Contributor Author

@felixbarny felixbarny Nov 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, a wrapper's implementation might look like this:

public <T extends Span> T unwrap(Class<T> clazz) {
	if (clazz.isInstance(this)) {
		return clazz.cast(this);
	} else {
		return delegate.unwrap(clazz);
	}
}

where delegate is a Span instance variable

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or, if Java 8+ is the baseline, the interface can implement a basic unwrap routine, freeing up implementations to have code that would be mostly duplicated.

*
* <p> If the class implementing this interface is an instance of the provided class, the <code>this</code>
* reference is returned. Otherwise, if the receiver is a wrapper, return the the result of calling
* <code>unwrap</code> recursively on the wrapped object. If the receiver is not a wrapper and is not an instance of
* the provided class, then <code>null</code> is returned.</p>
*
* @param clazz The Class that the result must be an instance of.
* @return an object that is an instance of the provided class, or <code>null</code> if there is no such class in
* the wrapper hierarchy.
*/
<T extends Span> T unwrap(java.lang.Class<T> clazz);
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,15 @@ public synchronized void finish(long finishMicros) {
this.finished = true;
}

@Override
public <T extends Span> T unwrap(Class<T> clazz) {
if (clazz.isInstance(this)) {
return clazz.cast(this);
} else {
return null;
}
}

@Override
public MockSpan setTag(String key, String value) {
return setObjectTag(key, value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import org.junit.Test;

import io.opentracing.Span;
import io.opentracing.Tracer;
import io.opentracing.noop.NoopSpan;

/**
* @author Pavol Loffay
Expand Down Expand Up @@ -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));
}
}
13 changes: 11 additions & 2 deletions opentracing-noop/src/main/java/io/opentracing/noop/NoopSpan.java
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand All @@ -33,6 +33,15 @@ public void finish() {}
@Override
public void finish(long finishMicros) {}

@Override
public <T extends Span> T unwrap(Class<T> clazz) {
if (clazz.isInstance(this)) {
return clazz.cast(this);
} else {
return null;
}
}

@Override
public NoopSpan setTag(String key, String value) { return this; }

Expand Down