-
Notifications
You must be signed in to change notification settings - Fork 719
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Adrian Cole
committed
Mar 22, 2017
1 parent
a66e0d0
commit c05fc37
Showing
6 changed files
with
135 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
122 changes: 122 additions & 0 deletions
122
brave/src/test/java/brave/features/finagle/FinagleTraceInteropTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
package brave.features.finagle; | ||
|
||
import brave.Span; | ||
import brave.Tracer; | ||
import brave.propagation.SpanScoper; | ||
import brave.propagation.TraceContext; | ||
import com.twitter.finagle.context.MarshalledContext; | ||
import com.twitter.finagle.tracing.Flags$; | ||
import com.twitter.finagle.tracing.SpanId; | ||
import com.twitter.finagle.tracing.Trace; | ||
import com.twitter.finagle.tracing.Trace$; | ||
import com.twitter.finagle.tracing.TraceId; | ||
import com.twitter.io.Buf; | ||
import com.twitter.util.Local; | ||
import java.lang.reflect.Field; | ||
import org.junit.Test; | ||
import scala.Option; | ||
import scala.Some; | ||
import scala.collection.immutable.Map; | ||
import scala.runtime.AbstractFunction0; | ||
|
||
import static com.twitter.finagle.context.Contexts.broadcast; | ||
import static org.assertj.core.api.Assertions.assertThat; | ||
|
||
public class FinagleTraceInteropTest { | ||
|
||
@Test public void finagleBraveInterop() throws Exception { | ||
Tracer tracer = Tracer.newBuilder().spanScoper(new FinagleSpanScoper()).build(); | ||
|
||
Span parent = tracer.newTrace(); // start a trace in Brave | ||
try (SpanScoper.SpanInScope wsParent = tracer.withSpan(parent)) { | ||
// Inside the parent scope, trace context is consistent between finagle and brave | ||
assertThat(tracer.currentSpan().context().spanId()) | ||
.isEqualTo(Trace.id().spanId().self()); | ||
|
||
// create a child in finagle | ||
Trace.letId(Trace.nextId(), false, new AbstractFunction0<Void>() { | ||
@Override public Void apply() { | ||
// Inside the child scope, trace context is consistent between finagle and brave | ||
assertThat(tracer.currentSpan().context().spanId()) | ||
.isEqualTo(Trace.id().spanId().self()); | ||
|
||
// The child span has the correct parent (consistent between finagle and brave) | ||
assertThat(tracer.currentSpan().context().parentId()) | ||
.isEqualTo(parent.context().spanId()) | ||
.isEqualTo(Trace.id().parentId().self()); | ||
|
||
return null; | ||
} | ||
}); | ||
|
||
// After leaving the child scope, trace context is consistent between finagle and brave | ||
assertThat(tracer.currentSpan().context().spanId()) | ||
.isEqualTo(Trace.id().spanId().self()); | ||
|
||
// The parent span was reverted | ||
assertThat(tracer.currentSpan().context().spanId()) | ||
.isEqualTo(parent.context().spanId()) | ||
.isEqualTo(Trace.id().spanId().self()); | ||
} | ||
|
||
// Outside a scope, trace context is consistent between finagle and brave | ||
assertThat(tracer.currentSpan()).isNull(); | ||
assertThat(Trace.idOption().isDefined()).isFalse(); | ||
} | ||
|
||
/** | ||
* In Finagle, let forms are used to apply an trace context to a function. This is implemented | ||
* under the scenes by a try-finally block using {@link Local#set(Option)}. The below code uses | ||
* this detail to allow interop between finagle and {@link SpanScoper}. | ||
*/ | ||
static class FinagleSpanScoper implements SpanScoper { | ||
static final MarshalledContext.Key<TraceId> TRACE_ID_KEY = Trace$.MODULE$.idCtx(); | ||
|
||
final Local broadcastLocal; | ||
|
||
FinagleSpanScoper() throws NoSuchFieldException, IllegalAccessException { | ||
Field field = MarshalledContext.class.getDeclaredField("local"); | ||
field.setAccessible(true); | ||
this.broadcastLocal = (Local) field.get(broadcast()); | ||
} | ||
|
||
@Override public TraceContext currentSpan() { | ||
Option<TraceId> option = broadcast().get(Trace$.MODULE$.idCtx()); | ||
if (option.isEmpty()) return null; | ||
return toTraceContext(option.get()); | ||
} | ||
|
||
@Override public SpanInScope open(TraceContext currentSpan) { | ||
Map<Buf, MarshalledContext.Cell> saved = broadcast().env(); | ||
Map<Buf, MarshalledContext.Cell> update = broadcast().env().updated( | ||
TRACE_ID_KEY.marshalId(), | ||
broadcast().Real().apply(TRACE_ID_KEY, new Some(toTraceId(currentSpan))) | ||
); | ||
broadcastLocal.set(new Some(update)); | ||
return () -> { | ||
broadcastLocal.set(new Some(saved)); | ||
}; | ||
} | ||
} | ||
|
||
static TraceContext toTraceContext(TraceId id) { | ||
return TraceContext.newBuilder() | ||
.traceId(id.traceId().self()) | ||
.parentId(id._parentId().isEmpty() ? null : id.parentId().self()) | ||
.spanId(id.spanId().self()) | ||
.sampled(id.getSampled().isEmpty() ? null : id.getSampled().get()) | ||
.debug(id.flags().isDebug()) | ||
// .shared(isn't known in finagle) | ||
.build(); | ||
} | ||
|
||
static TraceId toTraceId(TraceContext context) { | ||
return new TraceId( | ||
Option.apply(SpanId.apply(context.traceId())), | ||
Option.apply(context.parentId() == null ? null : SpanId.apply(context.parentId())), | ||
SpanId.apply(context.spanId()), | ||
Option.apply(context.sampled()), | ||
Flags$.MODULE$.apply(context.debug() ? 1 : 0) | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
/** | ||
* This shows how you can reuse finagle's trace context in Brave | ||
*/ | ||
package brave.features.finagle; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters