Refactor Ratpack
Remove the use of the OT project and Execution managed scopes. Updated tests.
MODIFY
dd-java-agent/instrumentation/ratpack-1.4/ratpack-1.4.gradle
dd-java-agent/instrumentation/ratpack-1.4/ratpack-1.4.gradle
@@ -51,7 +51,6 @@ testSets {
dependencies {
main_java8CompileOnly group: 'io.ratpack', name: 'ratpack-core', version: '1.4.0'
- main_java8Compile project(':dd-trace-ot')
main_java8Compile project(':dd-java-agent:agent-tooling')
main_java8Compile deps.bytebuddy
@@ -65,6 +64,7 @@ dependencies {
compile sourceSets.main_java8.output
testCompile project(':dd-java-agent:testing')
+ testCompile project(':dd-java-agent:instrumentation:java-concurrent')
testCompile group: 'io.ratpack', name: 'ratpack-groovy-test', version: '1.4.0'
latestDepTestCompile group: 'io.ratpack', name: 'ratpack-groovy-test', version: '+'
}

MODIFY
dd-java-agent/instrumentation/ratpack-1.4/src/main/java/datadog/trace/instrumentation/ratpack/RatpackHttpClientInstrumentation.java
dd-java-agent/instrumentation/ratpack-1.4/src/main/java/datadog/trace/instrumentation/ratpack/RatpackHttpClientInstrumentation.java
@@ -55,9 +55,6 @@ public final class RatpackHttpClientInstrumentation extends Instrumenter.Default
"datadog.trace.instrumentation.ratpack.impl.RatpackHttpClientAdvice$StreamedResponseAction",
"datadog.trace.instrumentation.ratpack.impl.RequestSpecInjectAdapter",
"datadog.trace.instrumentation.ratpack.impl.WrappedRequestSpec",
- // core helpers
- "datadog.opentracing.scopemanager.ContextualScopeManager",
- "datadog.opentracing.scopemanager.ScopeContext"
};
}

