From 6475f20308d3faa62aaff431854699187474de7a Mon Sep 17 00:00:00 2001 From: Gary Date: Fri, 9 Nov 2018 02:42:49 -0500 Subject: [PATCH] Refactor Ratpack Remove the use of the OT project and Execution managed scopes. Updated tests. --- .../ratpack-1.4/ratpack-1.4.gradle | 2 +- .../RatpackHttpClientInstrumentation.java | 3 - .../ratpack/RatpackInstrumentation.java | 8 - .../ratpack/impl/RatpackScopeManager.java | 82 ----- .../ratpack/impl/RatpackServerAdvice.java | 28 +- .../ratpack/impl/TracingHandler.java | 9 + .../src/test/groovy/RatpackTest.groovy | 315 ++++++++++++++++-- 7 files changed, 310 insertions(+), 137 deletions(-) delete mode 100644 dd-java-agent/instrumentation/ratpack-1.4/src/main/java8/datadog/trace/instrumentation/ratpack/impl/RatpackScopeManager.java diff --git a/dd-java-agent/instrumentation/ratpack-1.4/ratpack-1.4.gradle b/dd-java-agent/instrumentation/ratpack-1.4/ratpack-1.4.gradle index 8552623785..09b1ae8675 100644 --- a/dd-java-agent/instrumentation/ratpack-1.4/ratpack-1.4.gradle +++ b/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: '+' } diff --git a/dd-java-agent/instrumentation/ratpack-1.4/src/main/java/datadog/trace/instrumentation/ratpack/RatpackHttpClientInstrumentation.java b/dd-java-agent/instrumentation/ratpack-1.4/src/main/java/datadog/trace/instrumentation/ratpack/RatpackHttpClientInstrumentation.java index f438aff07c..856049aed7 100644 --- a/dd-java-agent/instrumentation/ratpack-1.4/src/main/java/datadog/trace/instrumentation/ratpack/RatpackHttpClientInstrumentation.java +++ b/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" }; } diff --git a/dd-java-agent/instrumentation/ratpack-1.4/src/main/java/datadog/trace/instrumentation/ratpack/RatpackInstrumentation.java b/dd-java-agent/instrumentation/ratpack-1.4/src/main/java/datadog/trace/instrumentation/ratpack/RatpackInstrumentation.java index 3b2e37eee9..d4eb2c91af 100644 --- a/dd-java-agent/instrumentation/ratpack-1.4/src/main/java/datadog/trace/instrumentation/ratpack/RatpackInstrumentation.java +++ b/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" diff --git a/dd-java-agent/instrumentation/ratpack-1.4/src/main/java8/datadog/trace/instrumentation/ratpack/impl/RatpackScopeManager.java b/dd-java-agent/instrumentation/ratpack-1.4/src/main/java8/datadog/trace/instrumentation/ratpack/impl/RatpackScopeManager.java deleted file mode 100644 index f21d3eec0c..0000000000 --- a/dd-java-agent/instrumentation/ratpack-1.4/src/main/java8/datadog/trace/instrumentation/ratpack/impl/RatpackScopeManager.java +++ /dev/null @@ -1,82 +0,0 @@ -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); - } - }); - } - } -} diff --git a/dd-java-agent/instrumentation/ratpack-1.4/src/main/java8/datadog/trace/instrumentation/ratpack/impl/RatpackServerAdvice.java b/dd-java-agent/instrumentation/ratpack-1.4/src/main/java8/datadog/trace/instrumentation/ratpack/impl/RatpackServerAdvice.java index 5f421bcbc3..62115e950b 100644 --- a/dd-java-agent/instrumentation/ratpack-1.4/src/main/java8/datadog/trace/instrumentation/ratpack/impl/RatpackServerAdvice.java +++ b/dd-java-agent/instrumentation/ratpack-1.4/src/main/java8/datadog/trace/instrumentation/ratpack/impl/RatpackServerAdvice.java @@ -1,6 +1,5 @@ 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 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 { 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); } diff --git a/dd-java-agent/instrumentation/ratpack-1.4/src/main/java8/datadog/trace/instrumentation/ratpack/impl/TracingHandler.java b/dd-java-agent/instrumentation/ratpack-1.4/src/main/java8/datadog/trace/instrumentation/ratpack/impl/TracingHandler.java index cb835c2de3..de2d6b414a 100644 --- a/dd-java-agent/instrumentation/ratpack-1.4/src/main/java8/datadog/trace/instrumentation/ratpack/impl/TracingHandler.java +++ b/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(); }); diff --git a/dd-java-agent/instrumentation/ratpack-1.4/src/test/groovy/RatpackTest.groovy b/dd-java-agent/instrumentation/ratpack-1.4/src/test/groovy/RatpackTest.groovy index dc96db7a97..cd930bc2d4 100644 --- a/dd-java-agent/instrumentation/ratpack-1.4/src/test/groovy/RatpackTest.groovy +++ b/dd-java-agent/instrumentation/ratpack-1.4/src/test/groovy/RatpackTest.groovy @@ -1,9 +1,10 @@ -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 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 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 } } }