From be34eaf03227424c4dfb0e921bbaaaf886e9fda4 Mon Sep 17 00:00:00 2001 From: Tyler Benson Date: Thu, 3 May 2018 12:28:07 +1000 Subject: [PATCH 1/3] Instrument HystrixCommand and HystrixThreadPool --- .../hystrix-1.3.15/hystrix-1.3.15.gradle | 29 ++++ .../HystrixCommandInstrumentation.java | 80 +++++++++ .../HystrixThreadPoolInstrumentation.java | 69 ++++++++ .../src/test/groovy/HystrixTest.groovy | 163 ++++++++++++++++++ .../trace/agent/test/ListWriterAssert.groovy | 45 +++++ .../trace/agent/test/SpanAssert.groovy | 56 ++++++ .../trace/agent/test/TagsAssert.groovy | 52 ++++++ .../trace/agent/test/TraceAssert.groovy | 47 +++++ dd-java-agent/testing/testing.gradle | 2 + settings.gradle | 1 + 10 files changed, 544 insertions(+) create mode 100644 dd-java-agent/instrumentation/hystrix-1.3.15/hystrix-1.3.15.gradle create mode 100644 dd-java-agent/instrumentation/hystrix-1.3.15/src/main/java/datadog/trace/instrumentation/hystrix/HystrixCommandInstrumentation.java create mode 100644 dd-java-agent/instrumentation/hystrix-1.3.15/src/main/java/datadog/trace/instrumentation/hystrix/HystrixThreadPoolInstrumentation.java create mode 100644 dd-java-agent/instrumentation/hystrix-1.3.15/src/test/groovy/HystrixTest.groovy create mode 100644 dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/ListWriterAssert.groovy create mode 100644 dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/SpanAssert.groovy create mode 100644 dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/TagsAssert.groovy create mode 100644 dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/TraceAssert.groovy diff --git a/dd-java-agent/instrumentation/hystrix-1.3.15/hystrix-1.3.15.gradle b/dd-java-agent/instrumentation/hystrix-1.3.15/hystrix-1.3.15.gradle new file mode 100644 index 00000000000..1e2ca09168f --- /dev/null +++ b/dd-java-agent/instrumentation/hystrix-1.3.15/hystrix-1.3.15.gradle @@ -0,0 +1,29 @@ +apply plugin: 'version-scan' + +versionScan { + group = "com.netflix.hystrix" + module = 'hystrix-core' + versions = "[1.3.15,)" + scanMethods = true + verifyPresent = [ + "com.netflix.hystrix.strategy.concurrency.HystrixContextScheduler\$ThreadPoolWorker": "schedule", + ] +} + +apply from: "${rootDir}/gradle/java.gradle" + +dependencies { +// compileOnly group: 'com.netflix.hystrix', name: 'hystrix-core', version: '1.5.12' + + compile project(':dd-trace-ot') + compile project(':dd-java-agent:agent-tooling') + + compile deps.bytebuddy + compile deps.opentracing + compile deps.autoservice + + testCompile project(':dd-java-agent:testing') + testCompile project(':dd-java-agent:instrumentation:java-concurrent') + testCompile project(':dd-java-agent:instrumentation:trace-annotation') + testCompile group: 'com.netflix.hystrix', name: 'hystrix-core', version: '1.4.0' +} diff --git a/dd-java-agent/instrumentation/hystrix-1.3.15/src/main/java/datadog/trace/instrumentation/hystrix/HystrixCommandInstrumentation.java b/dd-java-agent/instrumentation/hystrix-1.3.15/src/main/java/datadog/trace/instrumentation/hystrix/HystrixCommandInstrumentation.java new file mode 100644 index 00000000000..904f3b08f62 --- /dev/null +++ b/dd-java-agent/instrumentation/hystrix-1.3.15/src/main/java/datadog/trace/instrumentation/hystrix/HystrixCommandInstrumentation.java @@ -0,0 +1,80 @@ +package datadog.trace.instrumentation.hystrix; + +import static io.opentracing.log.Fields.ERROR_OBJECT; +import static net.bytebuddy.matcher.ElementMatchers.hasSuperType; +import static net.bytebuddy.matcher.ElementMatchers.isInterface; +import static net.bytebuddy.matcher.ElementMatchers.isMethod; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.not; + +import com.google.auto.service.AutoService; +import datadog.trace.agent.tooling.DDAdvice; +import datadog.trace.agent.tooling.DDTransformers; +import datadog.trace.agent.tooling.Instrumenter; +import io.opentracing.Scope; +import io.opentracing.Span; +import io.opentracing.tag.Tags; +import io.opentracing.util.GlobalTracer; +import java.lang.reflect.Method; +import java.util.Collections; +import net.bytebuddy.agent.builder.AgentBuilder; +import net.bytebuddy.asm.Advice; + +@AutoService(Instrumenter.class) +public class HystrixCommandInstrumentation extends Instrumenter.Configurable { + + public HystrixCommandInstrumentation() { + super("hystrix"); + } + + @Override + protected boolean defaultEnabled() { + return false; + } + + @Override + public AgentBuilder apply(final AgentBuilder agentBuilder) { + return agentBuilder + .type(not(isInterface()).and(hasSuperType(named("com.netflix.hystrix.HystrixCommand")))) + // Not adding a version restriction because this should work with any version and add some benefit. + .transform(DDTransformers.defaultTransformers()) + .transform( + DDAdvice.create() + .advice( + isMethod().and(named("run").or(named("getFallback"))), + TraceAdvice.class.getName())) + .asDecorator(); + } + + public static class TraceAdvice { + + @Advice.OnMethodEnter(suppress = Throwable.class) + public static Scope startSpan(@Advice.Origin final Method method) { + final Class declaringClass = method.getDeclaringClass(); + String className = declaringClass.getSimpleName(); + if (className.isEmpty()) { + className = declaringClass.getName(); + if (declaringClass.getPackage() != null) { + final String pkgName = declaringClass.getPackage().getName(); + if (!pkgName.isEmpty()) { + className = declaringClass.getName().replace(pkgName, "").substring(1); + } + } + } + final String operationName = className + "." + method.getName(); + + return GlobalTracer.get().buildSpan(operationName).startActive(true); + } + + @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) + public static void stopSpan( + @Advice.Enter final Scope scope, @Advice.Thrown final Throwable throwable) { + if (throwable != null) { + final Span span = scope.span(); + Tags.ERROR.set(span, true); + span.log(Collections.singletonMap(ERROR_OBJECT, throwable)); + } + scope.close(); + } + } +} diff --git a/dd-java-agent/instrumentation/hystrix-1.3.15/src/main/java/datadog/trace/instrumentation/hystrix/HystrixThreadPoolInstrumentation.java b/dd-java-agent/instrumentation/hystrix-1.3.15/src/main/java/datadog/trace/instrumentation/hystrix/HystrixThreadPoolInstrumentation.java new file mode 100644 index 00000000000..99a559e1f49 --- /dev/null +++ b/dd-java-agent/instrumentation/hystrix-1.3.15/src/main/java/datadog/trace/instrumentation/hystrix/HystrixThreadPoolInstrumentation.java @@ -0,0 +1,69 @@ +package datadog.trace.instrumentation.hystrix; + +import static net.bytebuddy.matcher.ElementMatchers.isMethod; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +import com.google.auto.service.AutoService; +import datadog.trace.agent.tooling.DDAdvice; +import datadog.trace.agent.tooling.DDTransformers; +import datadog.trace.agent.tooling.Instrumenter; +import datadog.trace.context.TraceScope; +import io.opentracing.Scope; +import io.opentracing.util.GlobalTracer; +import net.bytebuddy.agent.builder.AgentBuilder; +import net.bytebuddy.asm.Advice; + +@AutoService(Instrumenter.class) +public class HystrixThreadPoolInstrumentation extends Instrumenter.Configurable { + + public HystrixThreadPoolInstrumentation() { + super("hystrix"); + } + + @Override + protected boolean defaultEnabled() { + return false; + } + + @Override + public AgentBuilder apply(final AgentBuilder agentBuilder) { + return agentBuilder + .type( + named( + "com.netflix.hystrix.strategy.concurrency.HystrixContextScheduler$ThreadPoolWorker")) + // Not adding check for classes on the classpath because this is the only class we need. + .transform(DDTransformers.defaultTransformers()) + .transform( + DDAdvice.create() + .advice( + isMethod().and(named("schedule")).and(takesArguments(1)), + EnableAsyncAdvice.class.getName())) + .asDecorator(); + } + + public static class EnableAsyncAdvice { + + @Advice.OnMethodEnter(suppress = Throwable.class) + public static boolean enableAsyncTracking() { + final Scope scope = GlobalTracer.get().scopeManager().active(); + if (scope instanceof TraceScope) { + if (!((TraceScope) scope).isAsyncPropagating()) { + ((TraceScope) scope).setAsyncPropagation(true); + return true; + } + } + return false; + } + + @Advice.OnMethodExit(suppress = Throwable.class) + public static void disableAsyncTracking(@Advice.Enter final boolean wasEnabled) { + if (wasEnabled) { + final Scope scope = GlobalTracer.get().scopeManager().active(); + if (scope instanceof TraceScope) { + ((TraceScope) scope).setAsyncPropagation(false); + } + } + } + } +} diff --git a/dd-java-agent/instrumentation/hystrix-1.3.15/src/test/groovy/HystrixTest.groovy b/dd-java-agent/instrumentation/hystrix-1.3.15/src/test/groovy/HystrixTest.groovy new file mode 100644 index 00000000000..8aed84ca644 --- /dev/null +++ b/dd-java-agent/instrumentation/hystrix-1.3.15/src/test/groovy/HystrixTest.groovy @@ -0,0 +1,163 @@ +import com.netflix.hystrix.HystrixCommand +import datadog.trace.agent.test.AgentTestRunner +import datadog.trace.api.Trace +import spock.lang.Unroll + +import java.util.concurrent.BlockingQueue +import java.util.concurrent.LinkedBlockingQueue + +import static com.netflix.hystrix.HystrixCommandGroupKey.Factory.asKey +import static datadog.trace.agent.test.ListWriterAssert.assertTraces +import static datadog.trace.agent.test.TestUtils.runUnderTrace + +class HystrixTest extends AgentTestRunner { + static { + System.setProperty("dd.integration.hystrix.enabled", "true") + // Uncomment for debugging: +// System.setProperty("hystrix.command.default.execution.timeout.enabled", "false") + } + + @Unroll + def "test command #action"() { + setup: + def command = new HystrixCommand(asKey("ExampleGroup")) { + @Override + protected Object run() throws Exception { + return tracedMethod() + } + + @Trace + private String tracedMethod() { + return "Hello!" + } + } + def result = runUnderTrace("parent") { + operation(command) + } + expect: + result == "Hello!" + + assertTraces(TEST_WRITER, 1) { + trace(0, 3) { + span(0) { + serviceName "unnamed-java-app" + operationName "parent" + resourceName "parent" + spanType null + parent() + errored false + tags { + defaultTags() + } + } + span(1) { + serviceName "unnamed-java-app" + operationName "HystrixTest\$1.run" + resourceName "HystrixTest\$1.run" + spanType null + childOf span(0) + errored false + tags { + defaultTags() + } + } + span(2) { + serviceName "unnamed-java-app" + operationName "HystrixTest\$1.tracedMethod" + resourceName "HystrixTest\$1.tracedMethod" + spanType null + childOf span(1) + errored false + tags { + defaultTags() + } + } + } + } + + where: + action | operation + "execute" | { HystrixCommand cmd -> cmd.execute() } + "queue" | { HystrixCommand cmd -> cmd.queue().get() } + "observe" | { HystrixCommand cmd -> cmd.observe().toBlocking().first() } + "observe" | { HystrixCommand cmd -> + BlockingQueue queue = new LinkedBlockingQueue() + cmd.observe().subscribe { next -> + queue.put(next) + } + queue.poll() + } + } + + @Unroll + def "test command #action fallback"() { + setup: + def command = new HystrixCommand(asKey("ExampleGroup")) { + @Override + protected Object run() throws Exception { + throw new IllegalArgumentException() + } + + protected String getFallback() { + return "Fallback!" + } + } + def result = runUnderTrace("parent") { + operation(command) + } + expect: + result == "Fallback!" + + assertTraces(TEST_WRITER, 1) { + trace(0, 3) { + span(0) { + serviceName "unnamed-java-app" + operationName "parent" + resourceName "parent" + spanType null + parent() + errored false + tags { + defaultTags() + } + } + span(1) { + serviceName "unnamed-java-app" + operationName "HystrixTest\$2.getFallback" + resourceName "HystrixTest\$2.getFallback" + spanType null + childOf span(0) + errored false + tags { + defaultTags() + } + } + span(2) { + serviceName "unnamed-java-app" + operationName "HystrixTest\$2.run" + resourceName "HystrixTest\$2.run" + spanType null + childOf span(0) + errored true + tags { + errorTags(IllegalArgumentException) + defaultTags() + } + } + } + } + + where: + action | operation + "execute" | { HystrixCommand cmd -> cmd.execute() } + "queue" | { HystrixCommand cmd -> cmd.queue().get() } + "observe" | { HystrixCommand cmd -> cmd.observe().toBlocking().first() } + "observe" | { HystrixCommand cmd -> + BlockingQueue queue = new LinkedBlockingQueue() + cmd.observe().subscribe { next -> + queue.put(next) + } + queue.poll() + } + } +} diff --git a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/ListWriterAssert.groovy b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/ListWriterAssert.groovy new file mode 100644 index 00000000000..47589c04f74 --- /dev/null +++ b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/ListWriterAssert.groovy @@ -0,0 +1,45 @@ +package datadog.trace.agent.test + +import datadog.trace.common.writer.ListWriter + +import static datadog.trace.agent.test.TraceAssert.assertTrace + +class ListWriterAssert { + private final ListWriter writer + private final int size + private final Set assertedIndexes = new HashSet<>() + + private ListWriterAssert(writer) { + this.writer = writer + size = writer.size() + } + + static ListWriterAssert assertTraces(ListWriter writer, int expectedSize, + @DelegatesTo(value = ListWriterAssert, strategy = Closure.DELEGATE_FIRST) Closure spec) { + writer.waitForTraces(expectedSize) + assert writer.size() == expectedSize + def asserter = new ListWriterAssert(writer) + def clone = (Closure) spec.clone() + clone.delegate = asserter + clone.resolveStrategy = Closure.DELEGATE_FIRST + clone(asserter) + asserter.assertTracesAllVerified() + asserter + } + + TraceAssert trace(int index, int expectedSize, + @DelegatesTo(value = TraceAssert, strategy = Closure.DELEGATE_FIRST) Closure spec) { + if (index >= size) { + throw new ArrayIndexOutOfBoundsException(index) + } + if (writer.size() != size) { + throw new ConcurrentModificationException("ListWriter modified during assertion") + } + assertedIndexes.add(index) + assertTrace(writer.get(index), expectedSize, spec) + } + + void assertTracesAllVerified() { + assert assertedIndexes.size() == size + } +} diff --git a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/SpanAssert.groovy b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/SpanAssert.groovy new file mode 100644 index 00000000000..3b44546af7d --- /dev/null +++ b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/SpanAssert.groovy @@ -0,0 +1,56 @@ +package datadog.trace.agent.test + +import datadog.opentracing.DDSpan + +import static datadog.trace.agent.test.TagsAssert.assertTags + +class SpanAssert { + private final DDSpan span + + private SpanAssert(span) { + this.span = span + } + + static SpanAssert assertSpan(DDSpan span, + @DelegatesTo(value = SpanAssert, strategy = Closure.DELEGATE_FIRST) Closure spec) { + def asserter = new SpanAssert(span) + def clone = (Closure) spec.clone() + clone.delegate = asserter + clone.resolveStrategy = Closure.DELEGATE_FIRST + clone(asserter) + asserter + } + + def serviceName(String name) { + assert span.serviceName == name + } + + def operationName(String name) { + assert span.operationName == name + } + + def resourceName(String name) { + assert span.resourceName == name + } + + def spanType(String type) { + assert span.spanType == type + } + + def parent() { + assert span.parentId == 0 + } + + def childOf(DDSpan parent) { + assert span.parentId == parent.spanId + assert span.traceId == parent.traceId + } + + def errored(boolean errored) { + assert span.isError() == errored + } + + def tags(@DelegatesTo(value = TagsAssert, strategy = Closure.DELEGATE_FIRST) Closure spec) { + return assertTags(span, spec) + } +} diff --git a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/TagsAssert.groovy b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/TagsAssert.groovy new file mode 100644 index 00000000000..54a0f76e821 --- /dev/null +++ b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/TagsAssert.groovy @@ -0,0 +1,52 @@ +package datadog.trace.agent.test + +import datadog.opentracing.DDSpan + +class TagsAssert { + private final Map tags + private final Set assertedTags = new HashSet<>() + + private TagsAssert(DDSpan span) { + this.tags = span.tags + } + + static TagsAssert assertTags(DDSpan span, + @DelegatesTo(value = TagsAssert, strategy = Closure.DELEGATE_FIRST) Closure spec) { + def asserter = new TagsAssert(span) + def clone = (Closure) spec.clone() + clone.delegate = asserter + clone.resolveStrategy = Closure.DELEGATE_FIRST + clone(asserter) + asserter.assertTracesAllVerified() + asserter + } + + def defaultTags() { + assertedTags.add("thread.name") + assertedTags.add("thread.id") + + tags["thread.name"] != null + tags["thread.id"] != null + } + + def errorTags(Class errorType) { + assertedTags.add("error") + assertedTags.add("error.type") + assertedTags.add("error.stack") + + tags["error"] == true + tags["error.type"] == errorType + tags["error.stack"] instanceof String + } + + def methodMissing(String name, args) { + if (args.length > 1) { + throw new IllegalArgumentException(args) + } + assert tags[name] == args[0] + } + + void assertTracesAllVerified() { + assert tags.keySet() == assertedTags + } +} diff --git a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/TraceAssert.groovy b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/TraceAssert.groovy new file mode 100644 index 00000000000..99301e80bc9 --- /dev/null +++ b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/TraceAssert.groovy @@ -0,0 +1,47 @@ +package datadog.trace.agent.test + +import datadog.opentracing.DDSpan + +import static datadog.trace.agent.test.SpanAssert.assertSpan + +class TraceAssert { + private final List trace + private final int size + private final Set assertedIndexes = new HashSet<>() + + private TraceAssert(trace) { + this.trace = trace + size = trace.size() + } + + static TraceAssert assertTrace(List trace, int expectedSize, + @DelegatesTo(value = File, strategy = Closure.DELEGATE_FIRST) Closure spec) { + assert trace.size() == expectedSize + def asserter = new TraceAssert(trace) + def clone = (Closure) spec.clone() + clone.delegate = asserter + clone.resolveStrategy = Closure.DELEGATE_FIRST + clone(asserter) + asserter.assertTracesAllVerified() + asserter + } + + DDSpan span(int index) { + trace.get(index) + } + + SpanAssert span(int index, @DelegatesTo(value = SpanAssert, strategy = Closure.DELEGATE_FIRST) Closure spec) { + if (index >= size) { + throw new ArrayIndexOutOfBoundsException(index) + } + if (trace.size() != size) { + throw new ConcurrentModificationException("Trace modified during assertion") + } + assertedIndexes.add(index) + assertSpan(trace.get(index), spec) + } + + void assertTracesAllVerified() { + assert assertedIndexes.size() == size + } +} diff --git a/dd-java-agent/testing/testing.gradle b/dd-java-agent/testing/testing.gradle index 83f4c924f92..f4bdbf6ae84 100644 --- a/dd-java-agent/testing/testing.gradle +++ b/dd-java-agent/testing/testing.gradle @@ -11,6 +11,8 @@ dependencies { compile project(':dd-trace-ot') compile project(':dd-java-agent:agent-tooling') + compile deps.groovy + // test instrumenting java 1.1 bytecode testCompile group: 'net.sf.jt400', name: 'jt400', version: '6.1' } diff --git a/settings.gradle b/settings.gradle index 97f4a07d4a0..4834eae002b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -13,6 +13,7 @@ include ':dd-java-agent:instrumentation:apache-httpclient-4.3' include ':dd-java-agent:instrumentation:aws-sdk' include ':dd-java-agent:instrumentation:classloaders' include ':dd-java-agent:instrumentation:datastax-cassandra-3.2' +include ':dd-java-agent:instrumentation:hystrix-1.3.15' include ':dd-java-agent:instrumentation:jax-rs-annotations' include ':dd-java-agent:instrumentation:jax-rs-client' include ':dd-java-agent:instrumentation:java-concurrent' From 2561e72824882ec6613a03fa7b98f34dfa29add1 Mon Sep 17 00:00:00 2001 From: Tyler Benson Date: Thu, 3 May 2018 13:57:33 +1000 Subject: [PATCH 2/3] Do we do want to ignore proxies? If so, we have to change the test to be compatible. --- .../datadog/trace/agent/tooling/AgentInstaller.java | 2 +- .../jms-1/src/test/groovy/JMS1Test.groovy | 11 ++++++++--- .../jms-2/src/test/groovy/JMS2Test.groovy | 11 ++++++++--- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/AgentInstaller.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/AgentInstaller.java index 41915f74791..645efa97202 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/AgentInstaller.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/AgentInstaller.java @@ -48,7 +48,7 @@ public static ResettableClassFileTransformer installBytebuddyAgent( .or(nameStartsWith("datadog.opentracing.")) .or(nameStartsWith("datadog.slf4j.")) .or(nameStartsWith("java.").and(not(nameStartsWith("java.util.concurrent.")))) - .or(nameStartsWith("com.sun.").and(not(nameStartsWith("com.sun.proxy.")))) + .or(nameStartsWith("com.sun.")) .or(nameStartsWith("sun.")) .or(nameStartsWith("jdk.")) .or(nameStartsWith("org.aspectj.")) diff --git a/dd-java-agent/instrumentation/jms-1/src/test/groovy/JMS1Test.groovy b/dd-java-agent/instrumentation/jms-1/src/test/groovy/JMS1Test.groovy index 0467557fa33..9156517897b 100644 --- a/dd-java-agent/instrumentation/jms-1/src/test/groovy/JMS1Test.groovy +++ b/dd-java-agent/instrumentation/jms-1/src/test/groovy/JMS1Test.groovy @@ -8,6 +8,8 @@ import spock.lang.Shared import spock.lang.Unroll import javax.jms.Connection +import javax.jms.Message +import javax.jms.MessageListener import javax.jms.Session import javax.jms.TextMessage import java.util.concurrent.CountDownLatch @@ -152,9 +154,12 @@ class JMS1Test extends AgentTestRunner { def messageRef = new AtomicReference() def producer = session.createProducer(destination) def consumer = session.createConsumer(destination) - consumer.setMessageListener { message -> - lock.await() // ensure the producer trace is reported first. - messageRef.set(message) + consumer.setMessageListener new MessageListener() { + @Override + void onMessage(Message message) { + lock.await() // ensure the producer trace is reported first. + messageRef.set(message) + } } def message = session.createTextMessage("a message") diff --git a/dd-java-agent/instrumentation/jms-2/src/test/groovy/JMS2Test.groovy b/dd-java-agent/instrumentation/jms-2/src/test/groovy/JMS2Test.groovy index 795a22f599e..8a3f2b0500d 100644 --- a/dd-java-agent/instrumentation/jms-2/src/test/groovy/JMS2Test.groovy +++ b/dd-java-agent/instrumentation/jms-2/src/test/groovy/JMS2Test.groovy @@ -17,6 +17,8 @@ import org.hornetq.jms.client.HornetQMessageProducer import spock.lang.Shared import spock.lang.Unroll +import javax.jms.Message +import javax.jms.MessageListener import javax.jms.Session import javax.jms.TextMessage import java.util.concurrent.CountDownLatch @@ -143,9 +145,12 @@ class JMS2Test extends AgentTestRunner { def messageRef = new AtomicReference() def producer = session.createProducer(destination) def consumer = session.createConsumer(destination) - consumer.setMessageListener { message -> - lock.await() // ensure the producer trace is reported first. - messageRef.set(message) + consumer.setMessageListener new MessageListener() { + @Override + void onMessage(Message message) { + lock.await() // ensure the producer trace is reported first. + messageRef.set(message) + } } def message = session.createTextMessage("a message") From 660dfc834c51da683202d9e5a0b6f90fb08ca3d1 Mon Sep 17 00:00:00 2001 From: Tyler Benson Date: Fri, 4 May 2018 12:08:11 +1000 Subject: [PATCH 3/3] =?UTF-8?q?It=20actually=20isn=E2=80=99t=20compatable?= =?UTF-8?q?=20until=201.4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hystrix-1.3.15.gradle => hystrix-1.4/hystrix-1.4.gradle} | 5 ++--- .../hystrix/HystrixCommandInstrumentation.java | 0 .../hystrix/HystrixThreadPoolInstrumentation.java | 5 +++-- .../src/test/groovy/HystrixTest.groovy | 0 settings.gradle | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) rename dd-java-agent/instrumentation/{hystrix-1.3.15/hystrix-1.3.15.gradle => hystrix-1.4/hystrix-1.4.gradle} (82%) rename dd-java-agent/instrumentation/{hystrix-1.3.15 => hystrix-1.4}/src/main/java/datadog/trace/instrumentation/hystrix/HystrixCommandInstrumentation.java (100%) rename dd-java-agent/instrumentation/{hystrix-1.3.15 => hystrix-1.4}/src/main/java/datadog/trace/instrumentation/hystrix/HystrixThreadPoolInstrumentation.java (91%) rename dd-java-agent/instrumentation/{hystrix-1.3.15 => hystrix-1.4}/src/test/groovy/HystrixTest.groovy (100%) diff --git a/dd-java-agent/instrumentation/hystrix-1.3.15/hystrix-1.3.15.gradle b/dd-java-agent/instrumentation/hystrix-1.4/hystrix-1.4.gradle similarity index 82% rename from dd-java-agent/instrumentation/hystrix-1.3.15/hystrix-1.3.15.gradle rename to dd-java-agent/instrumentation/hystrix-1.4/hystrix-1.4.gradle index 1e2ca09168f..1c6ab359dbc 100644 --- a/dd-java-agent/instrumentation/hystrix-1.3.15/hystrix-1.3.15.gradle +++ b/dd-java-agent/instrumentation/hystrix-1.4/hystrix-1.4.gradle @@ -3,10 +3,9 @@ apply plugin: 'version-scan' versionScan { group = "com.netflix.hystrix" module = 'hystrix-core' - versions = "[1.3.15,)" - scanMethods = true + versions = "[1.4.0,)" verifyPresent = [ - "com.netflix.hystrix.strategy.concurrency.HystrixContextScheduler\$ThreadPoolWorker": "schedule", + "com.netflix.hystrix.AbstractCommand": null, ] } diff --git a/dd-java-agent/instrumentation/hystrix-1.3.15/src/main/java/datadog/trace/instrumentation/hystrix/HystrixCommandInstrumentation.java b/dd-java-agent/instrumentation/hystrix-1.4/src/main/java/datadog/trace/instrumentation/hystrix/HystrixCommandInstrumentation.java similarity index 100% rename from dd-java-agent/instrumentation/hystrix-1.3.15/src/main/java/datadog/trace/instrumentation/hystrix/HystrixCommandInstrumentation.java rename to dd-java-agent/instrumentation/hystrix-1.4/src/main/java/datadog/trace/instrumentation/hystrix/HystrixCommandInstrumentation.java diff --git a/dd-java-agent/instrumentation/hystrix-1.3.15/src/main/java/datadog/trace/instrumentation/hystrix/HystrixThreadPoolInstrumentation.java b/dd-java-agent/instrumentation/hystrix-1.4/src/main/java/datadog/trace/instrumentation/hystrix/HystrixThreadPoolInstrumentation.java similarity index 91% rename from dd-java-agent/instrumentation/hystrix-1.3.15/src/main/java/datadog/trace/instrumentation/hystrix/HystrixThreadPoolInstrumentation.java rename to dd-java-agent/instrumentation/hystrix-1.4/src/main/java/datadog/trace/instrumentation/hystrix/HystrixThreadPoolInstrumentation.java index 99a559e1f49..290bc418f1c 100644 --- a/dd-java-agent/instrumentation/hystrix-1.3.15/src/main/java/datadog/trace/instrumentation/hystrix/HystrixThreadPoolInstrumentation.java +++ b/dd-java-agent/instrumentation/hystrix-1.4/src/main/java/datadog/trace/instrumentation/hystrix/HystrixThreadPoolInstrumentation.java @@ -1,5 +1,6 @@ package datadog.trace.instrumentation.hystrix; +import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.takesArguments; @@ -31,8 +32,8 @@ public AgentBuilder apply(final AgentBuilder agentBuilder) { return agentBuilder .type( named( - "com.netflix.hystrix.strategy.concurrency.HystrixContextScheduler$ThreadPoolWorker")) - // Not adding check for classes on the classpath because this is the only class we need. + "com.netflix.hystrix.strategy.concurrency.HystrixContextScheduler$ThreadPoolWorker"), + classLoaderHasClasses("com.netflix.hystrix.AbstractCommand")) .transform(DDTransformers.defaultTransformers()) .transform( DDAdvice.create() diff --git a/dd-java-agent/instrumentation/hystrix-1.3.15/src/test/groovy/HystrixTest.groovy b/dd-java-agent/instrumentation/hystrix-1.4/src/test/groovy/HystrixTest.groovy similarity index 100% rename from dd-java-agent/instrumentation/hystrix-1.3.15/src/test/groovy/HystrixTest.groovy rename to dd-java-agent/instrumentation/hystrix-1.4/src/test/groovy/HystrixTest.groovy diff --git a/settings.gradle b/settings.gradle index 4834eae002b..359750c5c9b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -13,7 +13,7 @@ include ':dd-java-agent:instrumentation:apache-httpclient-4.3' include ':dd-java-agent:instrumentation:aws-sdk' include ':dd-java-agent:instrumentation:classloaders' include ':dd-java-agent:instrumentation:datastax-cassandra-3.2' -include ':dd-java-agent:instrumentation:hystrix-1.3.15' +include ':dd-java-agent:instrumentation:hystrix-1.4' include ':dd-java-agent:instrumentation:jax-rs-annotations' include ':dd-java-agent:instrumentation:jax-rs-client' include ':dd-java-agent:instrumentation:java-concurrent'