MODIFY
dd-java-agent/instrumentation/ratpack-1.4/src/main/java/datadog/trace/instrumentation/ratpack/RatpackInstrumentation.java
dd-java-agent/instrumentation/ratpack-1.4/src/main/java/datadog/trace/instrumentation/ratpack/RatpackInstrumentation.java
@@ -55,13 +55,8 @@ public final class RatpackInstrumentation extends Instrumenter.Default {
@Override
public String[] helperClassNames() {
return new String[] {
- // core helpers
- "datadog.opentracing.scopemanager.ContextualScopeManager",
- "datadog.opentracing.scopemanager.ScopeContext",
// service registry helpers
"datadog.trace.instrumentation.ratpack.impl.RatpackRequestExtractAdapter",
- "datadog.trace.instrumentation.ratpack.impl.RatpackScopeManager",
- "datadog.trace.instrumentation.ratpack.impl.RatpackScopeManager$RatpackScope",
"datadog.trace.instrumentation.ratpack.impl.RatpackServerAdvice",
"datadog.trace.instrumentation.ratpack.impl.RatpackServerAdvice$RatpackServerRegistryAdvice",
"datadog.trace.instrumentation.ratpack.impl.TracingHandler"
@@ -102,9 +97,6 @@ public final class RatpackInstrumentation extends Instrumenter.Default {
@Override
public String[] helperClassNames() {
return new String[] {
- // core helpers
- "datadog.opentracing.scopemanager.ContextualScopeManager",
- "datadog.opentracing.scopemanager.ScopeContext",
// exec helpers
"datadog.trace.instrumentation.ratpack.impl.RatpackServerAdvice$ExecStarterAdvice",
"datadog.trace.instrumentation.ratpack.impl.RatpackServerAdvice$ExecStarterAction"

DELETE
dd-java-agent/instrumentation/ratpack-1.4/src/main/java8/datadog/trace/instrumentation/ratpack/impl/RatpackScopeManager.java
-package datadog.trace.instrumentation.ratpack.impl;
-
-import datadog.opentracing.scopemanager.ScopeContext;
-import io.opentracing.Scope;
-import io.opentracing.Span;
-import ratpack.exec.Execution;
-import ratpack.exec.UnmanagedThreadException;
-
-/**
- * This scope manager uses the Ratpack Execution to store the current Scope. This is a ratpack
- * registry analogous to a ThreadLocal but for an execution that may transfer between several
- * threads
- */
-public final class RatpackScopeManager implements ScopeContext {
- @Override
- public boolean inContext() {
- return Execution.isManagedThread();
- }
-
- @Override
- public Scope activate(Span span, boolean finishSpanOnClose) {
- Execution execution = Execution.current();
- RatpackScope ratpackScope =
- new RatpackScope(
- span, finishSpanOnClose, execution.maybeGet(RatpackScope.class).orElse(null));
- // remove any existing RatpackScopes before adding it to the registry
- execution
- .maybeGet(RatpackScope.class)
- .ifPresent(ignored -> execution.remove(RatpackScope.class));
- execution.add(RatpackScope.class, ratpackScope);
- execution.onComplete(
- ratpackScope); // ensure that the scope is closed when the execution finishes
- return ratpackScope;
- }
-
- @Override
- public Scope active() {
- try {
- return Execution.current().maybeGet(RatpackScope.class).orElse(null);
- } catch (UnmanagedThreadException ume) {
- return null; // should never happen due to inContextCheck
- }
- }
-
- static class RatpackScope implements Scope {
- private final Span wrapped;
- private final boolean finishOnClose;
- private final RatpackScope toRestore;
-
- RatpackScope(Span wrapped, boolean finishOnClose, RatpackScope toRestore) {
- this.wrapped = wrapped;
- this.finishOnClose = finishOnClose;
- this.toRestore = toRestore;
- }
-
- @Override
- public Span span() {
- return wrapped;
- }
-
- @Override
- public void close() {
- Execution execution = Execution.current();
- // only close if this scope is the current scope for this Execution
- // As with ThreadLocalScope this shouldn't happen if users call methods in the expected order
- execution
- .maybeGet(RatpackScope.class)
- .filter(s -> this == s)
- .ifPresent(
- ignore -> {
- if (finishOnClose) {
- wrapped.finish();
- }
- // pop the execution "stack"
- execution.remove(RatpackScope.class);
- if (toRestore != null) {
- execution.add(toRestore);
- }
- });
- }
- }
-}

MODIFY
dd-java-agent/instrumentation/ratpack-1.4/src/main/java8/datadog/trace/instrumentation/ratpack/impl/RatpackServerAdvice.java
dd-java-agent/instrumentation/ratpack-1.4/src/main/java8/datadog/trace/instrumentation/ratpack/impl/RatpackServerAdvice.java
package datadog.trace.instrumentation.ratpack.impl;
-import datadog.opentracing.scopemanager.ContextualScopeManager;
import io.opentracing.Scope;
import io.opentracing.ScopeManager;
import io.opentracing.util.GlobalTracer;
@@ -17,25 +16,12 @@ public class RatpackServerAdvice {
public static class RatpackServerRegistryAdvice {
@Advice.OnMethodExit(suppress = Throwable.class)
public static void injectTracing(@Advice.Return(readOnly = false) Registry registry) {
- RatpackScopeManager ratpackScopeManager = new RatpackScopeManager();
- // the value returned from ServerRegistry.buildBaseRegistry needs to be modified to add our
- // scope manager and handler decorator to the registry
- //noinspection UnusedAssignment
registry =
registry.join(
Registry.builder()
- .add(ScopeManager.class, ratpackScopeManager)
+ .add(ScopeManager.class, GlobalTracer.get().scopeManager())
.add(HandlerDecorator.prepend(new TracingHandler()))
.build());
-
- if (GlobalTracer.isRegistered()) {
- if (GlobalTracer.get().scopeManager() instanceof ContextualScopeManager) {
- ((ContextualScopeManager) GlobalTracer.get().scopeManager())
- .addScopeContext(ratpackScopeManager);
- }
- } else {
- log.warn("No GlobalTracer registered");
- }
}
}
@@ -43,9 +29,8 @@ public class RatpackServerAdvice {
@Advice.OnMethodEnter
public static void addScopeToRegistry(
@Advice.Argument(value = 0, readOnly = false) Action<? super RegistrySpec> action) {
- Scope active = GlobalTracer.get().scopeManager().active();
+ final Scope active = GlobalTracer.get().scopeManager().active();
if (active != null) {
- //noinspection UnusedAssignment
action = new ExecStarterAction(active).append(action);
}
}
@@ -53,8 +38,8 @@ public class RatpackServerAdvice {
public static class ExecutionAdvice {
@Advice.OnMethodExit
- public static void addScopeToRegistry(@Advice.Return ExecStarter starter) {
- Scope active = GlobalTracer.get().scopeManager().active();
+ public static void addScopeToRegistry(@Advice.Return final ExecStarter starter) {
+ final Scope active = GlobalTracer.get().scopeManager().active();
if (active != null) {
starter.register(new ExecStarterAction(active));
}
@@ -64,13 +49,12 @@ public class RatpackServerAdvice {
public static class ExecStarterAction implements Action<RegistrySpec> {
private final Scope active;
- @SuppressWarnings("WeakerAccess")
- public ExecStarterAction(Scope active) {
+ public ExecStarterAction(final Scope active) {
this.active = active;
}
@Override
- public void execute(RegistrySpec spec) {
+ public void execute(final RegistrySpec spec) {
if (active != null) {
spec.add(active);
}

MODIFY
dd-java-agent/instrumentation/ratpack-1.4/src/main/java8/datadog/trace/instrumentation/ratpack/impl/TracingHandler.java
dd-java-agent/instrumentation/ratpack-1.4/src/main/java8/datadog/trace/instrumentation/ratpack/impl/TracingHandler.java
@@ -2,6 +2,7 @@ package datadog.trace.instrumentation.ratpack.impl;
import datadog.trace.api.DDSpanTypes;
import datadog.trace.api.DDTags;
+import datadog.trace.context.TraceScope;
import io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.SpanContext;
@@ -37,9 +38,16 @@ public final class TracingHandler implements Handler {
.withTag(Tags.HTTP_URL.getKey(), request.getUri())
.startActive(true);
+ if (scope instanceof TraceScope) {
+ ((TraceScope) scope).setAsyncPropagation(true);
+ }
+
ctx.getResponse()
.beforeSend(
response -> {
+ if (scope instanceof TraceScope) {
+ ((TraceScope) scope).setAsyncPropagation(false);
+ }
final Span span = scope.span();
span.setTag(DDTags.RESOURCE_NAME, getResourceName(ctx));
final Status status = response.getStatus();
@@ -49,6 +57,7 @@ public final class TracingHandler implements Handler {
}
Tags.HTTP_STATUS.set(span, status.getCode());
}
+
scope.close();
});

MODIFY
dd-java-agent/instrumentation/ratpack-1.4/src/test/groovy/RatpackTest.groovy
dd-java-agent/instrumentation/ratpack-1.4/src/test/groovy/RatpackTest.groovy
-import datadog.opentracing.scopemanager.ContextualScopeManager
import datadog.trace.agent.test.AgentTestRunner
import datadog.trace.agent.test.utils.OkHttpUtils
import datadog.trace.api.DDSpanTypes
-import datadog.trace.instrumentation.ratpack.impl.RatpackScopeManager
+import datadog.trace.api.DDTags
+import datadog.trace.context.TraceScope
import io.opentracing.Scope
+import io.opentracing.tag.Tags
import io.opentracing.util.GlobalTracer
import okhttp3.HttpUrl
import okhttp3.OkHttpClient
@@ -37,12 +38,15 @@ class RatpackTest extends AgentTestRunner {
.url(app.address.toURL())
.get()
.build()
+
when:
def resp = client.newCall(request).execute()
+
then:
resp.code() == 200
resp.body.string() == "success"
+<<<<<<< HEAD
TEST_WRITER.size() == 1
def trace = TEST_WRITER.firstTrace()
trace.size() == 1
@@ -60,6 +64,29 @@ class RatpackTest extends AgentTestRunner {
span.context().tags["http.status_code"] == 200
span.context().tags["thread.name"] != null
span.context().tags["thread.id"] != null
+=======
+ assertTraces(1) {
+ trace(0, 1) {
+ span(0) {
+ resourceName "GET /"
+ serviceName "unnamed-java-app"
+ operationName "ratpack.handler"
+ spanType DDSpanTypes.HTTP_SERVER
+ parent()
+ errored false
+ tags {
+ "$Tags.COMPONENT.key" "handler"
+ "$Tags.SPAN_KIND.key" Tags.SPAN_KIND_SERVER
+ "$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_SERVER
+ "$Tags.HTTP_METHOD.key" "GET"
+ "$Tags.HTTP_STATUS.key" 200
+ "$Tags.HTTP_URL.key" "/"
+ defaultTags()
+ }
+ }
+ }
+ }
+>>>>>>> 1bfa7e47... Refactor Ratpack
}
def "test path with bindings call"() {
@@ -77,12 +104,15 @@ class RatpackTest extends AgentTestRunner {
.url(HttpUrl.get(app.address).newBuilder().addPathSegments("a/b/baz").build())
.get()
.build()
+
when:
def resp = client.newCall(request).execute()
+
then:
resp.code() == 200
resp.body.string() == ":foo/:bar?/baz"
+<<<<<<< HEAD
TEST_WRITER.size() == 1
def trace = TEST_WRITER.firstTrace()
trace.size() == 1
@@ -100,6 +130,29 @@ class RatpackTest extends AgentTestRunner {
span.context().tags["http.status_code"] == 200
span.context().tags["thread.name"] != null
span.context().tags["thread.id"] != null
+=======
+ assertTraces(1) {
+ trace(0, 1) {
+ span(0) {
+ resourceName "GET /:foo/:bar?/baz"
+ serviceName "unnamed-java-app"
+ operationName "ratpack.handler"
+ spanType DDSpanTypes.HTTP_SERVER
+ parent()
+ errored false
+ tags {
+ "$Tags.COMPONENT.key" "handler"
+ "$Tags.SPAN_KIND.key" Tags.SPAN_KIND_SERVER
+ "$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_SERVER
+ "$Tags.HTTP_METHOD.key" "GET"
+ "$Tags.HTTP_STATUS.key" 200
+ "$Tags.HTTP_URL.key" "/a/b/baz"
+ defaultTags()
+ }
+ }
+ }
+ }
+>>>>>>> 1bfa7e47... Refactor Ratpack
}
def "test error response"() {
@@ -107,7 +160,9 @@ class RatpackTest extends AgentTestRunner {
def app = GroovyEmbeddedApp.ratpack {
handlers {
get {
- context.clientError(500)
+ context.render(Promise.sync {
+ return "fail " + 0 / 0
+ })
}
}
}
@@ -120,6 +175,7 @@ class RatpackTest extends AgentTestRunner {
then:
resp.code() == 500
+<<<<<<< HEAD
TEST_WRITER.size() == 1
def trace = TEST_WRITER.firstTrace()
trace.size() == 1
@@ -137,6 +193,31 @@ class RatpackTest extends AgentTestRunner {
span.context().tags["http.status_code"] == 500
span.context().tags["thread.name"] != null
span.context().tags["thread.id"] != null
+=======
+ assertTraces(1) {
+ trace(0, 1) {
+ span(0) {
+ resourceName "GET /"
+ serviceName "unnamed-java-app"
+ operationName "ratpack.handler"
+ spanType DDSpanTypes.HTTP_SERVER
+ parent()
+ errored true
+ tags {
+ "$Tags.COMPONENT.key" "handler"
+ "$Tags.SPAN_KIND.key" Tags.SPAN_KIND_SERVER
+ "$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_SERVER
+ "$Tags.HTTP_METHOD.key" "GET"
+ "$Tags.HTTP_STATUS.key" 500
+ "$Tags.HTTP_URL.key" "/"
+ "error" true
+// errorTags(Exception, String) // TODO: find out how to get throwable in instrumentation
+ defaultTags()
+ }
+ }
+ }
+ }
+>>>>>>> 1bfa7e47... Refactor Ratpack
}
def "test path call using ratpack http client"() {
@@ -173,8 +254,10 @@ class RatpackTest extends AgentTestRunner {
.url(app.address.toURL())
.get()
.build()
+
when:
def resp = client.newCall(request).execute()
+
then:
resp.code() == 200
resp.body().string() == "success"
@@ -182,6 +265,7 @@ class RatpackTest extends AgentTestRunner {
// 3rd is the three traces, ratpack, http client 2 and http client 1
// 2nd is nested2 from the external server (the result of the 2nd internal http client call)
// 1st is nested from the external server (the result of the 1st internal http client call)
+<<<<<<< HEAD
TEST_WRITER.size() == 3
def trace = TEST_WRITER.get(2)
trace.size() == 3
@@ -212,9 +296,121 @@ class RatpackTest extends AgentTestRunner {
clientTrace1.context().tags["http.status_code"] == 200
clientTrace1.context().tags["thread.name"] != null
clientTrace1.context().tags["thread.id"] != null
+=======
+ assertTraces(3) {
+ // simulated external system, first call
+ trace(0, 1) {
+ span(0) {
+ resourceName "GET /nested"
+ serviceName "unnamed-java-app"
+ operationName "ratpack.handler"
+ spanType DDSpanTypes.HTTP_SERVER
+ childOf(trace(2).get(2))
+ errored false
+ tags {
+ "$Tags.COMPONENT.key" "handler"
+ "$Tags.SPAN_KIND.key" Tags.SPAN_KIND_SERVER
+ "$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_SERVER
+ "$Tags.HTTP_METHOD.key" "GET"
+ "$Tags.HTTP_STATUS.key" 200
+ "$Tags.HTTP_URL.key" "/nested"
+ defaultTags(true)
+ }
+ }
+ }
+ // simulated external system, second call
+ trace(1, 1) {
+ span(0) {
+ resourceName "GET /nested2"
+ serviceName "unnamed-java-app"
+ operationName "ratpack.handler"
+ spanType DDSpanTypes.HTTP_SERVER
+ childOf(trace(2).get(1))
+ errored false
+ tags {
+ "$Tags.COMPONENT.key" "handler"
+ "$Tags.SPAN_KIND.key" Tags.SPAN_KIND_SERVER
+ "$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_SERVER
+ "$Tags.HTTP_METHOD.key" "GET"
+ "$Tags.HTTP_STATUS.key" 200
+ "$Tags.HTTP_URL.key" "/nested2"
+ defaultTags(true)
+ }
+ }
+ }
+ trace(2, 3) {
+ // main app span that processed the request from OKHTTP request
+ span(0) {
+ resourceName "GET /"
+ serviceName "unnamed-java-app"
+ operationName "ratpack.handler"
+ spanType DDSpanTypes.HTTP_SERVER
+ parent()
+ errored false
+ tags {
+ "$Tags.COMPONENT.key" "handler"
+ "$Tags.SPAN_KIND.key" Tags.SPAN_KIND_SERVER
+ "$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_SERVER
+ "$Tags.HTTP_METHOD.key" "GET"
+ "$Tags.HTTP_STATUS.key" 200
+ "$Tags.HTTP_URL.key" "/"
+ defaultTags()
+ }
+ }
+ // Second http client call that receives the 'ess' of Success
+ span(1) {
+ resourceName "GET /?"
+ serviceName "unnamed-java-app"
+ operationName "ratpack.client-request"
+ spanType DDSpanTypes.HTTP_CLIENT
+ childOf(span(0))
+ errored false
+ tags {
+ "$Tags.COMPONENT.key" "httpclient"
+ "$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
+ "$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_CLIENT
+ "$Tags.HTTP_METHOD.key" "GET"
+ "$Tags.HTTP_STATUS.key" 200
+ "$Tags.HTTP_URL.key" "${external.address}nested2"
+ defaultTags()
+ }
+ }
+ // First http client call that receives the 'Succ' of Success
+ span(2) {
+ resourceName "GET /nested"
+ serviceName "unnamed-java-app"
+ operationName "ratpack.client-request"
+ spanType DDSpanTypes.HTTP_CLIENT
+ childOf(span(0))
+ errored false
+ tags {
+ "$Tags.COMPONENT.key" "httpclient"
+ "$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
+ "$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_CLIENT
+ "$Tags.HTTP_METHOD.key" "GET"
+ "$Tags.HTTP_STATUS.key" 200
+ "$Tags.HTTP_URL.key" "${external.address}nested"
+ defaultTags()
+ }
+ }
+ }
+ }
+ }
- def clientTrace2 = trace[2] // First http client call that receives the 'Succ' of Success
+ def "test forked path call and start span in handler (#startSpanInHandler)"() {
+ setup:
+ def app = GroovyEmbeddedApp.ratpack {
+ handlers {
+ get {
+>>>>>>> 1bfa7e47... Refactor Ratpack
+ final Scope scope = !startSpanInHandler ? GlobalTracer.get().scopeManager().active() :
+ GlobalTracer.get()
+ .buildSpan("ratpack.exec-test")
+ .withTag(DDTags.RESOURCE_NAME, "INSIDE-TEST")
+ .startActive(true)
+
+<<<<<<< HEAD
clientTrace2.context().serviceName == "unnamed-java-app"
clientTrace2.context().operationName == "ratpack.client-request"
clientTrace1.context().tags["component"] == "ratpack-httpclient"
@@ -225,11 +421,23 @@ class RatpackTest extends AgentTestRunner {
clientTrace2.context().tags["http.status_code"] == 200
clientTrace2.context().tags["thread.name"] != null
clientTrace2.context().tags["thread.id"] != null
+=======
+ ((TraceScope) scope).setAsyncPropagation(true)
+ scope.span().setBaggageItem("test-baggage", "foo")
+ context.render(testPromise(startSpanInHandler).fork())
+ }
+ }
+ }
+ def request = new Request.Builder()
+ .url(app.address.toURL())
+ .get()
+ .build()
+>>>>>>> 1bfa7e47... Refactor Ratpack
- def nestedTrace = TEST_WRITER.get(1)
- nestedTrace.size() == 1
- def nestedSpan = nestedTrace[0] // simulated external system, second call
+ when:
+ def resp = client.newCall(request).execute()
+<<<<<<< HEAD
nestedSpan.context().serviceName == "unnamed-java-app"
nestedSpan.context().operationName == "ratpack.handler"
nestedSpan.context().resourceName == "GET /nested2"
@@ -242,11 +450,49 @@ class RatpackTest extends AgentTestRunner {
nestedSpan.context().tags["http.status_code"] == 200
nestedSpan.context().tags["thread.name"] != null
nestedSpan.context().tags["thread.id"] != null
+=======
+ then:
+ resp.code() == 200
+ resp.body().string() == "foo"
+>>>>>>> 1bfa7e47... Refactor Ratpack
- def nestedTrace2 = TEST_WRITER.get(0)
- nestedTrace2.size() == 1
- def nestedSpan2 = nestedTrace2[0] // simulated external system, first call
+ assertTraces(1) {
+ trace(0, (startSpanInHandler ? 2 : 1)) {
+ span(0) {
+ resourceName "GET /"
+ serviceName "unnamed-java-app"
+ operationName "ratpack.handler"
+ spanType DDSpanTypes.HTTP_SERVER
+ parent()
+ errored false
+ tags {
+ "$Tags.COMPONENT.key" "handler"
+ "$Tags.SPAN_KIND.key" Tags.SPAN_KIND_SERVER
+ "$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_SERVER
+ "$Tags.HTTP_METHOD.key" "GET"
+ "$Tags.HTTP_STATUS.key" 200
+ "$Tags.HTTP_URL.key" "/"
+ defaultTags()
+ }
+ }
+ if (startSpanInHandler) {
+ span(1) {
+ resourceName "INSIDE-TEST"
+ serviceName "unnamed-java-app"
+ operationName "ratpack.exec-test"
+ spanType DDSpanTypes.HTTP_SERVER
+ childOf(span(0))
+ errored false
+ tags {
+ "$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_SERVER
+ defaultTags()
+ }
+ }
+ }
+ }
+ }
+<<<<<<< HEAD
nestedSpan2.context().serviceName == "unnamed-java-app"
nestedSpan2.context().operationName == "ratpack.handler"
nestedSpan2.context().resourceName == "GET /nested"
@@ -259,33 +505,60 @@ class RatpackTest extends AgentTestRunner {
nestedSpan2.context().tags["http.status_code"] == 200
nestedSpan2.context().tags["thread.name"] != null
nestedSpan2.context().tags["thread.id"] != null
+=======
+ where:
+ startSpanInHandler << [true, false]
+>>>>>>> 1bfa7e47... Refactor Ratpack
}
def "forked executions inherit parent scope"() {
when:
- def result = ExecHarness.yieldSingle({ spec ->
- // This does the work of the initial instrumentation that occurs on the server registry. Because we are using
- // ExecHarness for testing this does not get executed by the instrumentation
- def ratpackScopeManager = new RatpackScopeManager()
- spec.add(ratpackScopeManager)
- ((ContextualScopeManager) GlobalTracer.get().scopeManager())
- .addScopeContext(ratpackScopeManager)
- }, {
+ def result = ExecHarness.yieldSingle({}, {
final Scope scope =
GlobalTracer.get()
.buildSpan("ratpack.exec-test")
+ .withTag(DDTags.RESOURCE_NAME, "INSIDE-TEST")
.startActive(true)
+
+ ((TraceScope) scope).setAsyncPropagation(true)
scope.span().setBaggageItem("test-baggage", "foo")
- ParallelBatch.of(testPromise(), testPromise()).yield()
+ ParallelBatch.of(testPromise(false), testPromise(false))
+ .yield()
+ .map({ now ->
+ // close the scope now that we got the baggage inside the promises
+ scope.close()
+ return now
+ })
})
then:
result.valueOrThrow == ["foo", "foo"]
+ assertTraces(1) {
+ trace(0, 1) {
+ span(0) {
+ resourceName "INSIDE-TEST"
+ serviceName "unnamed-java-app"
+ operationName "ratpack.exec-test"
+ parent()
+ errored false
+ tags {
+ defaultTags()
+ }
+ }
+ }
+ }
}
- Promise<String> testPromise() {
+ // returns a promise that contains the active scope's "test-baggage" baggage
+ // will close an active scope if closeSpan is set to true
+ Promise<String> testPromise(boolean closeSpan = true) {
Promise.sync {
- GlobalTracer.get().activeSpan().getBaggageItem("test-baggage")
+ Scope tracerScope = GlobalTracer.get().scopeManager().active()
+ String res = tracerScope.span().getBaggageItem("test-baggage")
+ if (closeSpan) {
+ tracerScope.close()
+ }
+ return res
}
}
}

Refactor Ratpack

Remove the use of the OT project and Execution managed scopes. Updated tests.