Merge pull request #473 from DataDog/tyler/combine-jms
Make JMS more resilent to property failure
This commit is contained in:
commit
96e02301f8
|
@ -16,11 +16,16 @@ import net.bytebuddy.pool.TypePool;
|
||||||
/**
|
/**
|
||||||
* Custom Pool strategy.
|
* Custom Pool strategy.
|
||||||
*
|
*
|
||||||
* <p>Here we are using WeakMap.Provider as the backing ClassLoader -> CacheProvider lookup. We also
|
* <p>Here we are using WeakMap.Provider as the backing ClassLoader -> CacheProvider lookup.
|
||||||
* use our bootstrap proxy when matching against the bootstrap loader.
|
|
||||||
*
|
*
|
||||||
* <p>The CacheProvider is also a custom implementation that uses guava's cache to evict. See
|
* <p>We also use our bootstrap proxy when matching against the bootstrap loader.
|
||||||
* eviction policy below.
|
*
|
||||||
|
* <p>The CacheProvider is also a custom implementation that uses guava's cache to evict.
|
||||||
|
*
|
||||||
|
* <p>By eviciting from the cache we are able to reduce the memory overhead of the agent for apps
|
||||||
|
* that have many classes.
|
||||||
|
*
|
||||||
|
* <p>See eviction policy below.
|
||||||
*/
|
*/
|
||||||
public class DDCachingPoolStrategy implements PoolStrategy {
|
public class DDCachingPoolStrategy implements PoolStrategy {
|
||||||
private static final WeakMap<ClassLoader, TypePool.CacheProvider> typePoolCache =
|
private static final WeakMap<ClassLoader, TypePool.CacheProvider> typePoolCache =
|
||||||
|
|
|
@ -1,125 +0,0 @@
|
||||||
package datadog.trace.instrumentation.jms1;
|
|
||||||
|
|
||||||
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
|
|
||||||
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
|
|
||||||
import static datadog.trace.instrumentation.jms.util.JmsUtil.toResourceName;
|
|
||||||
import static io.opentracing.log.Fields.ERROR_OBJECT;
|
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
|
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
|
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.not;
|
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
|
|
||||||
|
|
||||||
import com.google.auto.service.AutoService;
|
|
||||||
import datadog.trace.agent.tooling.Instrumenter;
|
|
||||||
import datadog.trace.api.DDSpanTypes;
|
|
||||||
import datadog.trace.api.DDTags;
|
|
||||||
import datadog.trace.instrumentation.jms.util.MessagePropertyTextMap;
|
|
||||||
import io.opentracing.Scope;
|
|
||||||
import io.opentracing.Span;
|
|
||||||
import io.opentracing.SpanContext;
|
|
||||||
import io.opentracing.Tracer;
|
|
||||||
import io.opentracing.propagation.Format;
|
|
||||||
import io.opentracing.tag.Tags;
|
|
||||||
import io.opentracing.util.GlobalTracer;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import javax.jms.Message;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import net.bytebuddy.asm.Advice;
|
|
||||||
import net.bytebuddy.description.type.TypeDescription;
|
|
||||||
import net.bytebuddy.matcher.ElementMatcher;
|
|
||||||
|
|
||||||
@AutoService(Instrumenter.class)
|
|
||||||
public final class JMS1MessageConsumerInstrumentation extends Instrumenter.Default {
|
|
||||||
public static final String[] JMS1_HELPER_CLASS_NAMES =
|
|
||||||
new String[] {
|
|
||||||
"datadog.trace.instrumentation.jms.util.JmsUtil",
|
|
||||||
"datadog.trace.instrumentation.jms.util.MessagePropertyTextMap"
|
|
||||||
};
|
|
||||||
|
|
||||||
public JMS1MessageConsumerInstrumentation() {
|
|
||||||
super("jms", "jms-1");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ElementMatcher<TypeDescription> typeMatcher() {
|
|
||||||
return not(isInterface()).and(safeHasSuperType(named("javax.jms.MessageConsumer")));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ElementMatcher<ClassLoader> classLoaderMatcher() {
|
|
||||||
return not(classLoaderHasClasses("javax.jms.JMSContext", "javax.jms.CompletionListener"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] helperClassNames() {
|
|
||||||
return JMS1_HELPER_CLASS_NAMES;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<ElementMatcher, String> transformers() {
|
|
||||||
final Map<ElementMatcher, String> transformers = new HashMap<>();
|
|
||||||
transformers.put(
|
|
||||||
named("receive").and(takesArguments(0).or(takesArguments(1))).and(isPublic()),
|
|
||||||
ConsumerAdvice.class.getName());
|
|
||||||
transformers.put(
|
|
||||||
named("receiveNoWait").and(takesArguments(0)).and(isPublic()),
|
|
||||||
ConsumerAdvice.class.getName());
|
|
||||||
return transformers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ConsumerAdvice {
|
|
||||||
|
|
||||||
@Advice.OnMethodEnter
|
|
||||||
public static long startSpan() {
|
|
||||||
return System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
|
||||||
public static void stopSpan(
|
|
||||||
@Advice.This final MessageConsumer consumer,
|
|
||||||
@Advice.Enter final long startTime,
|
|
||||||
@Advice.Origin final Method method,
|
|
||||||
@Advice.Return final Message message,
|
|
||||||
@Advice.Thrown final Throwable throwable) {
|
|
||||||
Tracer.SpanBuilder spanBuilder =
|
|
||||||
GlobalTracer.get()
|
|
||||||
.buildSpan("jms.consume")
|
|
||||||
.withTag(DDTags.SERVICE_NAME, "jms")
|
|
||||||
.withTag(DDTags.SPAN_TYPE, DDSpanTypes.MESSAGE_CONSUMER)
|
|
||||||
.withTag(Tags.COMPONENT.getKey(), "jms1")
|
|
||||||
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CONSUMER)
|
|
||||||
.withTag("span.origin.type", consumer.getClass().getName())
|
|
||||||
.withStartTimestamp(TimeUnit.MILLISECONDS.toMicros(startTime));
|
|
||||||
|
|
||||||
if (message == null) {
|
|
||||||
spanBuilder = spanBuilder.withTag(DDTags.RESOURCE_NAME, "JMS " + method.getName());
|
|
||||||
} else {
|
|
||||||
spanBuilder =
|
|
||||||
spanBuilder.withTag(
|
|
||||||
DDTags.RESOURCE_NAME, "Consumed from " + toResourceName(message, null));
|
|
||||||
|
|
||||||
final SpanContext extractedContext =
|
|
||||||
GlobalTracer.get()
|
|
||||||
.extract(Format.Builtin.TEXT_MAP, new MessagePropertyTextMap(message));
|
|
||||||
if (extractedContext != null) {
|
|
||||||
spanBuilder = spanBuilder.asChildOf(extractedContext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final Scope scope = spanBuilder.startActive(true);
|
|
||||||
final Span span = scope.span();
|
|
||||||
|
|
||||||
if (throwable != null) {
|
|
||||||
Tags.ERROR.set(span, Boolean.TRUE);
|
|
||||||
span.log(Collections.singletonMap(ERROR_OBJECT, throwable));
|
|
||||||
}
|
|
||||||
|
|
||||||
scope.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,107 +0,0 @@
|
||||||
package datadog.trace.instrumentation.jms1;
|
|
||||||
|
|
||||||
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
|
|
||||||
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
|
|
||||||
import static datadog.trace.instrumentation.jms.util.JmsUtil.toResourceName;
|
|
||||||
import static io.opentracing.log.Fields.ERROR_OBJECT;
|
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
|
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
|
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.not;
|
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
|
|
||||||
|
|
||||||
import com.google.auto.service.AutoService;
|
|
||||||
import datadog.trace.agent.tooling.Instrumenter;
|
|
||||||
import datadog.trace.api.DDSpanTypes;
|
|
||||||
import datadog.trace.api.DDTags;
|
|
||||||
import datadog.trace.context.TraceScope;
|
|
||||||
import datadog.trace.instrumentation.jms.util.MessagePropertyTextMap;
|
|
||||||
import io.opentracing.Scope;
|
|
||||||
import io.opentracing.Span;
|
|
||||||
import io.opentracing.SpanContext;
|
|
||||||
import io.opentracing.propagation.Format;
|
|
||||||
import io.opentracing.tag.Tags;
|
|
||||||
import io.opentracing.util.GlobalTracer;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import javax.jms.Message;
|
|
||||||
import javax.jms.MessageListener;
|
|
||||||
import net.bytebuddy.asm.Advice;
|
|
||||||
import net.bytebuddy.description.type.TypeDescription;
|
|
||||||
import net.bytebuddy.matcher.ElementMatcher;
|
|
||||||
|
|
||||||
@AutoService(Instrumenter.class)
|
|
||||||
public final class JMS1MessageListenerInstrumentation extends Instrumenter.Default {
|
|
||||||
|
|
||||||
public JMS1MessageListenerInstrumentation() {
|
|
||||||
super("jms", "jms-1");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ElementMatcher<TypeDescription> typeMatcher() {
|
|
||||||
return not(isInterface()).and(safeHasSuperType(named("javax.jms.MessageListener")));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ElementMatcher<ClassLoader> classLoaderMatcher() {
|
|
||||||
return not(classLoaderHasClasses("javax.jms.JMSContext", "javax.jms.CompletionListener"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] helperClassNames() {
|
|
||||||
return JMS1MessageConsumerInstrumentation.JMS1_HELPER_CLASS_NAMES;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<ElementMatcher, String> transformers() {
|
|
||||||
final Map<ElementMatcher, String> transformers = new HashMap<>();
|
|
||||||
transformers.put(
|
|
||||||
named("onMessage").and(takesArgument(0, named("javax.jms.Message"))).and(isPublic()),
|
|
||||||
MessageListenerAdvice.class.getName());
|
|
||||||
return transformers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class MessageListenerAdvice {
|
|
||||||
|
|
||||||
@Advice.OnMethodEnter(suppress = Throwable.class)
|
|
||||||
public static Scope startSpan(
|
|
||||||
@Advice.Argument(0) final Message message, @Advice.This final MessageListener listener) {
|
|
||||||
|
|
||||||
final SpanContext extractedContext =
|
|
||||||
GlobalTracer.get().extract(Format.Builtin.TEXT_MAP, new MessagePropertyTextMap(message));
|
|
||||||
|
|
||||||
final Scope scope =
|
|
||||||
GlobalTracer.get()
|
|
||||||
.buildSpan("jms.onMessage")
|
|
||||||
.asChildOf(extractedContext)
|
|
||||||
.withTag(DDTags.SERVICE_NAME, "jms")
|
|
||||||
.withTag(DDTags.SPAN_TYPE, DDSpanTypes.MESSAGE_CONSUMER)
|
|
||||||
.withTag(DDTags.RESOURCE_NAME, "Received from " + toResourceName(message, null))
|
|
||||||
.withTag(Tags.COMPONENT.getKey(), "jms1")
|
|
||||||
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CONSUMER)
|
|
||||||
.withTag("span.origin.type", listener.getClass().getName())
|
|
||||||
.startActive(true);
|
|
||||||
|
|
||||||
if (scope instanceof TraceScope) {
|
|
||||||
((TraceScope) scope).setAsyncPropagation(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return scope;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
|
||||||
public static void stopSpan(
|
|
||||||
@Advice.Enter final Scope scope, @Advice.Thrown final Throwable throwable) {
|
|
||||||
|
|
||||||
if (scope != null) {
|
|
||||||
if (throwable != null) {
|
|
||||||
final Span span = scope.span();
|
|
||||||
Tags.ERROR.set(span, Boolean.TRUE);
|
|
||||||
span.log(Collections.singletonMap(ERROR_OBJECT, throwable));
|
|
||||||
}
|
|
||||||
scope.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,156 +0,0 @@
|
||||||
package datadog.trace.instrumentation.jms1;
|
|
||||||
|
|
||||||
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
|
|
||||||
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
|
|
||||||
import static datadog.trace.instrumentation.jms.util.JmsUtil.toResourceName;
|
|
||||||
import static io.opentracing.log.Fields.ERROR_OBJECT;
|
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
|
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
|
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.not;
|
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
|
|
||||||
|
|
||||||
import com.google.auto.service.AutoService;
|
|
||||||
import datadog.trace.agent.tooling.Instrumenter;
|
|
||||||
import datadog.trace.api.DDSpanTypes;
|
|
||||||
import datadog.trace.api.DDTags;
|
|
||||||
import datadog.trace.instrumentation.jms.util.MessagePropertyTextMap;
|
|
||||||
import io.opentracing.Scope;
|
|
||||||
import io.opentracing.Span;
|
|
||||||
import io.opentracing.propagation.Format;
|
|
||||||
import io.opentracing.tag.Tags;
|
|
||||||
import io.opentracing.util.GlobalTracer;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import javax.jms.Destination;
|
|
||||||
import javax.jms.JMSException;
|
|
||||||
import javax.jms.Message;
|
|
||||||
import javax.jms.MessageProducer;
|
|
||||||
import net.bytebuddy.asm.Advice;
|
|
||||||
import net.bytebuddy.description.type.TypeDescription;
|
|
||||||
import net.bytebuddy.matcher.ElementMatcher;
|
|
||||||
|
|
||||||
@AutoService(Instrumenter.class)
|
|
||||||
public final class JMS1MessageProducerInstrumentation extends Instrumenter.Default {
|
|
||||||
|
|
||||||
public JMS1MessageProducerInstrumentation() {
|
|
||||||
super("jms", "jms-1");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ElementMatcher<TypeDescription> typeMatcher() {
|
|
||||||
return not(isInterface()).and(safeHasSuperType(named("javax.jms.MessageProducer")));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ElementMatcher<ClassLoader> classLoaderMatcher() {
|
|
||||||
return not(classLoaderHasClasses("javax.jms.JMSContext", "javax.jms.CompletionListener"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] helperClassNames() {
|
|
||||||
return JMS1MessageConsumerInstrumentation.JMS1_HELPER_CLASS_NAMES;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<ElementMatcher, String> transformers() {
|
|
||||||
final Map<ElementMatcher, String> transformers = new HashMap<>();
|
|
||||||
transformers.put(
|
|
||||||
named("send").and(takesArgument(0, named("javax.jms.Message"))).and(isPublic()),
|
|
||||||
ProducerAdvice.class.getName());
|
|
||||||
transformers.put(
|
|
||||||
named("send")
|
|
||||||
.and(takesArgument(0, named("javax.jms.Destination")))
|
|
||||||
.and(takesArgument(1, named("javax.jms.Message")))
|
|
||||||
.and(isPublic()),
|
|
||||||
ProducerWithDestinationAdvice.class.getName());
|
|
||||||
return transformers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ProducerAdvice {
|
|
||||||
|
|
||||||
@Advice.OnMethodEnter(suppress = Throwable.class)
|
|
||||||
public static Scope startSpan(
|
|
||||||
@Advice.Argument(0) final Message message, @Advice.This final MessageProducer producer) {
|
|
||||||
Destination defaultDestination;
|
|
||||||
try {
|
|
||||||
defaultDestination = producer.getDestination();
|
|
||||||
} catch (final JMSException e) {
|
|
||||||
defaultDestination = null;
|
|
||||||
}
|
|
||||||
final Scope scope =
|
|
||||||
GlobalTracer.get()
|
|
||||||
.buildSpan("jms.produce")
|
|
||||||
.withTag(DDTags.SERVICE_NAME, "jms")
|
|
||||||
.withTag(
|
|
||||||
DDTags.RESOURCE_NAME,
|
|
||||||
"Produced for " + toResourceName(message, defaultDestination))
|
|
||||||
.withTag(Tags.COMPONENT.getKey(), "jms1")
|
|
||||||
.withTag(DDTags.SPAN_TYPE, DDSpanTypes.MESSAGE_PRODUCER)
|
|
||||||
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_PRODUCER)
|
|
||||||
.withTag("span.origin.type", producer.getClass().getName())
|
|
||||||
.startActive(true);
|
|
||||||
|
|
||||||
GlobalTracer.get()
|
|
||||||
.inject(
|
|
||||||
scope.span().context(), Format.Builtin.TEXT_MAP, new MessagePropertyTextMap(message));
|
|
||||||
|
|
||||||
return scope;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
|
||||||
public static void stopSpan(
|
|
||||||
@Advice.Enter final Scope scope, @Advice.Thrown final Throwable throwable) {
|
|
||||||
|
|
||||||
if (scope != null) {
|
|
||||||
if (throwable != null) {
|
|
||||||
final Span span = scope.span();
|
|
||||||
Tags.ERROR.set(span, Boolean.TRUE);
|
|
||||||
span.log(Collections.singletonMap(ERROR_OBJECT, throwable));
|
|
||||||
}
|
|
||||||
scope.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ProducerWithDestinationAdvice {
|
|
||||||
|
|
||||||
@Advice.OnMethodEnter(suppress = Throwable.class)
|
|
||||||
public static Scope startSpan(
|
|
||||||
@Advice.Argument(0) final Destination destination,
|
|
||||||
@Advice.Argument(1) final Message message,
|
|
||||||
@Advice.This final MessageProducer producer) {
|
|
||||||
final Scope scope =
|
|
||||||
GlobalTracer.get()
|
|
||||||
.buildSpan("jms.produce")
|
|
||||||
.withTag(DDTags.SERVICE_NAME, "jms")
|
|
||||||
.withTag(DDTags.SPAN_TYPE, DDSpanTypes.MESSAGE_PRODUCER)
|
|
||||||
.withTag(DDTags.RESOURCE_NAME, "Produced for " + toResourceName(message, destination))
|
|
||||||
.withTag(Tags.COMPONENT.getKey(), "jms1")
|
|
||||||
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_PRODUCER)
|
|
||||||
.withTag("span.origin.type", producer.getClass().getName())
|
|
||||||
.startActive(true);
|
|
||||||
|
|
||||||
GlobalTracer.get()
|
|
||||||
.inject(
|
|
||||||
scope.span().context(), Format.Builtin.TEXT_MAP, new MessagePropertyTextMap(message));
|
|
||||||
|
|
||||||
return scope;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
|
||||||
public static void stopSpan(
|
|
||||||
@Advice.Enter final Scope scope, @Advice.Thrown final Throwable throwable) {
|
|
||||||
|
|
||||||
if (scope != null) {
|
|
||||||
if (throwable != null) {
|
|
||||||
final Span span = scope.span();
|
|
||||||
Tags.ERROR.set(span, Boolean.TRUE);
|
|
||||||
span.log(Collections.singletonMap(ERROR_OBJECT, throwable));
|
|
||||||
}
|
|
||||||
scope.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
apply plugin: 'version-scan'
|
|
||||||
|
|
||||||
versionScan {
|
|
||||||
group = "javax.jms"
|
|
||||||
module = "javax.jms-api"
|
|
||||||
versions = "[2,)"
|
|
||||||
legacyModule = "jms-api"
|
|
||||||
verifyPresent = [
|
|
||||||
"javax.jms.JMSContext" : null,
|
|
||||||
"javax.jms.CompletionListener": null,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
apply from: "${rootDir}/gradle/java.gradle"
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
// use jms1 helpers
|
|
||||||
compile(project(':dd-java-agent:instrumentation:jms-1')) {
|
|
||||||
transitive = false
|
|
||||||
}
|
|
||||||
compileOnly group: 'javax.jms', name: 'javax.jms-api', version: '2.0.1'
|
|
||||||
|
|
||||||
compile deps.bytebuddy
|
|
||||||
compile deps.opentracing
|
|
||||||
annotationProcessor deps.autoservice
|
|
||||||
implementation deps.autoservice
|
|
||||||
|
|
||||||
compile project(':dd-java-agent:agent-tooling')
|
|
||||||
|
|
||||||
testCompile project(':dd-java-agent:testing')
|
|
||||||
testCompile group: 'org.hornetq', name: 'hornetq-jms-client', version: '2.4.7.Final'
|
|
||||||
testCompile group: 'org.hornetq', name: 'hornetq-jms-server', version: '2.4.7.Final'
|
|
||||||
|
|
||||||
}
|
|
|
@ -11,8 +11,28 @@ versionScan {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
muzzle {
|
||||||
|
pass {
|
||||||
|
group = "javax.jms"
|
||||||
|
module = "jms-api"
|
||||||
|
versions = "(,)"
|
||||||
|
}
|
||||||
|
pass {
|
||||||
|
group = "javax.jms"
|
||||||
|
module = "javax.jms-api"
|
||||||
|
versions = "(,)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
apply from: "${rootDir}/gradle/java.gradle"
|
apply from: "${rootDir}/gradle/java.gradle"
|
||||||
|
|
||||||
|
apply plugin: 'org.unbroken-dome.test-sets'
|
||||||
|
|
||||||
|
testSets {
|
||||||
|
latestDepTest {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly group: 'javax.jms', name: 'jms-api', version: '1.1-rev-1'
|
compileOnly group: 'javax.jms', name: 'jms-api', version: '1.1-rev-1'
|
||||||
|
|
||||||
|
@ -27,4 +47,7 @@ dependencies {
|
||||||
testCompile group: 'org.apache.activemq.tooling', name: 'activemq-junit', version: '5.14.5'
|
testCompile group: 'org.apache.activemq.tooling', name: 'activemq-junit', version: '5.14.5'
|
||||||
testCompile group: 'org.apache.activemq', name: 'activemq-pool', version: '5.14.5'
|
testCompile group: 'org.apache.activemq', name: 'activemq-pool', version: '5.14.5'
|
||||||
testCompile group: 'org.apache.activemq', name: 'activemq-broker', version: '5.14.5'
|
testCompile group: 'org.apache.activemq', name: 'activemq-broker', version: '5.14.5'
|
||||||
|
|
||||||
|
latestDepTestCompile group: 'org.hornetq', name: 'hornetq-jms-client', version: '2.4.7.Final'
|
||||||
|
latestDepTestCompile group: 'org.hornetq', name: 'hornetq-jms-server', version: '2.4.7.Final'
|
||||||
}
|
}
|
|
@ -17,6 +17,7 @@ import org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory
|
||||||
import org.hornetq.core.server.HornetQServers
|
import org.hornetq.core.server.HornetQServers
|
||||||
import org.hornetq.jms.client.HornetQMessageConsumer
|
import org.hornetq.jms.client.HornetQMessageConsumer
|
||||||
import org.hornetq.jms.client.HornetQMessageProducer
|
import org.hornetq.jms.client.HornetQMessageProducer
|
||||||
|
import org.hornetq.jms.client.HornetQTextMessage
|
||||||
import spock.lang.Shared
|
import spock.lang.Shared
|
||||||
|
|
||||||
import javax.jms.Message
|
import javax.jms.Message
|
||||||
|
@ -32,7 +33,9 @@ class JMS2Test extends AgentTestRunner {
|
||||||
@Shared
|
@Shared
|
||||||
String messageText = "a message"
|
String messageText = "a message"
|
||||||
@Shared
|
@Shared
|
||||||
static Session session
|
Session session
|
||||||
|
|
||||||
|
HornetQTextMessage message = session.createTextMessage(messageText)
|
||||||
|
|
||||||
def setupSpec() {
|
def setupSpec() {
|
||||||
def tempDir = Files.createTempDir()
|
def tempDir = Files.createTempDir()
|
||||||
|
@ -73,7 +76,6 @@ class JMS2Test extends AgentTestRunner {
|
||||||
setup:
|
setup:
|
||||||
def producer = session.createProducer(destination)
|
def producer = session.createProducer(destination)
|
||||||
def consumer = session.createConsumer(destination)
|
def consumer = session.createConsumer(destination)
|
||||||
def message = session.createTextMessage(messageText)
|
|
||||||
|
|
||||||
producer.send(message)
|
producer.send(message)
|
||||||
|
|
||||||
|
@ -95,7 +97,7 @@ class JMS2Test extends AgentTestRunner {
|
||||||
tags {
|
tags {
|
||||||
defaultTags()
|
defaultTags()
|
||||||
"${DDTags.SPAN_TYPE}" DDSpanTypes.MESSAGE_CONSUMER
|
"${DDTags.SPAN_TYPE}" DDSpanTypes.MESSAGE_CONSUMER
|
||||||
"${Tags.COMPONENT.key}" "jms2"
|
"${Tags.COMPONENT.key}" "jms"
|
||||||
"${Tags.SPAN_KIND.key}" "consumer"
|
"${Tags.SPAN_KIND.key}" "consumer"
|
||||||
"span.origin.type" HornetQMessageConsumer.name
|
"span.origin.type" HornetQMessageConsumer.name
|
||||||
}
|
}
|
||||||
|
@ -129,7 +131,6 @@ class JMS2Test extends AgentTestRunner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def message = session.createTextMessage(messageText)
|
|
||||||
producer.send(message)
|
producer.send(message)
|
||||||
lock.countDown()
|
lock.countDown()
|
||||||
|
|
||||||
|
@ -148,7 +149,7 @@ class JMS2Test extends AgentTestRunner {
|
||||||
tags {
|
tags {
|
||||||
defaultTags()
|
defaultTags()
|
||||||
"${DDTags.SPAN_TYPE}" DDSpanTypes.MESSAGE_CONSUMER
|
"${DDTags.SPAN_TYPE}" DDSpanTypes.MESSAGE_CONSUMER
|
||||||
"${Tags.COMPONENT.key}" "jms2"
|
"${Tags.COMPONENT.key}" "jms"
|
||||||
"${Tags.SPAN_KIND.key}" "consumer"
|
"${Tags.SPAN_KIND.key}" "consumer"
|
||||||
"span.origin.type" { t -> t.contains("JMS2Test") }
|
"span.origin.type" { t -> t.contains("JMS2Test") }
|
||||||
}
|
}
|
||||||
|
@ -192,7 +193,7 @@ class JMS2Test extends AgentTestRunner {
|
||||||
tags {
|
tags {
|
||||||
defaultTags()
|
defaultTags()
|
||||||
"${DDTags.SPAN_TYPE}" DDSpanTypes.MESSAGE_CONSUMER
|
"${DDTags.SPAN_TYPE}" DDSpanTypes.MESSAGE_CONSUMER
|
||||||
"${Tags.COMPONENT.key}" "jms2"
|
"${Tags.COMPONENT.key}" "jms"
|
||||||
"${Tags.SPAN_KIND.key}" "consumer"
|
"${Tags.SPAN_KIND.key}" "consumer"
|
||||||
"span.origin.type" HornetQMessageConsumer.name
|
"span.origin.type" HornetQMessageConsumer.name
|
||||||
}
|
}
|
||||||
|
@ -231,7 +232,7 @@ class JMS2Test extends AgentTestRunner {
|
||||||
tags {
|
tags {
|
||||||
defaultTags()
|
defaultTags()
|
||||||
"${DDTags.SPAN_TYPE}" DDSpanTypes.MESSAGE_CONSUMER
|
"${DDTags.SPAN_TYPE}" DDSpanTypes.MESSAGE_CONSUMER
|
||||||
"${Tags.COMPONENT.key}" "jms2"
|
"${Tags.COMPONENT.key}" "jms"
|
||||||
"${Tags.SPAN_KIND.key}" "consumer"
|
"${Tags.SPAN_KIND.key}" "consumer"
|
||||||
"span.origin.type" HornetQMessageConsumer.name
|
"span.origin.type" HornetQMessageConsumer.name
|
||||||
}
|
}
|
||||||
|
@ -261,7 +262,7 @@ class JMS2Test extends AgentTestRunner {
|
||||||
tags {
|
tags {
|
||||||
defaultTags()
|
defaultTags()
|
||||||
"${DDTags.SPAN_TYPE}" DDSpanTypes.MESSAGE_PRODUCER
|
"${DDTags.SPAN_TYPE}" DDSpanTypes.MESSAGE_PRODUCER
|
||||||
"${Tags.COMPONENT.key}" "jms2"
|
"${Tags.COMPONENT.key}" "jms"
|
||||||
"${Tags.SPAN_KIND.key}" "producer"
|
"${Tags.SPAN_KIND.key}" "producer"
|
||||||
"span.origin.type" HornetQMessageProducer.name
|
"span.origin.type" HornetQMessageProducer.name
|
||||||
}
|
}
|
||||||
|
@ -282,7 +283,7 @@ class JMS2Test extends AgentTestRunner {
|
||||||
tags {
|
tags {
|
||||||
defaultTags()
|
defaultTags()
|
||||||
"${DDTags.SPAN_TYPE}" DDSpanTypes.MESSAGE_CONSUMER
|
"${DDTags.SPAN_TYPE}" DDSpanTypes.MESSAGE_CONSUMER
|
||||||
"${Tags.COMPONENT.key}" "jms2"
|
"${Tags.COMPONENT.key}" "jms"
|
||||||
"${Tags.SPAN_KIND.key}" "consumer"
|
"${Tags.SPAN_KIND.key}" "consumer"
|
||||||
"span.origin.type" origin
|
"span.origin.type" origin
|
||||||
}
|
}
|
|
@ -1,8 +1,7 @@
|
||||||
package datadog.trace.instrumentation.jms2;
|
package datadog.trace.instrumentation.jms;
|
||||||
|
|
||||||
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
|
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
|
||||||
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
|
import static datadog.trace.instrumentation.jms.JmsUtil.toResourceName;
|
||||||
import static datadog.trace.instrumentation.jms.util.JmsUtil.toResourceName;
|
|
||||||
import static io.opentracing.log.Fields.ERROR_OBJECT;
|
import static io.opentracing.log.Fields.ERROR_OBJECT;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
|
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
|
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
|
||||||
|
@ -14,7 +13,6 @@ import com.google.auto.service.AutoService;
|
||||||
import datadog.trace.agent.tooling.Instrumenter;
|
import datadog.trace.agent.tooling.Instrumenter;
|
||||||
import datadog.trace.api.DDSpanTypes;
|
import datadog.trace.api.DDSpanTypes;
|
||||||
import datadog.trace.api.DDTags;
|
import datadog.trace.api.DDTags;
|
||||||
import datadog.trace.instrumentation.jms.util.MessagePropertyTextMap;
|
|
||||||
import io.opentracing.Scope;
|
import io.opentracing.Scope;
|
||||||
import io.opentracing.Span;
|
import io.opentracing.Span;
|
||||||
import io.opentracing.SpanContext;
|
import io.opentracing.SpanContext;
|
||||||
|
@ -34,15 +32,10 @@ import net.bytebuddy.description.type.TypeDescription;
|
||||||
import net.bytebuddy.matcher.ElementMatcher;
|
import net.bytebuddy.matcher.ElementMatcher;
|
||||||
|
|
||||||
@AutoService(Instrumenter.class)
|
@AutoService(Instrumenter.class)
|
||||||
public final class JMS2MessageConsumerInstrumentation extends Instrumenter.Default {
|
public final class JMSMessageConsumerInstrumentation extends Instrumenter.Default {
|
||||||
public static final String[] JMS2_HELPER_CLASS_NAMES =
|
|
||||||
new String[] {
|
|
||||||
"datadog.trace.instrumentation.jms.util.JmsUtil",
|
|
||||||
"datadog.trace.instrumentation.jms.util.MessagePropertyTextMap"
|
|
||||||
};
|
|
||||||
|
|
||||||
public JMS2MessageConsumerInstrumentation() {
|
public JMSMessageConsumerInstrumentation() {
|
||||||
super("jms", "jms-2");
|
super("jms", "jms-1", "jms-2");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -50,14 +43,9 @@ public final class JMS2MessageConsumerInstrumentation extends Instrumenter.Defau
|
||||||
return not(isInterface()).and(safeHasSuperType(named("javax.jms.MessageConsumer")));
|
return not(isInterface()).and(safeHasSuperType(named("javax.jms.MessageConsumer")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ElementMatcher<ClassLoader> classLoaderMatcher() {
|
|
||||||
return classLoaderHasClasses("javax.jms.JMSContext", "javax.jms.CompletionListener");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] helperClassNames() {
|
public String[] helperClassNames() {
|
||||||
return JMS2_HELPER_CLASS_NAMES;
|
return new String[] {packageName + ".JmsUtil", packageName + ".MessagePropertyTextMap"};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -91,7 +79,7 @@ public final class JMS2MessageConsumerInstrumentation extends Instrumenter.Defau
|
||||||
.buildSpan("jms.consume")
|
.buildSpan("jms.consume")
|
||||||
.withTag(DDTags.SERVICE_NAME, "jms")
|
.withTag(DDTags.SERVICE_NAME, "jms")
|
||||||
.withTag(DDTags.SPAN_TYPE, DDSpanTypes.MESSAGE_CONSUMER)
|
.withTag(DDTags.SPAN_TYPE, DDSpanTypes.MESSAGE_CONSUMER)
|
||||||
.withTag(Tags.COMPONENT.getKey(), "jms2")
|
.withTag(Tags.COMPONENT.getKey(), "jms")
|
||||||
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CONSUMER)
|
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CONSUMER)
|
||||||
.withTag("span.origin.type", consumer.getClass().getName())
|
.withTag("span.origin.type", consumer.getClass().getName())
|
||||||
.withStartTimestamp(TimeUnit.MILLISECONDS.toMicros(startTime));
|
.withStartTimestamp(TimeUnit.MILLISECONDS.toMicros(startTime));
|
|
@ -1,8 +1,7 @@
|
||||||
package datadog.trace.instrumentation.jms2;
|
package datadog.trace.instrumentation.jms;
|
||||||
|
|
||||||
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
|
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
|
||||||
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
|
import static datadog.trace.instrumentation.jms.JmsUtil.toResourceName;
|
||||||
import static datadog.trace.instrumentation.jms.util.JmsUtil.toResourceName;
|
|
||||||
import static io.opentracing.log.Fields.ERROR_OBJECT;
|
import static io.opentracing.log.Fields.ERROR_OBJECT;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
|
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
|
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
|
||||||
|
@ -15,7 +14,6 @@ import datadog.trace.agent.tooling.Instrumenter;
|
||||||
import datadog.trace.api.DDSpanTypes;
|
import datadog.trace.api.DDSpanTypes;
|
||||||
import datadog.trace.api.DDTags;
|
import datadog.trace.api.DDTags;
|
||||||
import datadog.trace.context.TraceScope;
|
import datadog.trace.context.TraceScope;
|
||||||
import datadog.trace.instrumentation.jms.util.MessagePropertyTextMap;
|
|
||||||
import io.opentracing.Scope;
|
import io.opentracing.Scope;
|
||||||
import io.opentracing.Span;
|
import io.opentracing.Span;
|
||||||
import io.opentracing.SpanContext;
|
import io.opentracing.SpanContext;
|
||||||
|
@ -32,10 +30,10 @@ import net.bytebuddy.description.type.TypeDescription;
|
||||||
import net.bytebuddy.matcher.ElementMatcher;
|
import net.bytebuddy.matcher.ElementMatcher;
|
||||||
|
|
||||||
@AutoService(Instrumenter.class)
|
@AutoService(Instrumenter.class)
|
||||||
public final class JMS2MessageListenerInstrumentation extends Instrumenter.Default {
|
public final class JMSMessageListenerInstrumentation extends Instrumenter.Default {
|
||||||
|
|
||||||
public JMS2MessageListenerInstrumentation() {
|
public JMSMessageListenerInstrumentation() {
|
||||||
super("jms", "jms-2");
|
super("jms", "jms-1", "jms-2");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -43,14 +41,9 @@ public final class JMS2MessageListenerInstrumentation extends Instrumenter.Defau
|
||||||
return not(isInterface()).and(safeHasSuperType(named("javax.jms.MessageListener")));
|
return not(isInterface()).and(safeHasSuperType(named("javax.jms.MessageListener")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ElementMatcher<ClassLoader> classLoaderMatcher() {
|
|
||||||
return classLoaderHasClasses("javax.jms.JMSContext", "javax.jms.CompletionListener");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] helperClassNames() {
|
public String[] helperClassNames() {
|
||||||
return JMS2MessageConsumerInstrumentation.JMS2_HELPER_CLASS_NAMES;
|
return new String[] {packageName + ".JmsUtil", packageName + ".MessagePropertyTextMap"};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -78,7 +71,7 @@ public final class JMS2MessageListenerInstrumentation extends Instrumenter.Defau
|
||||||
.withTag(DDTags.SERVICE_NAME, "jms")
|
.withTag(DDTags.SERVICE_NAME, "jms")
|
||||||
.withTag(DDTags.SPAN_TYPE, DDSpanTypes.MESSAGE_CONSUMER)
|
.withTag(DDTags.SPAN_TYPE, DDSpanTypes.MESSAGE_CONSUMER)
|
||||||
.withTag(DDTags.RESOURCE_NAME, "Received from " + toResourceName(message, null))
|
.withTag(DDTags.RESOURCE_NAME, "Received from " + toResourceName(message, null))
|
||||||
.withTag(Tags.COMPONENT.getKey(), "jms2")
|
.withTag(Tags.COMPONENT.getKey(), "jms")
|
||||||
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CONSUMER)
|
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CONSUMER)
|
||||||
.withTag("span.origin.type", listener.getClass().getName())
|
.withTag("span.origin.type", listener.getClass().getName())
|
||||||
.startActive(true);
|
.startActive(true);
|
|
@ -1,8 +1,7 @@
|
||||||
package datadog.trace.instrumentation.jms2;
|
package datadog.trace.instrumentation.jms;
|
||||||
|
|
||||||
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
|
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
|
||||||
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
|
import static datadog.trace.instrumentation.jms.JmsUtil.toResourceName;
|
||||||
import static datadog.trace.instrumentation.jms.util.JmsUtil.toResourceName;
|
|
||||||
import static io.opentracing.log.Fields.ERROR_OBJECT;
|
import static io.opentracing.log.Fields.ERROR_OBJECT;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
|
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
|
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
|
||||||
|
@ -14,7 +13,6 @@ import com.google.auto.service.AutoService;
|
||||||
import datadog.trace.agent.tooling.Instrumenter;
|
import datadog.trace.agent.tooling.Instrumenter;
|
||||||
import datadog.trace.api.DDSpanTypes;
|
import datadog.trace.api.DDSpanTypes;
|
||||||
import datadog.trace.api.DDTags;
|
import datadog.trace.api.DDTags;
|
||||||
import datadog.trace.instrumentation.jms.util.MessagePropertyTextMap;
|
|
||||||
import io.opentracing.Scope;
|
import io.opentracing.Scope;
|
||||||
import io.opentracing.Span;
|
import io.opentracing.Span;
|
||||||
import io.opentracing.propagation.Format;
|
import io.opentracing.propagation.Format;
|
||||||
|
@ -32,10 +30,10 @@ import net.bytebuddy.description.type.TypeDescription;
|
||||||
import net.bytebuddy.matcher.ElementMatcher;
|
import net.bytebuddy.matcher.ElementMatcher;
|
||||||
|
|
||||||
@AutoService(Instrumenter.class)
|
@AutoService(Instrumenter.class)
|
||||||
public final class JMS2MessageProducerInstrumentation extends Instrumenter.Default {
|
public final class JMSMessageProducerInstrumentation extends Instrumenter.Default {
|
||||||
|
|
||||||
public JMS2MessageProducerInstrumentation() {
|
public JMSMessageProducerInstrumentation() {
|
||||||
super("jms", "jms-2");
|
super("jms", "jms-1", "jms-2");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -43,14 +41,9 @@ public final class JMS2MessageProducerInstrumentation extends Instrumenter.Defau
|
||||||
return not(isInterface()).and(safeHasSuperType(named("javax.jms.MessageProducer")));
|
return not(isInterface()).and(safeHasSuperType(named("javax.jms.MessageProducer")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ElementMatcher<ClassLoader> classLoaderMatcher() {
|
|
||||||
return classLoaderHasClasses("javax.jms.JMSContext", "javax.jms.CompletionListener");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] helperClassNames() {
|
public String[] helperClassNames() {
|
||||||
return JMS2MessageConsumerInstrumentation.JMS2_HELPER_CLASS_NAMES;
|
return new String[] {packageName + ".JmsUtil", packageName + ".MessagePropertyTextMap"};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -83,11 +76,11 @@ public final class JMS2MessageProducerInstrumentation extends Instrumenter.Defau
|
||||||
GlobalTracer.get()
|
GlobalTracer.get()
|
||||||
.buildSpan("jms.produce")
|
.buildSpan("jms.produce")
|
||||||
.withTag(DDTags.SERVICE_NAME, "jms")
|
.withTag(DDTags.SERVICE_NAME, "jms")
|
||||||
.withTag(DDTags.SPAN_TYPE, DDSpanTypes.MESSAGE_PRODUCER)
|
|
||||||
.withTag(
|
.withTag(
|
||||||
DDTags.RESOURCE_NAME,
|
DDTags.RESOURCE_NAME,
|
||||||
"Produced for " + toResourceName(message, defaultDestination))
|
"Produced for " + toResourceName(message, defaultDestination))
|
||||||
.withTag(Tags.COMPONENT.getKey(), "jms2")
|
.withTag(Tags.COMPONENT.getKey(), "jms")
|
||||||
|
.withTag(DDTags.SPAN_TYPE, DDSpanTypes.MESSAGE_PRODUCER)
|
||||||
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_PRODUCER)
|
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_PRODUCER)
|
||||||
.withTag("span.origin.type", producer.getClass().getName())
|
.withTag("span.origin.type", producer.getClass().getName())
|
||||||
.startActive(true);
|
.startActive(true);
|
||||||
|
@ -127,7 +120,7 @@ public final class JMS2MessageProducerInstrumentation extends Instrumenter.Defau
|
||||||
.withTag(DDTags.SERVICE_NAME, "jms")
|
.withTag(DDTags.SERVICE_NAME, "jms")
|
||||||
.withTag(DDTags.SPAN_TYPE, DDSpanTypes.MESSAGE_PRODUCER)
|
.withTag(DDTags.SPAN_TYPE, DDSpanTypes.MESSAGE_PRODUCER)
|
||||||
.withTag(DDTags.RESOURCE_NAME, "Produced for " + toResourceName(message, destination))
|
.withTag(DDTags.RESOURCE_NAME, "Produced for " + toResourceName(message, destination))
|
||||||
.withTag(Tags.COMPONENT.getKey(), "jms2")
|
.withTag(Tags.COMPONENT.getKey(), "jms")
|
||||||
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_PRODUCER)
|
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_PRODUCER)
|
||||||
.withTag("span.origin.type", producer.getClass().getName())
|
.withTag("span.origin.type", producer.getClass().getName())
|
||||||
.startActive(true);
|
.startActive(true);
|
||||||
|
@ -135,6 +128,7 @@ public final class JMS2MessageProducerInstrumentation extends Instrumenter.Defau
|
||||||
GlobalTracer.get()
|
GlobalTracer.get()
|
||||||
.inject(
|
.inject(
|
||||||
scope.span().context(), Format.Builtin.TEXT_MAP, new MessagePropertyTextMap(message));
|
scope.span().context(), Format.Builtin.TEXT_MAP, new MessagePropertyTextMap(message));
|
||||||
|
|
||||||
return scope;
|
return scope;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package datadog.trace.instrumentation.jms.util;
|
package datadog.trace.instrumentation.jms;
|
||||||
|
|
||||||
import javax.jms.Destination;
|
import javax.jms.Destination;
|
||||||
import javax.jms.Message;
|
import javax.jms.Message;
|
|
@ -1,4 +1,4 @@
|
||||||
package datadog.trace.instrumentation.jms.util;
|
package datadog.trace.instrumentation.jms;
|
||||||
|
|
||||||
import io.opentracing.propagation.TextMap;
|
import io.opentracing.propagation.TextMap;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
|
@ -7,7 +7,9 @@ import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.jms.JMSException;
|
import javax.jms.JMSException;
|
||||||
import javax.jms.Message;
|
import javax.jms.Message;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class MessagePropertyTextMap implements TextMap {
|
public class MessagePropertyTextMap implements TextMap {
|
||||||
static final String DASH = "__dash__";
|
static final String DASH = "__dash__";
|
||||||
|
|
||||||
|
@ -39,10 +41,13 @@ public class MessagePropertyTextMap implements TextMap {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void put(final String key, final String value) {
|
public void put(final String key, final String value) {
|
||||||
|
final String propName = key.replace("-", DASH);
|
||||||
try {
|
try {
|
||||||
message.setStringProperty(key.replace("-", DASH), value);
|
message.setStringProperty(propName, value);
|
||||||
} catch (final JMSException e) {
|
} catch (final JMSException e) {
|
||||||
throw new RuntimeException(e);
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("Failure setting jms property: " + propName, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -6,6 +6,7 @@ import io.opentracing.tag.Tags
|
||||||
import org.apache.activemq.ActiveMQConnectionFactory
|
import org.apache.activemq.ActiveMQConnectionFactory
|
||||||
import org.apache.activemq.ActiveMQMessageConsumer
|
import org.apache.activemq.ActiveMQMessageConsumer
|
||||||
import org.apache.activemq.ActiveMQMessageProducer
|
import org.apache.activemq.ActiveMQMessageProducer
|
||||||
|
import org.apache.activemq.command.ActiveMQTextMessage
|
||||||
import org.apache.activemq.junit.EmbeddedActiveMQBroker
|
import org.apache.activemq.junit.EmbeddedActiveMQBroker
|
||||||
import spock.lang.Shared
|
import spock.lang.Shared
|
||||||
|
|
||||||
|
@ -25,7 +26,7 @@ class JMS1Test extends AgentTestRunner {
|
||||||
@Shared
|
@Shared
|
||||||
Session session
|
Session session
|
||||||
|
|
||||||
def message = session.createTextMessage(messageText)
|
ActiveMQTextMessage message = session.createTextMessage(messageText)
|
||||||
|
|
||||||
def setupSpec() {
|
def setupSpec() {
|
||||||
EmbeddedActiveMQBroker broker = new EmbeddedActiveMQBroker()
|
EmbeddedActiveMQBroker broker = new EmbeddedActiveMQBroker()
|
||||||
|
@ -62,7 +63,7 @@ class JMS1Test extends AgentTestRunner {
|
||||||
tags {
|
tags {
|
||||||
defaultTags()
|
defaultTags()
|
||||||
"${DDTags.SPAN_TYPE}" DDSpanTypes.MESSAGE_CONSUMER
|
"${DDTags.SPAN_TYPE}" DDSpanTypes.MESSAGE_CONSUMER
|
||||||
"${Tags.COMPONENT.key}" "jms1"
|
"${Tags.COMPONENT.key}" "jms"
|
||||||
"${Tags.SPAN_KIND.key}" "consumer"
|
"${Tags.SPAN_KIND.key}" "consumer"
|
||||||
"span.origin.type" ActiveMQMessageConsumer.name
|
"span.origin.type" ActiveMQMessageConsumer.name
|
||||||
}
|
}
|
||||||
|
@ -114,7 +115,7 @@ class JMS1Test extends AgentTestRunner {
|
||||||
tags {
|
tags {
|
||||||
defaultTags()
|
defaultTags()
|
||||||
"${DDTags.SPAN_TYPE}" DDSpanTypes.MESSAGE_CONSUMER
|
"${DDTags.SPAN_TYPE}" DDSpanTypes.MESSAGE_CONSUMER
|
||||||
"${Tags.COMPONENT.key}" "jms1"
|
"${Tags.COMPONENT.key}" "jms"
|
||||||
"${Tags.SPAN_KIND.key}" "consumer"
|
"${Tags.SPAN_KIND.key}" "consumer"
|
||||||
"span.origin.type" { t -> t.contains("JMS1Test") }
|
"span.origin.type" { t -> t.contains("JMS1Test") }
|
||||||
}
|
}
|
||||||
|
@ -158,7 +159,7 @@ class JMS1Test extends AgentTestRunner {
|
||||||
tags {
|
tags {
|
||||||
defaultTags()
|
defaultTags()
|
||||||
"${DDTags.SPAN_TYPE}" DDSpanTypes.MESSAGE_CONSUMER
|
"${DDTags.SPAN_TYPE}" DDSpanTypes.MESSAGE_CONSUMER
|
||||||
"${Tags.COMPONENT.key}" "jms1"
|
"${Tags.COMPONENT.key}" "jms"
|
||||||
"${Tags.SPAN_KIND.key}" "consumer"
|
"${Tags.SPAN_KIND.key}" "consumer"
|
||||||
"span.origin.type" ActiveMQMessageConsumer.name
|
"span.origin.type" ActiveMQMessageConsumer.name
|
||||||
}
|
}
|
||||||
|
@ -197,7 +198,7 @@ class JMS1Test extends AgentTestRunner {
|
||||||
tags {
|
tags {
|
||||||
defaultTags()
|
defaultTags()
|
||||||
"${DDTags.SPAN_TYPE}" DDSpanTypes.MESSAGE_CONSUMER
|
"${DDTags.SPAN_TYPE}" DDSpanTypes.MESSAGE_CONSUMER
|
||||||
"${Tags.COMPONENT.key}" "jms1"
|
"${Tags.COMPONENT.key}" "jms"
|
||||||
"${Tags.SPAN_KIND.key}" "consumer"
|
"${Tags.SPAN_KIND.key}" "consumer"
|
||||||
"span.origin.type" ActiveMQMessageConsumer.name
|
"span.origin.type" ActiveMQMessageConsumer.name
|
||||||
}
|
}
|
||||||
|
@ -214,6 +215,61 @@ class JMS1Test extends AgentTestRunner {
|
||||||
session.createTopic("someTopic") | "Topic someTopic"
|
session.createTopic("someTopic") | "Topic someTopic"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def "sending a read-only message to #jmsResourceName fails"() {
|
||||||
|
setup:
|
||||||
|
def producer = session.createProducer(destination)
|
||||||
|
def consumer = session.createConsumer(destination)
|
||||||
|
|
||||||
|
expect:
|
||||||
|
!message.isReadOnlyProperties()
|
||||||
|
|
||||||
|
when:
|
||||||
|
message.setReadOnlyProperties(true)
|
||||||
|
and:
|
||||||
|
producer.send(message)
|
||||||
|
|
||||||
|
TextMessage receivedMessage = consumer.receive()
|
||||||
|
|
||||||
|
then:
|
||||||
|
receivedMessage.text == messageText
|
||||||
|
|
||||||
|
// This will result in a logged failure because we tried to
|
||||||
|
// write properties in MessagePropertyTextMap when readOnlyProperties = true.
|
||||||
|
// The consumer span will also not be linked to the parent.
|
||||||
|
assertTraces(TEST_WRITER, 2) {
|
||||||
|
producerTrace(it, 0, jmsResourceName)
|
||||||
|
trace(1, 1) { // Consumer trace
|
||||||
|
span(0) {
|
||||||
|
parent()
|
||||||
|
serviceName "jms"
|
||||||
|
operationName "jms.consume"
|
||||||
|
resourceName "Consumed from $jmsResourceName"
|
||||||
|
spanType DDSpanTypes.MESSAGE_PRODUCER
|
||||||
|
errored false
|
||||||
|
|
||||||
|
tags {
|
||||||
|
defaultTags()
|
||||||
|
"${DDTags.SPAN_TYPE}" DDSpanTypes.MESSAGE_CONSUMER
|
||||||
|
"${Tags.COMPONENT.key}" "jms"
|
||||||
|
"${Tags.SPAN_KIND.key}" "consumer"
|
||||||
|
"span.origin.type" ActiveMQMessageConsumer.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
producer.close()
|
||||||
|
consumer.close()
|
||||||
|
|
||||||
|
where:
|
||||||
|
destination | jmsResourceName
|
||||||
|
session.createQueue("someQueue") | "Queue someQueue"
|
||||||
|
session.createTopic("someTopic") | "Topic someTopic"
|
||||||
|
session.createTemporaryQueue() | "Temporary Queue"
|
||||||
|
session.createTemporaryTopic() | "Temporary Topic"
|
||||||
|
}
|
||||||
|
|
||||||
def producerTrace(ListWriterAssert writer, int index, String jmsResourceName) {
|
def producerTrace(ListWriterAssert writer, int index, String jmsResourceName) {
|
||||||
writer.trace(index, 3) {
|
writer.trace(index, 3) {
|
||||||
span(0) {
|
span(0) {
|
||||||
|
@ -227,7 +283,7 @@ class JMS1Test extends AgentTestRunner {
|
||||||
tags {
|
tags {
|
||||||
defaultTags()
|
defaultTags()
|
||||||
"${DDTags.SPAN_TYPE}" DDSpanTypes.MESSAGE_PRODUCER
|
"${DDTags.SPAN_TYPE}" DDSpanTypes.MESSAGE_PRODUCER
|
||||||
"${Tags.COMPONENT.key}" "jms1"
|
"${Tags.COMPONENT.key}" "jms"
|
||||||
"${Tags.SPAN_KIND.key}" "producer"
|
"${Tags.SPAN_KIND.key}" "producer"
|
||||||
"span.origin.type" ActiveMQMessageProducer.name
|
"span.origin.type" ActiveMQMessageProducer.name
|
||||||
}
|
}
|
||||||
|
@ -243,7 +299,7 @@ class JMS1Test extends AgentTestRunner {
|
||||||
tags {
|
tags {
|
||||||
defaultTags()
|
defaultTags()
|
||||||
"${DDTags.SPAN_TYPE}" DDSpanTypes.MESSAGE_PRODUCER
|
"${DDTags.SPAN_TYPE}" DDSpanTypes.MESSAGE_PRODUCER
|
||||||
"${Tags.COMPONENT.key}" "jms1"
|
"${Tags.COMPONENT.key}" "jms"
|
||||||
"${Tags.SPAN_KIND.key}" "producer"
|
"${Tags.SPAN_KIND.key}" "producer"
|
||||||
"span.origin.type" ActiveMQMessageProducer.name
|
"span.origin.type" ActiveMQMessageProducer.name
|
||||||
}
|
}
|
||||||
|
@ -259,7 +315,7 @@ class JMS1Test extends AgentTestRunner {
|
||||||
tags {
|
tags {
|
||||||
defaultTags()
|
defaultTags()
|
||||||
"${DDTags.SPAN_TYPE}" DDSpanTypes.MESSAGE_PRODUCER
|
"${DDTags.SPAN_TYPE}" DDSpanTypes.MESSAGE_PRODUCER
|
||||||
"${Tags.COMPONENT.key}" "jms1"
|
"${Tags.COMPONENT.key}" "jms"
|
||||||
"${Tags.SPAN_KIND.key}" "producer"
|
"${Tags.SPAN_KIND.key}" "producer"
|
||||||
"span.origin.type" ActiveMQMessageProducer.name
|
"span.origin.type" ActiveMQMessageProducer.name
|
||||||
}
|
}
|
||||||
|
@ -280,7 +336,7 @@ class JMS1Test extends AgentTestRunner {
|
||||||
tags {
|
tags {
|
||||||
defaultTags()
|
defaultTags()
|
||||||
"${DDTags.SPAN_TYPE}" DDSpanTypes.MESSAGE_CONSUMER
|
"${DDTags.SPAN_TYPE}" DDSpanTypes.MESSAGE_CONSUMER
|
||||||
"${Tags.COMPONENT.key}" "jms1"
|
"${Tags.COMPONENT.key}" "jms"
|
||||||
"${Tags.SPAN_KIND.key}" "consumer"
|
"${Tags.SPAN_KIND.key}" "consumer"
|
||||||
"span.origin.type" origin
|
"span.origin.type" origin
|
||||||
}
|
}
|
|
@ -30,8 +30,7 @@ include ':dd-java-agent:instrumentation:jboss-classloading'
|
||||||
include ':dd-java-agent:instrumentation:jdbc'
|
include ':dd-java-agent:instrumentation:jdbc'
|
||||||
include ':dd-java-agent:instrumentation:jedis-1.4'
|
include ':dd-java-agent:instrumentation:jedis-1.4'
|
||||||
include ':dd-java-agent:instrumentation:jetty-8'
|
include ':dd-java-agent:instrumentation:jetty-8'
|
||||||
include ':dd-java-agent:instrumentation:jms-1'
|
include ':dd-java-agent:instrumentation:jms'
|
||||||
include ':dd-java-agent:instrumentation:jms-2'
|
|
||||||
include ':dd-java-agent:instrumentation:jsp-2.3'
|
include ':dd-java-agent:instrumentation:jsp-2.3'
|
||||||
include ':dd-java-agent:instrumentation:kafka-clients-0.11'
|
include ':dd-java-agent:instrumentation:kafka-clients-0.11'
|
||||||
include ':dd-java-agent:instrumentation:kafka-streams-0.11'
|
include ':dd-java-agent:instrumentation:kafka-streams-0.11'
|
||||||
|
|
Loading…
Reference in New Issue