aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/build.gradle4
-rw-r--r--core/pom.xml15
-rw-r--r--core/src/main/java/com/google/instrumentation/trace/ContextSpanHandler.java38
-rw-r--r--core/src/main/java/com/google/instrumentation/trace/ContextUtils.java75
-rw-r--r--core/src/main/java/com/google/instrumentation/trace/ScopedSpanHandle.java5
-rw-r--r--core/src/main/java/com/google/instrumentation/trace/SpanBuilder.java47
-rw-r--r--core/src/main/java/com/google/instrumentation/trace/Tracer.java128
-rw-r--r--core/src/test/java/com/google/instrumentation/trace/ContextUtilsTest.java87
-rw-r--r--core/src/test/java/com/google/instrumentation/trace/ScopedSpanHandleTest.java18
-rw-r--r--core/src/test/java/com/google/instrumentation/trace/SpanBuilderTest.java42
-rw-r--r--core/src/test/java/com/google/instrumentation/trace/TracerTest.java134
11 files changed, 339 insertions, 254 deletions
diff --git a/core/build.gradle b/core/build.gradle
index da14e524..067b34c1 100644
--- a/core/build.gradle
+++ b/core/build.gradle
@@ -2,9 +2,11 @@ description = 'Instrumentation: Core'
dependencies {
compile project(':shared'),
+ libraries.grpc_context,
libraries.guava,
libraries.errorprone,
libraries.jsr305
- testCompile project(':instrumentation-core-impl')
+ testCompile project(':instrumentation-core-impl'),
+ libraries.grpc_context
}
diff --git a/core/pom.xml b/core/pom.xml
index 5a623297..b8bcf678 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -16,6 +16,15 @@
<version>0.1.0-SNAPSHOT</version>
</parent>
+ <dependencies>
+ <dependency>
+ <groupId>com.google.io</groupId>
+ <artifactId>shared</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
<build>
<plugins>
<plugin>
@@ -30,10 +39,12 @@
</goals>
<configuration>
<!--
- Don't build the tests, because they currently create a circular
+ Don't build the stats tests, because they currently create a circular
dependency between the 'core' and 'core_impl' directories.
-->
- <skip>true</skip>
+ <testExcludes>
+ <exclude>**/stats/*.java</exclude>
+ </testExcludes>
</configuration>
</execution>
</executions>
diff --git a/core/src/main/java/com/google/instrumentation/trace/ContextSpanHandler.java b/core/src/main/java/com/google/instrumentation/trace/ContextSpanHandler.java
deleted file mode 100644
index c7eac797..00000000
--- a/core/src/main/java/com/google/instrumentation/trace/ContextSpanHandler.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2017, Google Inc.
- * 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 com.google.instrumentation.trace;
-
-import com.google.instrumentation.common.NonThrowingCloseable;
-
-/** Class to assist in {@link Span}/Context interactions. */
-abstract class ContextSpanHandler {
- /**
- * Returns The {@link Span} from the current context.
- *
- * @return The {@code Span} from the current context.
- */
- abstract Span getCurrentSpan();
-
- /**
- * Enters the scope of code where the given {@link Span} is in the current context, and returns an
- * object that represents that scope. The scope is exited when the returned object is closed.
- *
- * <p>Supports try-with-resource idiom.
- *
- * @param span The {@code Span} to be set to the current context.
- * @return An object that defines a scope where the given {@code Span} will be set to the current
- * context.
- */
- abstract NonThrowingCloseable withSpan(Span span);
-}
diff --git a/core/src/main/java/com/google/instrumentation/trace/ContextUtils.java b/core/src/main/java/com/google/instrumentation/trace/ContextUtils.java
new file mode 100644
index 00000000..bab9c189
--- /dev/null
+++ b/core/src/main/java/com/google/instrumentation/trace/ContextUtils.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2017, Google Inc.
+ * 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 com.google.instrumentation.trace;
+
+import com.google.instrumentation.common.NonThrowingCloseable;
+import io.grpc.Context;
+
+/**
+ * Util methods/functionality to interact with the {@link io.grpc.Context}.
+ *
+ * <p>Users must interact with the current Context via the public APIs in {@link Tracer} and avoid
+ * usages of the {@link #CONTEXT_SPAN_KEY} directly.
+ */
+public final class ContextUtils {
+ /** The {@link io.grpc.Context.Key} used to interact with {@link io.grpc.Context}. */
+ public static final Context.Key<Span> CONTEXT_SPAN_KEY = Context.key("instrumentation-trace-key");
+
+ // No instance of this class.
+ private ContextUtils() {}
+
+ /**
+ * Returns The {@link Span} from the current context.
+ *
+ * @return The {@code Span} from the current context.
+ */
+ static Span getCurrentSpan() {
+ return CONTEXT_SPAN_KEY.get(Context.current());
+ }
+
+ /**
+ * Enters the scope of code where the given {@link Span} is in the current context, and returns an
+ * object that represents that scope. The scope is exited when the returned object is closed.
+ *
+ * <p>Supports try-with-resource idiom.
+ *
+ * @param span The {@code Span} to be set to the current context.
+ * @return An object that defines a scope where the given {@code Span} is set to the current
+ * context.
+ */
+ static NonThrowingCloseable withSpan(Span span) {
+ return new WithSpan(span, CONTEXT_SPAN_KEY);
+ }
+
+ // Defines an arbitrary scope of code as a traceable operation. Supports try-with-resources idiom.
+ private static final class WithSpan implements NonThrowingCloseable {
+ private final Context origContext;
+
+ /**
+ * Constructs a new {@link WithSpan}.
+ *
+ * @param span is the {@code Span} to be added to the current {@code io.grpc.Context}.
+ * @param contextKey is the {@code Context.Key} used to set/get {@code Span} from the {@code
+ * Context}.
+ */
+ WithSpan(Span span, Context.Key<Span> contextKey) {
+ origContext = Context.current().withValue(contextKey, span).attach();
+ }
+
+ @Override
+ public void close() {
+ Context.current().detach(origContext);
+ }
+ }
+}
diff --git a/core/src/main/java/com/google/instrumentation/trace/ScopedSpanHandle.java b/core/src/main/java/com/google/instrumentation/trace/ScopedSpanHandle.java
index 152e17e3..2838071b 100644
--- a/core/src/main/java/com/google/instrumentation/trace/ScopedSpanHandle.java
+++ b/core/src/main/java/com/google/instrumentation/trace/ScopedSpanHandle.java
@@ -30,11 +30,10 @@ final class ScopedSpanHandle implements NonThrowingCloseable {
* Creates a {@code ScopedSpanHandle}
*
* @param span The span that will be installed in the current context.
- * @param contextSpanHandler The handler that is used to interact with the current context.
*/
- ScopedSpanHandle(Span span, ContextSpanHandler contextSpanHandler) {
+ ScopedSpanHandle(Span span) {
this.span = span;
- this.withSpan = contextSpanHandler.withSpan(span);
+ this.withSpan = ContextUtils.withSpan(span);
}
/**
diff --git a/core/src/main/java/com/google/instrumentation/trace/SpanBuilder.java b/core/src/main/java/com/google/instrumentation/trace/SpanBuilder.java
index 69298e68..9341d8cf 100644
--- a/core/src/main/java/com/google/instrumentation/trace/SpanBuilder.java
+++ b/core/src/main/java/com/google/instrumentation/trace/SpanBuilder.java
@@ -22,25 +22,6 @@ import javax.annotation.Nullable;
* {@link SpanBuilder} is used to construct {@link Span} instances which define arbitrary scopes of
* code that are sampled for distributed tracing as a single atomic unit.
*
- * <p>This is a simple example where all the work is being done within a single scope and the
- * Context is manually propagated:
- *
- * <pre>{@code
- * class MyClass {
- * private static final Tracer tracer = Tracer.getTracer();
- * void DoWork() {
- * Span span = tracer.spanBuilder(null, "MyRootSpan").startSpan();
- * span.addAnnotation("my annotation");
- * try {
- * doSomeWork(span); // Manually propagate the new span down the stack.
- * } finally {
- * // To make sure we end the span even in case of an exception.
- * span.end(); // Manually end the span.
- * }
- * }
- * }
- * }</pre>
- *
* <p>This is a simple example where all the work is being done within a single scope and a single
* thread and the Context is automatically propagated:
*
@@ -96,20 +77,37 @@ import javax.annotation.Nullable;
* }
* }</pre>
*
+ * <p>This is a simple example where all the work is being done within a single scope and the
+ * Context is manually propagated:
+ *
+ * <pre>{@code
+ * class MyClass {
+ * private static final Tracer tracer = Tracer.getTracer();
+ * void DoWork() {
+ * Span span = tracer.spanBuilder(null, "MyRootSpan").startSpan();
+ * span.addAnnotation("my annotation");
+ * try {
+ * doSomeWork(span); // Manually propagate the new span down the stack.
+ * } finally {
+ * // To make sure we end the span even in case of an exception.
+ * span.end(); // Manually end the span.
+ * }
+ * }
+ * }
+ * }</pre>
+ *
* <p>If your Java version is less than Java SE 7, see {@link SpanBuilder#startSpan} and {@link
* SpanBuilder#startScopedSpan} for usage examples.
*/
public final class SpanBuilder {
private final SpanFactory spanFactory;
- private final ContextSpanHandler contextSpanHandler;
- private SpanContext parentSpanContext;
- private boolean hasRemoteParent;
private final String name;
private final StartSpanOptions startSpanOption = new StartSpanOptions();
+ private SpanContext parentSpanContext;
+ private boolean hasRemoteParent;
SpanBuilder(
SpanFactory spanFactory,
- ContextSpanHandler contextSpanHandler,
SpanContext parentSpanContext,
boolean hasRemoteParent,
String name) {
@@ -117,7 +115,6 @@ public final class SpanBuilder {
this.hasRemoteParent = hasRemoteParent;
this.name = name;
this.spanFactory = spanFactory;
- this.contextSpanHandler = contextSpanHandler;
}
/**
@@ -273,7 +270,7 @@ public final class SpanBuilder {
* current Context.
*/
public NonThrowingCloseable startScopedSpan() {
- return new ScopedSpanHandle(start(), contextSpanHandler);
+ return new ScopedSpanHandle(start());
}
// Utility method to start a Span.
diff --git a/core/src/main/java/com/google/instrumentation/trace/Tracer.java b/core/src/main/java/com/google/instrumentation/trace/Tracer.java
index 432e7db4..07cac993 100644
--- a/core/src/main/java/com/google/instrumentation/trace/Tracer.java
+++ b/core/src/main/java/com/google/instrumentation/trace/Tracer.java
@@ -31,14 +31,21 @@ import javax.annotation.Nullable;
* <p>Users may choose to use manual or automatic Context propagation. Because of that this class
* offers APIs to facilitate both usages.
*
+ * <p>The automatic context propagation is done using {@link io.grpc.Context} which is a gRPC
+ * independent implementation for in-process Context propagation mechanism which can carry
+ * scoped-values across API boundaries and between threads. Users of the library must propagate the
+ * {@link io.grpc.Context} between different threads.
+ *
* <p>Example usage with automatic context propagation:
*
* <pre>{@code
* class MyClass {
* private static final Tracer tracer = Tracer.getTracer();
- * void DoWork() {
+ * void doWork() {
* try(NonThrowingCloseable ss = tracer.spanBuilder("MyClass.DoWork").startScopedSpan) {
- * tracer.getCurrentSpan().addAnnotation("We did the work.");
+ * tracer.getCurrentSpan().addAnnotation("Starting the work.");
+ * doWorkInternal();
+ * tracer.getCurrentSpan().addAnnotation("Finished working.");
* }
* }
* }
@@ -49,9 +56,15 @@ import javax.annotation.Nullable;
* <pre>{@code
* class MyClass {
* private static final Tracer tracer = Tracer.getTracer();
- * void DoWork(Span parent) {
- * try(NonThrowingCloseable ss = tracer.spanBuilder(parent, "MyClass.DoWork").startScopedSpan) {
- * tracer.getCurrentSpan().addAnnotation("We did the work.");
+ * void doWork() {
+ * Span span = tracer.spanBuilder(null, "MyRootSpan").startSpan();
+ * span.addAnnotation("Starting the work.");
+ * try {
+ * doSomeWork(span); // Manually propagate the new span down the stack.
+ * } finally {
+ * span.addAnnotation("Finished working.");
+ * // To make sure we end the span even in case of an exception.
+ * span.end(); // Manually end the span.
* }
* }
* }
@@ -60,25 +73,38 @@ import javax.annotation.Nullable;
public final class Tracer {
private static final Logger logger = Logger.getLogger(Tracer.class.getName());
private static final Tracer INSTANCE =
- new Tracer(
- loadContextSpanHandler(Provider.getCorrectClassLoader(ContextSpanHandler.class)),
- loadSpanFactory(Provider.getCorrectClassLoader(SpanFactory.class)));
- private final ContextSpanHandler contextSpanHandler;
+ new Tracer(loadSpanFactory(Provider.getCorrectClassLoader(SpanFactory.class)));
private final SpanFactory spanFactory;
+ @VisibleForTesting
+ Tracer(SpanFactory spanFactory) {
+ this.spanFactory = checkNotNull(spanFactory, "spanFactory");
+ }
+
/**
- * Returns the {@link Tracer} with the provided implementations for {@link ContextSpanHandler} and
- * {@link SpanFactory}.
- *
- * <p>If no implementation is provided for any of the {@link Tracer} modules then no-op
- * implementations will be used.
+ * Returns the {@link Tracer} with the provided implementations for {@link SpanFactory}. If no
+ * implementation is provided then no-op implementations will be used.
*
- * @return the {@link Tracer}.
+ * @return the {@code Tracer}.
*/
public static Tracer getTracer() {
return INSTANCE;
}
+ // Any provider that may be used for SpanFactory can be added here.
+ @VisibleForTesting
+ static SpanFactory loadSpanFactory(ClassLoader classLoader) {
+ try {
+ // Call Class.forName with literal string name of the class to help shading tools.
+ return Provider.createInstance(
+ Class.forName("com.google.instrumentation.trace.SpanFactoryImpl", true, classLoader),
+ SpanFactory.class);
+ } catch (ClassNotFoundException e) {
+ logger.log(Level.FINE, "Using default implementation for SpanFactory.", e);
+ }
+ return new NoopSpanFactory();
+ }
+
/**
* Gets the current Span from the current Context.
*
@@ -92,7 +118,7 @@ public final class Tracer {
* from the Context.
*/
public Span getCurrentSpan() {
- Span currentSpan = contextSpanHandler.getCurrentSpan();
+ Span currentSpan = ContextUtils.getCurrentSpan();
return currentSpan != null ? currentSpan : BlankSpan.INSTANCE;
}
@@ -146,7 +172,7 @@ public final class Tracer {
* @throws NullPointerException if span is null.
*/
public NonThrowingCloseable withSpan(Span span) {
- return contextSpanHandler.withSpan(checkNotNull(span, "span"));
+ return ContextUtils.withSpan(checkNotNull(span, "span"));
}
/**
@@ -163,7 +189,7 @@ public final class Tracer {
* @throws NullPointerException if name is null.
*/
public SpanBuilder spanBuilder(String name) {
- return spanBuilder(contextSpanHandler.getCurrentSpan(), name);
+ return spanBuilder(ContextUtils.getCurrentSpan(), name);
}
/**
@@ -183,7 +209,6 @@ public final class Tracer {
public SpanBuilder spanBuilder(@Nullable Span parent, String name) {
return new SpanBuilder(
spanFactory,
- contextSpanHandler,
parent == null ? null : parent.getContext(),
/* hasRemoteParent = */ false,
checkNotNull(name, "name"));
@@ -205,39 +230,7 @@ public final class Tracer {
*/
public SpanBuilder spanBuilderWithRemoteParent(@Nullable SpanContext remoteParent, String name) {
return new SpanBuilder(
- spanFactory,
- contextSpanHandler,
- remoteParent,
- /* hasRemoteParent = */ true,
- checkNotNull(name, "name"));
- }
-
- @VisibleForTesting
- Tracer(ContextSpanHandler contextSpanHandler, SpanFactory spanFactory) {
- this.contextSpanHandler = checkNotNull(contextSpanHandler, "contextSpanHandler");
- this.spanFactory = checkNotNull(spanFactory, "spanFactory");
- }
-
- // No-op implementation of the ContextSpanHandler
- private static final class NoopContextSpanHandler extends ContextSpanHandler {
- private static final NonThrowingCloseable defaultWithSpan =
- new NonThrowingCloseable() {
- @Override
- public void close() {
- // Do nothing.
- }
- };
-
- @Override
- @Nullable
- public Span getCurrentSpan() {
- return null;
- }
-
- @Override
- public NonThrowingCloseable withSpan(Span span) {
- return defaultWithSpan;
- }
+ spanFactory, remoteParent, /* hasRemoteParent = */ true, checkNotNull(name, "name"));
}
// No-op implementation of the SpanFactory
@@ -251,35 +244,4 @@ public final class Tracer {
return BlankSpan.INSTANCE;
}
}
-
- // Any provider that may be used for SpanFactory can be added here.
- @VisibleForTesting
- static SpanFactory loadSpanFactory(ClassLoader classLoader) {
- try {
- // Because of shading tools we must call Class.forName with the literal string name of the
- // class.
- return Provider.createInstance(
- Class.forName("com.google.instrumentation.trace.SpanFactoryImpl", true, classLoader),
- SpanFactory.class);
- } catch (ClassNotFoundException e) {
- logger.log(Level.FINE, "Using default implementation for SpanFactory.", e);
- }
- return new NoopSpanFactory();
- }
-
- // Any provider that may be used for ContextSpanHandler can be added here.
- @VisibleForTesting
- static ContextSpanHandler loadContextSpanHandler(ClassLoader classLoader) {
- try {
- // Because of shading tools we must call Class.forName with the literal string name of the
- // class.
- return Provider.createInstance(
- Class.forName(
- "com.google.instrumentation.trace.ContextSpanHandlerImpl", true, classLoader),
- ContextSpanHandler.class);
- } catch (ClassNotFoundException e) {
- logger.log(Level.FINE, "Using default implementation for ContextSpanHandler.", e);
- }
- return new NoopContextSpanHandler();
- }
}
diff --git a/core/src/test/java/com/google/instrumentation/trace/ContextUtilsTest.java b/core/src/test/java/com/google/instrumentation/trace/ContextUtilsTest.java
new file mode 100644
index 00000000..425f6731
--- /dev/null
+++ b/core/src/test/java/com/google/instrumentation/trace/ContextUtilsTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2017, Google Inc.
+ * 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 com.google.instrumentation.trace;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.instrumentation.common.NonThrowingCloseable;
+import io.grpc.Context;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/** Unit tests for {@link ContextUtils}. */
+public class ContextUtilsTest {
+ @Mock private Span span;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void getCurrentSpan_WhenNoContext() {
+ assertThat(ContextUtils.getCurrentSpan()).isNull();
+ }
+
+ @Test
+ public void getCurrentSpan() {
+ assertThat(ContextUtils.getCurrentSpan()).isNull();
+ Context origContext = Context.current().withValue(ContextUtils.CONTEXT_SPAN_KEY, span).attach();
+ // Make sure context is detached even if test fails.
+ try {
+ assertThat(ContextUtils.getCurrentSpan()).isSameAs(span);
+ } finally {
+ Context.current().detach(origContext);
+ }
+ assertThat(ContextUtils.getCurrentSpan()).isNull();
+ }
+
+ @Test
+ public void withSpan() {
+ assertThat(ContextUtils.getCurrentSpan()).isNull();
+ NonThrowingCloseable ws = ContextUtils.withSpan(span);
+ try {
+ assertThat(ContextUtils.getCurrentSpan()).isSameAs(span);
+ } finally {
+ ws.close();
+ }
+ assertThat(ContextUtils.getCurrentSpan()).isNull();
+ ;
+ }
+
+ @Test
+ public void propagationViaRunnable() {
+ Runnable runnable = null;
+ NonThrowingCloseable ws = ContextUtils.withSpan(span);
+ try {
+ assertThat(ContextUtils.getCurrentSpan()).isSameAs(span);
+ runnable =
+ Context.current()
+ .wrap(
+ new Runnable() {
+ @Override
+ public void run() {
+ assertThat(ContextUtils.getCurrentSpan()).isSameAs(span);
+ }
+ });
+ } finally {
+ ws.close();
+ }
+ assertThat(ContextUtils.getCurrentSpan()).isNotSameAs(span);
+ // When we run the runnable we will have the span in the current Context.
+ runnable.run();
+ }
+}
diff --git a/core/src/test/java/com/google/instrumentation/trace/ScopedSpanHandleTest.java b/core/src/test/java/com/google/instrumentation/trace/ScopedSpanHandleTest.java
index 971904b1..ec17428b 100644
--- a/core/src/test/java/com/google/instrumentation/trace/ScopedSpanHandleTest.java
+++ b/core/src/test/java/com/google/instrumentation/trace/ScopedSpanHandleTest.java
@@ -13,9 +13,9 @@
package com.google.instrumentation.trace;
+import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.same;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
import com.google.instrumentation.common.NonThrowingCloseable;
import org.junit.Before;
@@ -28,12 +28,9 @@ import org.mockito.MockitoAnnotations;
/** Unit tests for {@link ScopedSpanHandle}. */
@RunWith(JUnit4.class)
public class ScopedSpanHandleTest {
+ private static final Tracer tracer = Tracer.getTracer();
@Mock private Span span;
- @Mock private ContextSpanHandler csh;
-
- @Mock private NonThrowingCloseable ntc;
-
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
@@ -41,11 +38,14 @@ public class ScopedSpanHandleTest {
@Test
public void initAttachesSpan_CloseDetachesAndEndsSpan() {
- when(csh.withSpan(same(span))).thenReturn(ntc);
- try (NonThrowingCloseable ss = new ScopedSpanHandle(span, csh)) {
- // Do nothing.
+ assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE);
+ NonThrowingCloseable ss = new ScopedSpanHandle(span);
+ try {
+ assertThat(tracer.getCurrentSpan()).isSameAs(span);
+ } finally {
+ ss.close();
}
- verify(ntc).close();
+ assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE);
verify(span).end(same(EndSpanOptions.DEFAULT));
}
}
diff --git a/core/src/test/java/com/google/instrumentation/trace/SpanBuilderTest.java b/core/src/test/java/com/google/instrumentation/trace/SpanBuilderTest.java
index 657f3fe7..32a977cc 100644
--- a/core/src/test/java/com/google/instrumentation/trace/SpanBuilderTest.java
+++ b/core/src/test/java/com/google/instrumentation/trace/SpanBuilderTest.java
@@ -35,12 +35,10 @@ import org.mockito.MockitoAnnotations;
/** Unit tests for {@link Tracer}. */
@RunWith(JUnit4.class)
public class SpanBuilderTest {
- @Mock private ContextSpanHandler contextSpanHandler;
+ private static final String SPAN_NAME = "MySpanName";
+ private static final Tracer tracer = Tracer.getTracer();
@Mock private Span span;
@Mock private SpanFactory spanFactory;
- @Mock private NonThrowingCloseable withSpan;
-
- private static final String SPAN_NAME = "MySpanName";
private Random random;
private SpanContext spanContext;
private SpanBuilder spanBuilder;
@@ -54,9 +52,7 @@ public class SpanBuilderTest {
TraceId.generateRandomId(random),
SpanId.generateRandomId(random),
TraceOptions.DEFAULT);
- spanBuilder =
- new SpanBuilder(
- spanFactory, contextSpanHandler, spanContext, false /* hasRemoteParent */, SPAN_NAME);
+ spanBuilder = new SpanBuilder(spanFactory, spanContext, false /* hasRemoteParent */, SPAN_NAME);
}
@Test
@@ -64,9 +60,12 @@ public class SpanBuilderTest {
when(spanFactory.startSpan(
isNull(SpanContext.class), eq(false), same(SPAN_NAME), eq(new StartSpanOptions())))
.thenReturn(span);
- when(contextSpanHandler.withSpan(same(span))).thenReturn(withSpan);
- try (NonThrowingCloseable ss = spanBuilder.becomeRoot().startScopedSpan()) {}
- verify(withSpan).close();
+ NonThrowingCloseable ss = spanBuilder.becomeRoot().startScopedSpan();
+ try {
+ assertThat(tracer.getCurrentSpan()).isSameAs(span);
+ } finally {
+ ss.close();
+ }
verify(span).end(same(EndSpanOptions.DEFAULT));
}
@@ -78,14 +77,17 @@ public class SpanBuilderTest {
when(spanFactory.startSpan(
isNull(SpanContext.class), eq(false), same(SPAN_NAME), eq(startSpanOptions)))
.thenReturn(span);
- when(contextSpanHandler.withSpan(same(span))).thenReturn(withSpan);
- try (NonThrowingCloseable ss =
+ NonThrowingCloseable ss =
spanBuilder
.becomeRoot()
.setSampler(Samplers.neverSample())
.setStartTime(Timestamp.fromMillis(1234567L))
- .startScopedSpan()) {}
- verify(withSpan).close();
+ .startScopedSpan();
+ try {
+ assertThat(tracer.getCurrentSpan()).isSameAs(span);
+ } finally {
+ ss.close();
+ }
verify(span).end(same(EndSpanOptions.DEFAULT));
}
@@ -102,9 +104,7 @@ public class SpanBuilderTest {
@Test
public void startSpan_WithNullParent() {
- spanBuilder =
- new SpanBuilder(
- spanFactory, contextSpanHandler, null, false /* hasRemoteParent */, SPAN_NAME);
+ spanBuilder = new SpanBuilder(spanFactory, null, false /* hasRemoteParent */, SPAN_NAME);
when(spanFactory.startSpan(
isNull(SpanContext.class), eq(false), same(SPAN_NAME), eq(new StartSpanOptions())))
.thenReturn(span);
@@ -161,9 +161,7 @@ public class SpanBuilderTest {
@Test
public void startSpanWitRemoteParent() {
- spanBuilder =
- new SpanBuilder(
- spanFactory, contextSpanHandler, spanContext, true /* hasRemoteParent */, SPAN_NAME);
+ spanBuilder = new SpanBuilder(spanFactory, spanContext, true /* hasRemoteParent */, SPAN_NAME);
when(spanFactory.startSpan(
same(spanContext), eq(true), same(SPAN_NAME), eq(new StartSpanOptions())))
.thenReturn(span);
@@ -175,9 +173,7 @@ public class SpanBuilderTest {
@Test
public void startSpanWitRemoteParent_WithNullParent() {
- spanBuilder =
- new SpanBuilder(
- spanFactory, contextSpanHandler, null, true /* hasRemoteParent */, SPAN_NAME);
+ spanBuilder = new SpanBuilder(spanFactory, null, true /* hasRemoteParent */, SPAN_NAME);
when(spanFactory.startSpan(
isNull(SpanContext.class), eq(true), same(SPAN_NAME), eq(new StartSpanOptions())))
.thenReturn(span);
diff --git a/core/src/test/java/com/google/instrumentation/trace/TracerTest.java b/core/src/test/java/com/google/instrumentation/trace/TracerTest.java
index cc60fe5c..69661177 100644
--- a/core/src/test/java/com/google/instrumentation/trace/TracerTest.java
+++ b/core/src/test/java/com/google/instrumentation/trace/TracerTest.java
@@ -21,7 +21,9 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import com.google.instrumentation.common.NonThrowingCloseable;
+import io.grpc.Context;
import java.util.Random;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
@@ -33,14 +35,15 @@ import org.mockito.MockitoAnnotations;
/** Unit tests for {@link Tracer}. */
@RunWith(JUnit4.class)
public class TracerTest {
- @Rule public ExpectedException thrown = ExpectedException.none();
-
private static final Tracer tracer = Tracer.getTracer();
-
- @Mock private ContextSpanHandler contextSpanHandler;
+ @Rule public ExpectedException thrown = ExpectedException.none();
@Mock private SpanFactory spanFactory;
@Mock private Span span;
- @Mock private NonThrowingCloseable withSpan;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
@Test
public void defaultGetCurrentSpan() {
@@ -49,14 +52,43 @@ public class TracerTest {
@Test(expected = NullPointerException.class)
public void withSpan_NullSpan() {
- try (NonThrowingCloseable ws = tracer.withSpan(null)) {}
+ tracer.withSpan(null);
}
@Test
- public void defaultWithSpan() {
- try (NonThrowingCloseable ss = tracer.withSpan(BlankSpan.INSTANCE)) {
- assertThat(tracer.getCurrentSpan()).isEqualTo(BlankSpan.INSTANCE);
+ public void getCurrentSpan_WithSpan() {
+ assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE);
+ NonThrowingCloseable ws = tracer.withSpan(span);
+ try {
+ assertThat(tracer.getCurrentSpan()).isSameAs(span);
+ } finally {
+ ws.close();
}
+ assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE);
+ }
+
+ @Test
+ public void propagationViaRunnable() {
+ Runnable runnable = null;
+ NonThrowingCloseable ws = tracer.withSpan(span);
+ try {
+ assertThat(tracer.getCurrentSpan()).isSameAs(span);
+ runnable =
+ Context.current()
+ .wrap(
+ new Runnable() {
+ @Override
+ public void run() {
+ assertThat(tracer.getCurrentSpan()).isSameAs(span);
+ }
+ });
+ } finally {
+ ws.close();
+ }
+ assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE);
+ // When we run the runnable we will have the span in the current Context.
+ runnable.run();
+ assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE);
}
@Test(expected = NullPointerException.class)
@@ -92,35 +124,6 @@ public class TracerTest {
}
@Test
- public void loadContextSpanHandler_UsesProvidedClassLoader() {
- final RuntimeException toThrow = new RuntimeException("UseClassLoader");
- thrown.expect(RuntimeException.class);
- thrown.expectMessage("UseClassLoader");
- Tracer.loadContextSpanHandler(
- new ClassLoader() {
- @Override
- public Class<?> loadClass(String name) {
- throw toThrow;
- }
- });
- }
-
- @Test
- public void loadContextSpanHandler_IgnoresMissingClasses() {
- assertThat(
- Tracer.loadContextSpanHandler(
- new ClassLoader() {
- @Override
- public Class<?> loadClass(String name) throws ClassNotFoundException {
- throw new ClassNotFoundException();
- }
- })
- .getClass()
- .getName())
- .isEqualTo("com.google.instrumentation.trace.Tracer$NoopContextSpanHandler");
- }
-
- @Test
public void loadSpanFactory_UsesProvidedClassLoader() {
final RuntimeException toThrow = new RuntimeException("UseClassLoader");
thrown.expect(RuntimeException.class);
@@ -150,47 +153,39 @@ public class TracerTest {
}
@Test
- public void getCurrentSpan() {
- Tracer mockTracer = newTracerWithMocks();
- when(contextSpanHandler.getCurrentSpan()).thenReturn(span);
- assertThat(mockTracer.getCurrentSpan()).isEqualTo(span);
- }
-
- @Test
- public void withSpan() {
- Tracer mockTracer = newTracerWithMocks();
- when(contextSpanHandler.withSpan(same(span))).thenReturn(withSpan);
- try (NonThrowingCloseable ss = mockTracer.withSpan(span)) {}
- verify(withSpan).close();
- }
-
- @Test
public void startScopedSpanRoot() {
Tracer mockTracer = newTracerWithMocks();
- when(contextSpanHandler.getCurrentSpan()).thenReturn(null);
when(spanFactory.startSpan(
isNull(SpanContext.class), eq(false), eq("MySpanName"), eq(new StartSpanOptions())))
.thenReturn(span);
- when(contextSpanHandler.withSpan(same(span))).thenReturn(withSpan);
- try (NonThrowingCloseable ss =
- mockTracer.spanBuilder("MySpanName").becomeRoot().startScopedSpan()) {}
- verify(withSpan).close();
+ NonThrowingCloseable ss = mockTracer.spanBuilder("MySpanName").becomeRoot().startScopedSpan();
+ try {
+ assertThat(tracer.getCurrentSpan()).isSameAs(span);
+ } finally {
+ ss.close();
+ }
verify(span).end(same(EndSpanOptions.DEFAULT));
}
@Test
public void startScopedSpanChild() {
Tracer mockTracer = newTracerWithMocks();
- when(contextSpanHandler.getCurrentSpan()).thenReturn(BlankSpan.INSTANCE);
- when(spanFactory.startSpan(
- same(BlankSpan.INSTANCE.getContext()),
- eq(false),
- eq("MySpanName"),
- eq(new StartSpanOptions())))
- .thenReturn(span);
- when(contextSpanHandler.withSpan(same(span))).thenReturn(withSpan);
- try (NonThrowingCloseable ss = mockTracer.spanBuilder("MySpanName").startScopedSpan()) {}
- verify(withSpan).close();
+ NonThrowingCloseable ws = mockTracer.withSpan(BlankSpan.INSTANCE);
+ try {
+ assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE);
+ when(spanFactory.startSpan(
+ same(SpanContext.INVALID), eq(false), eq("MySpanName"), eq(new StartSpanOptions())))
+ .thenReturn(span);
+ NonThrowingCloseable ss = mockTracer.spanBuilder("MySpanName").startScopedSpan();
+ try {
+ assertThat(tracer.getCurrentSpan()).isSameAs(span);
+ } finally {
+ ss.close();
+ }
+ assertThat(tracer.getCurrentSpan()).isSameAs(BlankSpan.INSTANCE);
+ } finally {
+ ws.close();
+ }
verify(span).end(same(EndSpanOptions.DEFAULT));
}
@@ -242,7 +237,6 @@ public class TracerTest {
}
private Tracer newTracerWithMocks() {
- MockitoAnnotations.initMocks(this);
- return new Tracer(contextSpanHandler, spanFactory);
+ return new Tracer(spanFactory);
}
}