Skip to content

Commit

Permalink
Adds finagle interop example
Browse files Browse the repository at this point in the history
  • Loading branch information
Adrian Cole committed Mar 22, 2017
1 parent a66e0d0 commit c05fc37
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 2 deletions.
2 changes: 1 addition & 1 deletion brave-benchmarks/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
<dependency>
<groupId>com.twitter</groupId>
<artifactId>finagle-core_2.12</artifactId>
<version>6.41.0</version>
<version>${finagle.version}</version>
</dependency>
</dependencies>

Expand Down
6 changes: 6 additions & 0 deletions brave/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -78,5 +78,11 @@
<version>${grpc.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.twitter</groupId>
<artifactId>finagle-core_2.12</artifactId>
<version>${finagle.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
2 changes: 1 addition & 1 deletion brave/src/main/java/brave/Tracer.java
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ public Span newTrace(SamplingFlags samplingFlags) {
/** Converts the context as-is to a Span object */
public Span toSpan(TraceContext context) {
if (context == null) throw new NullPointerException("context == null");
if (context.sampled()) {
if (context.sampled() == null || context.sampled()) {
return RealSpan.create(context, clock, recorder);
}
return NoopSpan.create(context);
Expand Down
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)
);
}
}
4 changes: 4 additions & 0 deletions brave/src/test/java/brave/features/finagle/package-info.java
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;
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
<jetty.version>8.1.22.v20160922</jetty.version>
<zipkin.version>1.19.2</zipkin.version>
<zipkin-reporter.version>0.6.12</zipkin-reporter.version>
<finagle.version>6.43.0</finagle.version>
<log4j.version>2.8.1</log4j.version>
<okhttp.version>3.5.0</okhttp.version>
<grpc.version>1.0.3</grpc.version>
Expand Down

0 comments on commit c05fc37

Please sign in to comment.