Merge pull request #416 from DataDog/tyler/contributing

Add contributing document and apply formatting.
This commit is contained in:
Tyler Benson 2018-07-31 12:24:23 +10:00 committed by GitHub
commit 12e41be258
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
87 changed files with 635 additions and 493 deletions

30
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,30 @@
### Contributing
Pull requests for bug fixes are welcome, but before submitting new features or changes to current functionality [open an issue](https://github.com/DataDog/dd-trace-java/issues/new)
and discuss your ideas or propose the changes you wish to make. After a resolution is reached a PR can be submitted for review.
### Code Style
This project includes a `.editorconfig` file for basic editor settings. This file is supported by most common text editors.
Java files must be formatted using [google-java-format](https://github.com/google/google-java-format). Please run the following task to ensure files are formatted before committing:
```shell
./gradlew :googleJavaFormat
```
Other source files (Groovy, Scala, etc) should ideally be formatted by Intellij Idea's default formatting, but are not enforced.
### Intellij Idea
Suggested plugins and settings:
* Editor > Code Style > Java/Groovy > Imports
* Class count to use import with '*': `10` (some number sufficiently large that is unlikely to matter)
* Names count to use static import with '*': `10`
* With java use the following import layout (groovy should still use the default) to ensure consistency with google-java-format:
![import layout](https://user-images.githubusercontent.com/734411/43430811-28442636-94ae-11e8-86f1-f270ddcba023.png)
* [Google Java Format](https://plugins.jetbrains.com/plugin/8527-google-java-format)
* [Lombok](https://plugins.jetbrains.com/plugin/6317-lombok-plugin)
* [Save Actions](https://plugins.jetbrains.com/plugin/7642-save-actions)
![Recommended Settings](https://user-images.githubusercontent.com/734411/43430944-db84bf8a-94ae-11e8-8cec-0daa064937c4.png)

View File

@ -21,11 +21,11 @@ class MuzzlePlugin implements Plugin<Project> {
List<URL> userUrls = new ArrayList<>() List<URL> userUrls = new ArrayList<>()
project.getLogger().info("Creating user classpath for: " + project.getName()) project.getLogger().info("Creating user classpath for: " + project.getName())
for (File f : project.configurations.compileOnly.getFiles()) { for (File f : project.configurations.compileOnly.getFiles()) {
project.getLogger().info( '--' + f) project.getLogger().info('--' + f)
userUrls.add(f.toURI().toURL()) userUrls.add(f.toURI().toURL())
} }
for (File f : bootstrapProject.sourceSets.main.runtimeClasspath.getFiles()) { for (File f : bootstrapProject.sourceSets.main.runtimeClasspath.getFiles()) {
project.getLogger().info( '--' + f) project.getLogger().info('--' + f)
userUrls.add(f.toURI().toURL()) userUrls.add(f.toURI().toURL())
} }
final ClassLoader userCL = new URLClassLoader(userUrls.toArray(new URL[0]), (ClassLoader) null) final ClassLoader userCL = new URLClassLoader(userUrls.toArray(new URL[0]), (ClassLoader) null)
@ -33,11 +33,11 @@ class MuzzlePlugin implements Plugin<Project> {
project.getLogger().info("Creating dd classpath for: " + project.getName()) project.getLogger().info("Creating dd classpath for: " + project.getName())
Set<URL> ddUrls = new HashSet<>() Set<URL> ddUrls = new HashSet<>()
for (File f : toolingProject.sourceSets.main.runtimeClasspath.getFiles()) { for (File f : toolingProject.sourceSets.main.runtimeClasspath.getFiles()) {
project.getLogger().info( '--' + f) project.getLogger().info('--' + f)
ddUrls.add(f.toURI().toURL()) ddUrls.add(f.toURI().toURL())
} }
for(File f : project.sourceSets.main.runtimeClasspath.getFiles()) { for (File f : project.sourceSets.main.runtimeClasspath.getFiles()) {
project.getLogger().info( '--' + f) project.getLogger().info('--' + f)
ddUrls.add(f.toURI().toURL()) ddUrls.add(f.toURI().toURL())
} }

View File

@ -9,10 +9,10 @@ import static datadog.trace.agent.test.IntegrationTestUtils.createJarWithClasses
class ClassLoadingTest extends Specification { class ClassLoadingTest extends Specification {
/** Assert that we can instrument classloaders which cannot resolve agent advice classes. */ /** Assert that we can instrument classloaders which cannot resolve agent advice classes. */
def "instrument classloader without agent classes" () { def "instrument classloader without agent classes"() {
setup: setup:
final URL[] classpath = [createJarWithClasses(ClassToInstrument, Trace)] final URL[] classpath = [createJarWithClasses(ClassToInstrument, Trace)]
final URLClassLoader loader = new URLClassLoader(classpath, (ClassLoader)null) final URLClassLoader loader = new URLClassLoader(classpath, (ClassLoader) null)
when: when:
loader.loadClass("datadog.agent.TracingAgent") loader.loadClass("datadog.agent.TracingAgent")

View File

@ -54,51 +54,51 @@ class ShadowPackageRenamingTest extends Specification {
} }
def "agent jar contains no bootstrap classes"() { def "agent jar contains no bootstrap classes"() {
setup: setup:
final ClassPath agentClasspath = ClassPath.from(IntegrationTestUtils.getAgentClassLoader()) final ClassPath agentClasspath = ClassPath.from(IntegrationTestUtils.getAgentClassLoader())
final ClassPath bootstrapClasspath = ClassPath.from(IntegrationTestUtils.getBootstrapProxy()) final ClassPath bootstrapClasspath = ClassPath.from(IntegrationTestUtils.getBootstrapProxy())
final Set<String> bootstrapClasses = new HashSet<>() final Set<String> bootstrapClasses = new HashSet<>()
final String[] bootstrapPrefixes = IntegrationTestUtils.getBootstrapPackagePrefixes() final String[] bootstrapPrefixes = IntegrationTestUtils.getBootstrapPackagePrefixes()
final String[] agentPrefixes = IntegrationTestUtils.getAgentPackagePrefixes() final String[] agentPrefixes = IntegrationTestUtils.getAgentPackagePrefixes()
final List<String> badBootstrapPrefixes = [] final List<String> badBootstrapPrefixes = []
final List<String> badAgentPrefixes = [] final List<String> badAgentPrefixes = []
for (ClassPath.ClassInfo info : bootstrapClasspath.getAllClasses()) { for (ClassPath.ClassInfo info : bootstrapClasspath.getAllClasses()) {
bootstrapClasses.add(info.getName()) bootstrapClasses.add(info.getName())
// make sure all bootstrap classes can be loaded from system // make sure all bootstrap classes can be loaded from system
ClassLoader.getSystemClassLoader().loadClass(info.getName()) ClassLoader.getSystemClassLoader().loadClass(info.getName())
boolean goodPrefix = false boolean goodPrefix = false
for (int i = 0; i < bootstrapPrefixes.length; ++i) { for (int i = 0; i < bootstrapPrefixes.length; ++i) {
if (info.getName().startsWith(bootstrapPrefixes[i])) { if (info.getName().startsWith(bootstrapPrefixes[i])) {
goodPrefix = true goodPrefix = true
break break
} }
} }
if (!goodPrefix) { if (!goodPrefix) {
badBootstrapPrefixes.add(info.getName()) badBootstrapPrefixes.add(info.getName())
} }
} }
final List<ClassPath.ClassInfo> duplicateClassFile = new ArrayList<>() final List<ClassPath.ClassInfo> duplicateClassFile = new ArrayList<>()
for (ClassPath.ClassInfo classInfo : agentClasspath.getAllClasses()) { for (ClassPath.ClassInfo classInfo : agentClasspath.getAllClasses()) {
if (bootstrapClasses.contains(classInfo.getName())) { if (bootstrapClasses.contains(classInfo.getName())) {
duplicateClassFile.add(classInfo) duplicateClassFile.add(classInfo)
} }
boolean goodPrefix = false boolean goodPrefix = false
for (int i = 0; i < agentPrefixes.length; ++i) { for (int i = 0; i < agentPrefixes.length; ++i) {
if (classInfo.getName().startsWith(agentPrefixes[i])) { if (classInfo.getName().startsWith(agentPrefixes[i])) {
goodPrefix = true goodPrefix = true
break break
} }
} }
if (!goodPrefix) { if (!goodPrefix) {
badAgentPrefixes.add(classInfo.getName()) badAgentPrefixes.add(classInfo.getName())
} }
} }
expect: expect:
duplicateClassFile == [] duplicateClassFile == []
badBootstrapPrefixes == [] badBootstrapPrefixes == []
badAgentPrefixes == [] badAgentPrefixes == []
} }
} }

View File

@ -1,10 +1,10 @@
package datadog.trace.agent.integration.muzzle package datadog.trace.agent.integration.muzzle
import datadog.trace.agent.test.IntegrationTestUtils import datadog.trace.agent.test.IntegrationTestUtils
import java.lang.reflect.Field
import java.lang.reflect.Method
import spock.lang.Specification import spock.lang.Specification
import java.lang.reflect.Field
import java.lang.reflect.Method
class MuzzleBytecodeTransformTest extends Specification { class MuzzleBytecodeTransformTest extends Specification {
@ -33,7 +33,7 @@ class MuzzleBytecodeTransformTest extends Specification {
if (f.get(instrumenter) == null) { if (f.get(instrumenter) == null) {
unInitFields.add(instrumenter.getClass()) unInitFields.add(instrumenter.getClass())
} }
} catch(NoSuchFieldException | NoSuchMethodException e) { } catch (NoSuchFieldException | NoSuchMethodException e) {
unMuzzledClasses.add(instrumenter.getClass()) unMuzzledClasses.add(instrumenter.getClass())
} finally { } finally {
if (null != f) { if (null != f) {

View File

@ -5,7 +5,7 @@ plugins {
apply from: "${rootDir}/gradle/java.gradle" apply from: "${rootDir}/gradle/java.gradle"
excludedClassesConverage += [ 'datadog.trace.bootstrap.*' ] excludedClassesConverage += ['datadog.trace.bootstrap.*']
dependencies { dependencies {
compile project(':dd-trace-api') compile project(':dd-trace-api')

View File

@ -1,6 +1,6 @@
apply from: "${rootDir}/gradle/java.gradle" apply from: "${rootDir}/gradle/java.gradle"
excludedClassesConverage += [ 'datadog.trace.agent.tooling.*' ] excludedClassesConverage += ['datadog.trace.agent.tooling.*']
configurations { configurations {
// classpath used by the instrumentation muzzle plugin // classpath used by the instrumentation muzzle plugin

View File

@ -3,7 +3,11 @@ package datadog.trace.agent.tooling;
import datadog.trace.bootstrap.DatadogClassLoader; import datadog.trace.bootstrap.DatadogClassLoader;
import datadog.trace.bootstrap.PatchLogger; import datadog.trace.bootstrap.PatchLogger;
import io.opentracing.util.GlobalTracer; import io.opentracing.util.GlobalTracer;
import java.util.*; import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
@ -44,7 +48,7 @@ public class ClassLoaderMatcher {
private static final Set<String> CLASSLOADER_CLASSES_TO_SKIP; private static final Set<String> CLASSLOADER_CLASSES_TO_SKIP;
static { static {
final Set<String> classesToSkip = new HashSet<String>(); final Set<String> classesToSkip = new HashSet<>();
classesToSkip.add("org.codehaus.groovy.runtime.callsite.CallSiteClassLoader"); classesToSkip.add("org.codehaus.groovy.runtime.callsite.CallSiteClassLoader");
classesToSkip.add("sun.reflect.DelegatingClassLoader"); classesToSkip.add("sun.reflect.DelegatingClassLoader");
classesToSkip.add("jdk.internal.reflect.DelegatingClassLoader"); classesToSkip.add("jdk.internal.reflect.DelegatingClassLoader");
@ -55,7 +59,7 @@ public class ClassLoaderMatcher {
private SkipClassLoaderMatcher() {} private SkipClassLoaderMatcher() {}
@Override @Override
public boolean matches(ClassLoader target) { public boolean matches(final ClassLoader target) {
if (target == BOOTSTRAP_CLASSLOADER) { if (target == BOOTSTRAP_CLASSLOADER) {
// Don't skip bootstrap loader // Don't skip bootstrap loader
return false; return false;
@ -63,7 +67,7 @@ public class ClassLoaderMatcher {
return shouldSkipClass(target) || shouldSkipInstance(target); return shouldSkipClass(target) || shouldSkipInstance(target);
} }
private boolean shouldSkipClass(ClassLoader loader) { private boolean shouldSkipClass(final ClassLoader loader) {
return CLASSLOADER_CLASSES_TO_SKIP.contains(loader.getClass().getName()); return CLASSLOADER_CLASSES_TO_SKIP.contains(loader.getClass().getName());
} }
@ -77,7 +81,7 @@ public class ClassLoaderMatcher {
if (null != cached) { if (null != cached) {
return cached.booleanValue(); return cached.booleanValue();
} }
boolean skip = !delegatesToBootstrap(loader); final boolean skip = !delegatesToBootstrap(loader);
if (skip) { if (skip) {
log.debug( log.debug(
"skipping classloader instance {} of type {}", loader, loader.getClass().getName()); "skipping classloader instance {} of type {}", loader, loader.getClass().getName());
@ -87,7 +91,7 @@ public class ClassLoaderMatcher {
} }
} }
private boolean delegatesToBootstrap(ClassLoader loader) { private boolean delegatesToBootstrap(final ClassLoader loader) {
boolean delegates = true; boolean delegates = true;
if (!loadsExpectedClass(loader, GlobalTracer.class)) { if (!loadsExpectedClass(loader, GlobalTracer.class)) {
log.debug("loader {} failed to delegate bootstrap opentracing class", loader); log.debug("loader {} failed to delegate bootstrap opentracing class", loader);
@ -100,10 +104,10 @@ public class ClassLoaderMatcher {
return delegates; return delegates;
} }
private boolean loadsExpectedClass(ClassLoader loader, Class<?> expectedClass) { private boolean loadsExpectedClass(final ClassLoader loader, final Class<?> expectedClass) {
try { try {
return loader.loadClass(expectedClass.getName()) == expectedClass; return loader.loadClass(expectedClass.getName()) == expectedClass;
} catch (ClassNotFoundException e) { } catch (final ClassNotFoundException e) {
return false; return false;
} }
} }

View File

@ -12,7 +12,12 @@ import net.bytebuddy.description.field.FieldList;
import net.bytebuddy.description.method.MethodList; import net.bytebuddy.description.method.MethodList;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.implementation.Implementation; import net.bytebuddy.implementation.Implementation;
import net.bytebuddy.jar.asm.*; import net.bytebuddy.jar.asm.ClassVisitor;
import net.bytebuddy.jar.asm.ClassWriter;
import net.bytebuddy.jar.asm.Label;
import net.bytebuddy.jar.asm.MethodVisitor;
import net.bytebuddy.jar.asm.Opcodes;
import net.bytebuddy.jar.asm.Type;
import net.bytebuddy.pool.TypePool; import net.bytebuddy.pool.TypePool;
/** Visit a class and add: a private instrumenationMuzzle field and getter */ /** Visit a class and add: a private instrumenationMuzzle field and getter */

View File

@ -3,7 +3,10 @@ package datadog.trace.agent.tooling.muzzle;
import static datadog.trace.agent.tooling.ClassLoaderMatcher.BOOTSTRAP_CLASSLOADER; import static datadog.trace.agent.tooling.ClassLoaderMatcher.BOOTSTRAP_CLASSLOADER;
import datadog.trace.agent.tooling.Utils; import datadog.trace.agent.tooling.Utils;
import java.util.*; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/** An immutable reference to a jvm class. */ /** An immutable reference to a jvm class. */
public class Reference { public class Reference {

View File

@ -3,8 +3,17 @@ package datadog.trace.agent.tooling.muzzle;
import datadog.trace.agent.tooling.Utils; import datadog.trace.agent.tooling.Utils;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.*; import java.util.ArrayDeque;
import net.bytebuddy.jar.asm.*; import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import net.bytebuddy.jar.asm.ClassReader;
import net.bytebuddy.jar.asm.ClassVisitor;
import net.bytebuddy.jar.asm.Label;
import net.bytebuddy.jar.asm.MethodVisitor;
import net.bytebuddy.jar.asm.Opcodes;
/** Visit a class and collect all references made by the visited class. */ /** Visit a class and collect all references made by the visited class. */
public class ReferenceCreator extends ClassVisitor { public class ReferenceCreator extends ClassVisitor {

View File

@ -3,7 +3,14 @@ package datadog.trace.agent.tooling.muzzle;
import static net.bytebuddy.dynamic.loading.ClassLoadingStrategy.BOOTSTRAP_LOADER; import static net.bytebuddy.dynamic.loading.ClassLoadingStrategy.BOOTSTRAP_LOADER;
import datadog.trace.agent.tooling.Utils; import datadog.trace.agent.tooling.Utils;
import java.util.*; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
/** Matches a set of references against a classloader. */ /** Matches a set of references against a classloader. */

View File

@ -1,10 +1,9 @@
package datadog.trace.agent.test package datadog.trace.agent.test
import datadog.trace.bootstrap.DatadogClassLoader
import datadog.trace.agent.tooling.ClassLoaderMatcher import datadog.trace.agent.tooling.ClassLoaderMatcher
import datadog.trace.bootstrap.DatadogClassLoader
import spock.lang.Specification import spock.lang.Specification
class ClassLoaderMatcherTest extends Specification { class ClassLoaderMatcherTest extends Specification {
def "skip non-delegating classloader"() { def "skip non-delegating classloader"() {
@ -24,7 +23,7 @@ class ClassLoaderMatcherTest extends Specification {
def "does not skip empty classloader"() { def "does not skip empty classloader"() {
setup: setup:
final ClassLoader emptyLoader = new ClassLoader(){} final ClassLoader emptyLoader = new ClassLoader() {}
expect: expect:
!ClassLoaderMatcher.skipClassLoader().matches(emptyLoader) !ClassLoaderMatcher.skipClassLoader().matches(emptyLoader)
} }
@ -37,9 +36,10 @@ class ClassLoaderMatcherTest extends Specification {
/* /*
* A URLClassloader which only delegates java.* classes * A URLClassloader which only delegates java.* classes
*/ */
private static class NonDelegatingClassLoader extends URLClassLoader { private static class NonDelegatingClassLoader extends URLClassLoader {
NonDelegatingClassLoader() { NonDelegatingClassLoader() {
super(new URL[0], (ClassLoader)null) super(new URL[0], (ClassLoader) null)
} }
@Override @Override

View File

@ -1,22 +1,20 @@
package datadog.trace.agent.test package datadog.trace.agent.test
import datadog.trace.bootstrap.ExceptionLogger import ch.qos.logback.classic.Level
import ch.qos.logback.classic.Logger
import ch.qos.logback.core.read.ListAppender
import datadog.trace.agent.tooling.ExceptionHandlers import datadog.trace.agent.tooling.ExceptionHandlers
import datadog.trace.bootstrap.ExceptionLogger
import net.bytebuddy.agent.ByteBuddyAgent import net.bytebuddy.agent.ByteBuddyAgent
import net.bytebuddy.agent.builder.AgentBuilder
import net.bytebuddy.dynamic.ClassFileLocator import net.bytebuddy.dynamic.ClassFileLocator
import org.slf4j.LoggerFactory
import spock.lang.Shared
import spock.lang.Specification
import static net.bytebuddy.matcher.ElementMatchers.isMethod import static net.bytebuddy.matcher.ElementMatchers.isMethod
import static net.bytebuddy.matcher.ElementMatchers.named import static net.bytebuddy.matcher.ElementMatchers.named
import net.bytebuddy.agent.builder.AgentBuilder
import spock.lang.Specification
import spock.lang.Shared
import org.slf4j.LoggerFactory
import ch.qos.logback.classic.Logger
import ch.qos.logback.core.read.ListAppender
import ch.qos.logback.classic.Level
class ExceptionHandlerTest extends Specification { class ExceptionHandlerTest extends Specification {
@Shared @Shared
ListAppender testAppender = new ListAppender() ListAppender testAppender = new ListAppender()
@ -25,7 +23,7 @@ class ExceptionHandlerTest extends Specification {
AgentBuilder builder = new AgentBuilder.Default() AgentBuilder builder = new AgentBuilder.Default()
.disableClassFormatChanges() .disableClassFormatChanges()
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION) .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.type(named(getClass().getName()+'$SomeClass')) .type(named(getClass().getName() + '$SomeClass'))
.transform( .transform(
new AgentBuilder.Transformer.ForAdvice() new AgentBuilder.Transformer.ForAdvice()
.with(new AgentBuilder.LocationStrategy.Simple(ClassFileLocator.ForClassLoader.of(BadAdvice.getClassLoader()))) .with(new AgentBuilder.LocationStrategy.Simple(ClassFileLocator.ForClassLoader.of(BadAdvice.getClassLoader())))
@ -68,11 +66,11 @@ class ExceptionHandlerTest extends Specification {
testAppender.list.get(testAppender.list.size() - 1).getMessage() == "Failed to handle exception in instrumentation" testAppender.list.get(testAppender.list.size() - 1).getMessage() == "Failed to handle exception in instrumentation"
} }
def "exception on non-delegating classloader" () { def "exception on non-delegating classloader"() {
setup: setup:
int initLogEvents = testAppender.list.size() int initLogEvents = testAppender.list.size()
URL[] classpath = [ SomeClass.getProtectionDomain().getCodeSource().getLocation(), URL[] classpath = [SomeClass.getProtectionDomain().getCodeSource().getLocation(),
GroovyObject.getProtectionDomain().getCodeSource().getLocation() ] GroovyObject.getProtectionDomain().getCodeSource().getLocation()]
URLClassLoader loader = new URLClassLoader(classpath, (ClassLoader) null) URLClassLoader loader = new URLClassLoader(classpath, (ClassLoader) null)
when: when:
loader.loadClass(LoggerFactory.getName()) loader.loadClass(LoggerFactory.getName())

View File

@ -1,9 +1,6 @@
package datadog.trace.agent.test package datadog.trace.agent.test
import datadog.trace.agent.tooling.AgentInstaller import datadog.trace.agent.tooling.AgentInstaller
import static datadog.trace.agent.tooling.ClassLoaderMatcher.BOOTSTRAP_CLASSLOADER
import datadog.trace.agent.tooling.HelperInjector import datadog.trace.agent.tooling.HelperInjector
import datadog.trace.agent.tooling.Utils import datadog.trace.agent.tooling.Utils
import net.bytebuddy.agent.ByteBuddyAgent import net.bytebuddy.agent.ByteBuddyAgent
@ -11,6 +8,8 @@ import spock.lang.Specification
import java.lang.reflect.Method import java.lang.reflect.Method
import static datadog.trace.agent.tooling.ClassLoaderMatcher.BOOTSTRAP_CLASSLOADER
class HelperInjectionTest extends Specification { class HelperInjectionTest extends Specification {
def "helpers injected to non-delegating classloader"() { def "helpers injected to non-delegating classloader"() {

View File

@ -14,6 +14,7 @@ jacocoTestReport.dependsOn ':dd-java-agent-ittests:test'
* Note jarname must end in .zip, or its classes will be on the classpath of * Note jarname must end in .zip, or its classes will be on the classpath of
* the dd-java-agent jar. * the dd-java-agent jar.
*/ */
def includeShadowJar(subproject, jarname) { def includeShadowJar(subproject, jarname) {
def agent_project = project def agent_project = project
subproject.afterEvaluate { subproject.afterEvaluate {

View File

@ -1,20 +1,20 @@
import akka.NotUsed import akka.NotUsed
import akka.stream.javadsl.Source import akka.stream.javadsl.Source
import akka.stream.testkit.TestSubscriber.Probe
import akka.stream.testkit.javadsl.TestSink import akka.stream.testkit.javadsl.TestSink
import datadog.trace.agent.test.AgentTestRunner
import datadog.trace.api.DDSpanTypes import datadog.trace.api.DDSpanTypes
import datadog.trace.api.DDTags import datadog.trace.api.DDTags
import io.opentracing.tag.Tags import io.opentracing.tag.Tags
import net.bytebuddy.utility.JavaModule import net.bytebuddy.utility.JavaModule
import datadog.trace.agent.test.AgentTestRunner
import play.inject.guice.GuiceApplicationBuilder import play.inject.guice.GuiceApplicationBuilder
import spock.lang.Shared import spock.lang.Shared
import akka.stream.testkit.TestSubscriber.Probe
import java.util.function.Function import java.util.function.Function
import static com.lightbend.lagom.javadsl.testkit.ServiceTest.* import static com.lightbend.lagom.javadsl.testkit.ServiceTest.TestServer
import static com.lightbend.lagom.javadsl.testkit.ServiceTest.defaultSetup
import static com.lightbend.lagom.javadsl.testkit.ServiceTest.startServer
import static datadog.trace.agent.test.ListWriterAssert.assertTraces import static datadog.trace.agent.test.ListWriterAssert.assertTraces
class LagomTest extends AgentTestRunner { class LagomTest extends AgentTestRunner {
@ -41,30 +41,31 @@ class LagomTest extends AgentTestRunner {
def setupSpec() { def setupSpec() {
server = startServer(defaultSetup() server = startServer(defaultSetup()
.withCluster(false) .withCluster(false)
.withPersistence(false) .withPersistence(false)
.withCassandra(false) .withCassandra(false)
.withJdbc(false) .withJdbc(false)
.withConfigureBuilder( .withConfigureBuilder(
new Function<GuiceApplicationBuilder, GuiceApplicationBuilder>() { new Function<GuiceApplicationBuilder, GuiceApplicationBuilder>() {
@Override @Override
GuiceApplicationBuilder apply(GuiceApplicationBuilder builder) { GuiceApplicationBuilder apply(GuiceApplicationBuilder builder) {
return builder return builder
.bindings(new ServiceTestModule()) .bindings(new ServiceTestModule())
}})) }
}))
} }
def cleanupSpec() { def cleanupSpec() {
server.stop() server.stop()
} }
def "normal request traces" () { def "normal request traces"() {
setup: setup:
EchoService service = server.client(EchoService) EchoService service = server.client(EchoService)
Source<String, NotUsed> input = Source<String, NotUsed> input =
Source.from(Arrays.asList("msg1", "msg2", "msg3")) Source.from(Arrays.asList("msg1", "msg2", "msg3"))
.concat(Source.maybe()) .concat(Source.maybe())
Source<String, NotUsed> output = service.echo().invoke(input) Source<String, NotUsed> output = service.echo().invoke(input)
.toCompletableFuture().get() .toCompletableFuture().get()
Probe<String> probe = output.runWith(TestSink.probe(server.system()), server.materializer()) Probe<String> probe = output.runWith(TestSink.probe(server.system()), server.materializer())
@ -80,7 +81,7 @@ class LagomTest extends AgentTestRunner {
span(0) { span(0) {
serviceName "unnamed-java-app" serviceName "unnamed-java-app"
operationName "akka-http.request" operationName "akka-http.request"
resourceName "GET ws://?/echo" resourceName "GET ws://?/echo"
errored false errored false
tags { tags {
defaultTags() defaultTags()
@ -100,7 +101,7 @@ class LagomTest extends AgentTestRunner {
} }
} }
def "error traces" () { def "error traces"() {
setup: setup:
EchoService service = server.client(EchoService) EchoService service = server.client(EchoService)

View File

@ -1,8 +1,11 @@
import static com.lightbend.lagom.javadsl.api.Service.*; import static com.lightbend.lagom.javadsl.api.Service.named;
import static com.lightbend.lagom.javadsl.api.Service.namedCall;
import akka.NotUsed; import akka.NotUsed;
import akka.stream.javadsl.Source; import akka.stream.javadsl.Source;
import com.lightbend.lagom.javadsl.api.*; import com.lightbend.lagom.javadsl.api.Descriptor;
import com.lightbend.lagom.javadsl.api.Service;
import com.lightbend.lagom.javadsl.api.ServiceCall;
public interface EchoService extends Service { public interface EchoService extends Service {

View File

@ -1,7 +1,9 @@
package datadog.trace.instrumentation.akkahttp; package datadog.trace.instrumentation.akkahttp;
import static io.opentracing.log.Fields.ERROR_OBJECT; import static io.opentracing.log.Fields.ERROR_OBJECT;
import static net.bytebuddy.matcher.ElementMatchers.*; import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.returns;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import akka.NotUsed; import akka.NotUsed;
import akka.http.javadsl.model.headers.RawHeader; import akka.http.javadsl.model.headers.RawHeader;
@ -10,7 +12,7 @@ import akka.http.scaladsl.model.HttpRequest;
import akka.http.scaladsl.model.HttpResponse; import akka.http.scaladsl.model.HttpResponse;
import akka.stream.scaladsl.Flow; import akka.stream.scaladsl.Flow;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.*; 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 io.opentracing.Scope; import io.opentracing.Scope;
@ -92,10 +94,10 @@ public final class AkkaHttpClientInstrumentation extends Instrumenter.Default {
.withTag(Tags.HTTP_METHOD.getKey(), request.method().value()) .withTag(Tags.HTTP_METHOD.getKey(), request.method().value())
.withTag(Tags.HTTP_URL.getKey(), request.getUri().toString()); .withTag(Tags.HTTP_URL.getKey(), request.getUri().toString());
} }
Scope scope = builder.startActive(false); final Scope scope = builder.startActive(false);
if (request != null) { if (request != null) {
AkkaHttpHeaders headers = new AkkaHttpHeaders(request); final AkkaHttpHeaders headers = new AkkaHttpHeaders(request);
GlobalTracer.get().inject(scope.span().context(), Format.Builtin.HTTP_HEADERS, headers); GlobalTracer.get().inject(scope.span().context(), Format.Builtin.HTTP_HEADERS, headers);
// Request is immutable, so we have to assign new value once we update headers // Request is immutable, so we have to assign new value once we update headers
request = headers.getRequest(); request = headers.getRequest();
@ -111,7 +113,7 @@ public final class AkkaHttpClientInstrumentation extends Instrumenter.Default {
@Advice.Return final Future<HttpResponse> responseFuture, @Advice.Return final Future<HttpResponse> responseFuture,
@Advice.Enter final Scope scope, @Advice.Enter final Scope scope,
@Advice.Thrown final Throwable throwable) { @Advice.Thrown final Throwable throwable) {
Span span = scope.span(); final Span span = scope.span();
if (throwable == null) { if (throwable == null) {
responseFuture.onComplete(new OnCompleteHandler(span), thiz.system().dispatcher()); responseFuture.onComplete(new OnCompleteHandler(span), thiz.system().dispatcher());
} else { } else {
@ -135,12 +137,12 @@ public final class AkkaHttpClientInstrumentation extends Instrumenter.Default {
public static class OnCompleteHandler extends AbstractFunction1<Try<HttpResponse>, Void> { public static class OnCompleteHandler extends AbstractFunction1<Try<HttpResponse>, Void> {
private final Span span; private final Span span;
public OnCompleteHandler(Span span) { public OnCompleteHandler(final Span span) {
this.span = span; this.span = span;
} }
@Override @Override
public Void apply(Try<HttpResponse> result) { public Void apply(final Try<HttpResponse> result) {
if (result.isSuccess()) { if (result.isSuccess()) {
Tags.HTTP_STATUS.set(span, result.get().status().intValue()); Tags.HTTP_STATUS.set(span, result.get().status().intValue());
} else { } else {
@ -155,7 +157,7 @@ public final class AkkaHttpClientInstrumentation extends Instrumenter.Default {
public static class AkkaHttpHeaders implements TextMap { public static class AkkaHttpHeaders implements TextMap {
private HttpRequest request; private HttpRequest request;
public AkkaHttpHeaders(HttpRequest request) { public AkkaHttpHeaders(final HttpRequest request) {
this.request = request; this.request = request;
} }

View File

@ -4,11 +4,10 @@ import java.util.Collections
import akka.NotUsed import akka.NotUsed
import akka.http.scaladsl.model.{HttpRequest, HttpResponse} import akka.http.scaladsl.model.{HttpRequest, HttpResponse}
import akka.stream.Supervision
import akka.stream.scaladsl.Flow import akka.stream.scaladsl.Flow
import datadog.trace.api.{DDSpanTypes, DDTags} import datadog.trace.api.{DDSpanTypes, DDTags}
import io.opentracing.Span
import io.opentracing.log.Fields.ERROR_OBJECT import io.opentracing.log.Fields.ERROR_OBJECT
import io.opentracing.{Scope, Span}
import io.opentracing.propagation.Format import io.opentracing.propagation.Format
import io.opentracing.tag.Tags import io.opentracing.tag.Tags
import io.opentracing.util.GlobalTracer import io.opentracing.util.GlobalTracer

View File

@ -1,14 +1,15 @@
package datadog.trace.instrumentation.akkahttp; package datadog.trace.instrumentation.akkahttp;
import static io.opentracing.log.Fields.ERROR_OBJECT; import static io.opentracing.log.Fields.ERROR_OBJECT;
import static net.bytebuddy.matcher.ElementMatchers.*; import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import akka.http.javadsl.model.HttpHeader; import akka.http.javadsl.model.HttpHeader;
import akka.http.scaladsl.model.HttpRequest; import akka.http.scaladsl.model.HttpRequest;
import akka.http.scaladsl.model.HttpResponse; import akka.http.scaladsl.model.HttpResponse;
import akka.stream.*; import akka.stream.Materializer;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.*; 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;
@ -19,7 +20,10 @@ import io.opentracing.propagation.Format;
import io.opentracing.propagation.TextMap; import io.opentracing.propagation.TextMap;
import io.opentracing.tag.Tags; import io.opentracing.tag.Tags;
import io.opentracing.util.GlobalTracer; import io.opentracing.util.GlobalTracer;
import java.util.*; import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
@ -90,13 +94,13 @@ public final class AkkaHttpServerInstrumentation extends Instrumenter.Default {
public static void wrapHandler( public static void wrapHandler(
@Advice.Argument(value = 0, readOnly = false) @Advice.Argument(value = 0, readOnly = false)
Function1<HttpRequest, scala.concurrent.Future<HttpResponse>> handler, Function1<HttpRequest, scala.concurrent.Future<HttpResponse>> handler,
@Advice.Argument(value = 7) Materializer materializer) { @Advice.Argument(value = 7) final Materializer materializer) {
handler = new DatadogAsyncWrapper(handler, materializer.executionContext()); handler = new DatadogAsyncWrapper(handler, materializer.executionContext());
} }
} }
public static class DatadogWrapperHelper { public static class DatadogWrapperHelper {
public static Scope createSpan(HttpRequest request) { public static Scope createSpan(final HttpRequest request) {
final SpanContext extractedContext = final SpanContext extractedContext =
GlobalTracer.get() GlobalTracer.get()
.extract(Format.Builtin.HTTP_HEADERS, new AkkaHttpServerHeaders(request)); .extract(Format.Builtin.HTTP_HEADERS, new AkkaHttpServerHeaders(request));
@ -117,7 +121,7 @@ public final class AkkaHttpServerInstrumentation extends Instrumenter.Default {
return scope; return scope;
} }
public static void finishSpan(Span span, HttpResponse response) { public static void finishSpan(final Span span, final HttpResponse response) {
Tags.HTTP_STATUS.set(span, response.status().intValue()); Tags.HTTP_STATUS.set(span, response.status().intValue());
if (GlobalTracer.get().scopeManager().active() instanceof TraceScope) { if (GlobalTracer.get().scopeManager().active() instanceof TraceScope) {
@ -126,7 +130,7 @@ public final class AkkaHttpServerInstrumentation extends Instrumenter.Default {
span.finish(); span.finish();
} }
public static void finishSpan(Span span, Throwable t) { public static void finishSpan(final Span span, final Throwable t) {
Tags.ERROR.set(span, true); Tags.ERROR.set(span, true);
span.log(Collections.singletonMap(ERROR_OBJECT, t)); span.log(Collections.singletonMap(ERROR_OBJECT, t));
Tags.HTTP_STATUS.set(span, 500); Tags.HTTP_STATUS.set(span, 500);
@ -141,19 +145,19 @@ public final class AkkaHttpServerInstrumentation extends Instrumenter.Default {
public static class DatadogSyncWrapper extends AbstractFunction1<HttpRequest, HttpResponse> { public static class DatadogSyncWrapper extends AbstractFunction1<HttpRequest, HttpResponse> {
private final Function1<HttpRequest, HttpResponse> userHandler; private final Function1<HttpRequest, HttpResponse> userHandler;
public DatadogSyncWrapper(Function1<HttpRequest, HttpResponse> userHandler) { public DatadogSyncWrapper(final Function1<HttpRequest, HttpResponse> userHandler) {
this.userHandler = userHandler; this.userHandler = userHandler;
} }
@Override @Override
public HttpResponse apply(HttpRequest request) { public HttpResponse apply(final HttpRequest request) {
final Scope scope = DatadogWrapperHelper.createSpan(request); final Scope scope = DatadogWrapperHelper.createSpan(request);
try { try {
final HttpResponse response = userHandler.apply(request); final HttpResponse response = userHandler.apply(request);
scope.close(); scope.close();
DatadogWrapperHelper.finishSpan(scope.span(), response); DatadogWrapperHelper.finishSpan(scope.span(), response);
return response; return response;
} catch (Throwable t) { } catch (final Throwable t) {
scope.close(); scope.close();
DatadogWrapperHelper.finishSpan(scope.span(), t); DatadogWrapperHelper.finishSpan(scope.span(), t);
throw t; throw t;
@ -167,19 +171,19 @@ public final class AkkaHttpServerInstrumentation extends Instrumenter.Default {
private final ExecutionContext executionContext; private final ExecutionContext executionContext;
public DatadogAsyncWrapper( public DatadogAsyncWrapper(
Function1<HttpRequest, Future<HttpResponse>> userHandler, final Function1<HttpRequest, Future<HttpResponse>> userHandler,
ExecutionContext executionContext) { final ExecutionContext executionContext) {
this.userHandler = userHandler; this.userHandler = userHandler;
this.executionContext = executionContext; this.executionContext = executionContext;
} }
@Override @Override
public Future<HttpResponse> apply(HttpRequest request) { public Future<HttpResponse> apply(final HttpRequest request) {
final Scope scope = DatadogWrapperHelper.createSpan(request); final Scope scope = DatadogWrapperHelper.createSpan(request);
Future<HttpResponse> futureResponse = null; Future<HttpResponse> futureResponse = null;
try { try {
futureResponse = userHandler.apply(request); futureResponse = userHandler.apply(request);
} catch (Throwable t) { } catch (final Throwable t) {
scope.close(); scope.close();
DatadogWrapperHelper.finishSpan(scope.span(), t); DatadogWrapperHelper.finishSpan(scope.span(), t);
throw t; throw t;
@ -188,14 +192,14 @@ public final class AkkaHttpServerInstrumentation extends Instrumenter.Default {
futureResponse.transform( futureResponse.transform(
new AbstractFunction1<HttpResponse, HttpResponse>() { new AbstractFunction1<HttpResponse, HttpResponse>() {
@Override @Override
public HttpResponse apply(HttpResponse response) { public HttpResponse apply(final HttpResponse response) {
DatadogWrapperHelper.finishSpan(scope.span(), response); DatadogWrapperHelper.finishSpan(scope.span(), response);
return response; return response;
} }
}, },
new AbstractFunction1<Throwable, Throwable>() { new AbstractFunction1<Throwable, Throwable>() {
@Override @Override
public Throwable apply(Throwable t) { public Throwable apply(final Throwable t) {
DatadogWrapperHelper.finishSpan(scope.span(), t); DatadogWrapperHelper.finishSpan(scope.span(), t);
return t; return t;
} }
@ -209,7 +213,7 @@ public final class AkkaHttpServerInstrumentation extends Instrumenter.Default {
public static class AkkaHttpServerHeaders implements TextMap { public static class AkkaHttpServerHeaders implements TextMap {
private final HttpRequest request; private final HttpRequest request;
public AkkaHttpServerHeaders(HttpRequest request) { public AkkaHttpServerHeaders(final HttpRequest request) {
this.request = request; this.request = request;
} }
@ -217,7 +221,7 @@ public final class AkkaHttpServerInstrumentation extends Instrumenter.Default {
public Iterator<Map.Entry<String, String>> iterator() { public Iterator<Map.Entry<String, String>> iterator() {
final Map<String, String> javaMap = new HashMap<>(request.headers().size()); final Map<String, String> javaMap = new HashMap<>(request.headers().size());
for (HttpHeader header : request.getHeaders()) { for (final HttpHeader header : request.getHeaders()) {
javaMap.put(header.name(), header.value()); javaMap.put(header.name(), header.value());
} }
@ -225,7 +229,7 @@ public final class AkkaHttpServerInstrumentation extends Instrumenter.Default {
} }
@Override @Override
public void put(String name, String value) { public void put(final String name, final String value) {
throw new IllegalStateException("akka http server headers can only be extracted"); throw new IllegalStateException("akka http server headers can only be extracted");
} }
} }

View File

@ -55,9 +55,9 @@ class AkkaHttpClientInstrumentationTest extends AgentTestRunner {
@Shared @Shared
ActorMaterializer materializer = ActorMaterializer.create(system) ActorMaterializer materializer = ActorMaterializer.create(system)
def pool = Http.get(system).<Integer>superPool(materializer) def pool = Http.get(system).<Integer> superPool(materializer)
def "#route request trace" () { def "#route request trace"() {
setup: setup:
def url = server.address.resolve("/" + route).toURL() def url = server.address.resolve("/" + route).toURL()
@ -116,7 +116,7 @@ class AkkaHttpClientInstrumentationTest extends AgentTestRunner {
"error" | 500 | true | null "error" | 500 | true | null
} }
def "error request trace" () { def "error request trace"() {
setup: setup:
def url = new URL("http://localhost:${server.address.port + 1}/test") def url = new URL("http://localhost:${server.address.port + 1}/test")
@ -153,7 +153,7 @@ class AkkaHttpClientInstrumentationTest extends AgentTestRunner {
} }
} }
def "singleRequest exception trace" () { def "singleRequest exception trace"() {
when: when:
// Passing null causes NPE in singleRequest // Passing null causes NPE in singleRequest
Http.get(system).singleRequest(null, materializer) Http.get(system).singleRequest(null, materializer)
@ -183,14 +183,14 @@ class AkkaHttpClientInstrumentationTest extends AgentTestRunner {
} }
def "#route pool request trace" () { def "#route pool request trace"() {
setup: setup:
def url = server.address.resolve("/" + route).toURL() def url = server.address.resolve("/" + route).toURL()
CompletionStage<Pair<Try<HttpResponse>, Integer>> sink = Source CompletionStage<Pair<Try<HttpResponse>, Integer>> sink = Source
.<Pair<HttpRequest, Integer>>single(new Pair(HttpRequest.create(url.toString()), 1)) .<Pair<HttpRequest, Integer>> single(new Pair(HttpRequest.create(url.toString()), 1))
.via(pool) .via(pool)
.runWith(Sink.<Pair<Try<HttpResponse>, Integer>>head(), materializer) .runWith(Sink.<Pair<Try<HttpResponse>, Integer>> head(), materializer)
when: when:
HttpResponse response = sink.toCompletableFuture().get().first().get() HttpResponse response = sink.toCompletableFuture().get().first().get()
@ -242,14 +242,14 @@ class AkkaHttpClientInstrumentationTest extends AgentTestRunner {
"error" | 500 | true | null "error" | 500 | true | null
} }
def "error request pool trace" () { def "error request pool trace"() {
setup: setup:
def url = new URL("http://localhost:${server.address.port + 1}/test") def url = new URL("http://localhost:${server.address.port + 1}/test")
CompletionStage<Pair<Try<HttpResponse>, Integer>> sink = Source CompletionStage<Pair<Try<HttpResponse>, Integer>> sink = Source
.<Pair<HttpRequest, Integer>>single(new Pair(HttpRequest.create(url.toString()), 1)) .<Pair<HttpRequest, Integer>> single(new Pair(HttpRequest.create(url.toString()), 1))
.via(pool) .via(pool)
.runWith(Sink.<Pair<Try<HttpResponse>, Integer>>head(), materializer) .runWith(Sink.<Pair<Try<HttpResponse>, Integer>> head(), materializer)
def response = sink.toCompletableFuture().get().first() def response = sink.toCompletableFuture().get().first()
when: when:

View File

@ -30,7 +30,7 @@ class AkkaHttpServerInstrumentationTest extends AgentTestRunner {
AkkaHttpTestSyncWebServer.stop() AkkaHttpTestSyncWebServer.stop()
} }
def "#server 200 request trace" () { def "#server 200 request trace"() {
setup: setup:
OkHttpClient client = new OkHttpClient.Builder().build() OkHttpClient client = new OkHttpClient.Builder().build()
def request = new Request.Builder() def request = new Request.Builder()
@ -71,12 +71,12 @@ class AkkaHttpServerInstrumentationTest extends AgentTestRunner {
} }
where: where:
server | port server | port
"async" | asyncPort "async" | asyncPort
"sync" | syncPort "sync" | syncPort
} }
def "#server exceptions trace for #endpoint" () { def "#server exceptions trace for #endpoint"() {
setup: setup:
OkHttpClient client = new OkHttpClient.Builder().build() OkHttpClient client = new OkHttpClient.Builder().build()
def request = new Request.Builder() def request = new Request.Builder()
@ -110,13 +110,13 @@ class AkkaHttpServerInstrumentationTest extends AgentTestRunner {
} }
where: where:
server | port | endpoint | errorMessage server | port | endpoint | errorMessage
"async" | asyncPort | "throw-handler" | "Oh no handler" "async" | asyncPort | "throw-handler" | "Oh no handler"
"async" | asyncPort | "throw-callback" | "Oh no callback" "async" | asyncPort | "throw-callback" | "Oh no callback"
"sync" | syncPort | "throw-handler" | "Oh no handler" "sync" | syncPort | "throw-handler" | "Oh no handler"
} }
def "#server 5xx trace" () { def "#server 5xx trace"() {
setup: setup:
OkHttpClient client = new OkHttpClient.Builder().build() OkHttpClient client = new OkHttpClient.Builder().build()
def request = new Request.Builder() def request = new Request.Builder()
@ -150,12 +150,12 @@ class AkkaHttpServerInstrumentationTest extends AgentTestRunner {
} }
where: where:
server | port server | port
"async" | asyncPort "async" | asyncPort
"sync" | syncPort "sync" | syncPort
} }
def "#server 4xx trace" () { def "#server 4xx trace"() {
setup: setup:
OkHttpClient client = new OkHttpClient.Builder().build() OkHttpClient client = new OkHttpClient.Builder().build()
def request = new Request.Builder() def request = new Request.Builder()
@ -188,8 +188,8 @@ class AkkaHttpServerInstrumentationTest extends AgentTestRunner {
} }
where: where:
server | port server | port
"async" | asyncPort "async" | asyncPort
"sync" | syncPort "sync" | syncPort
} }
} }

View File

@ -1,8 +1,8 @@
import akka.actor.ActorSystem import akka.actor.ActorSystem
import akka.http.scaladsl.Http import akka.http.scaladsl.Http
import akka.http.scaladsl.Http.ServerBinding import akka.http.scaladsl.Http.ServerBinding
import akka.http.scaladsl.model._
import akka.http.scaladsl.model.HttpMethods.GET import akka.http.scaladsl.model.HttpMethods.GET
import akka.http.scaladsl.model._
import akka.stream.ActorMaterializer import akka.stream.ActorMaterializer
import datadog.trace.agent.test.TestUtils import datadog.trace.agent.test.TestUtils
import datadog.trace.api.Trace import datadog.trace.api.Trace
@ -37,7 +37,7 @@ object AkkaHttpTestAsyncWebServer {
} }
} }
private var binding :ServerBinding = null private var binding: ServerBinding = null
def start(): Unit = synchronized { def start(): Unit = synchronized {
if (null == binding) { if (null == binding) {
@ -77,7 +77,7 @@ object AkkaHttpTestSyncWebServer {
HttpResponse(entity = "Not found unit test.", status = StatusCodes.NotFound) HttpResponse(entity = "Not found unit test.", status = StatusCodes.NotFound)
} }
private var binding :ServerBinding = null private var binding: ServerBinding = null
def start(): Unit = synchronized { def start(): Unit = synchronized {
if (null == binding) { if (null == binding) {

View File

@ -13,7 +13,11 @@
*/ */
package datadog.trace.instrumentation.aws.v0; package datadog.trace.instrumentation.aws.v0;
import static io.opentracing.log.Fields.*; import static io.opentracing.log.Fields.ERROR_KIND;
import static io.opentracing.log.Fields.ERROR_OBJECT;
import static io.opentracing.log.Fields.EVENT;
import static io.opentracing.log.Fields.MESSAGE;
import static io.opentracing.log.Fields.STACK;
import com.amazonaws.AmazonWebServiceResponse; import com.amazonaws.AmazonWebServiceResponse;
import com.amazonaws.Request; import com.amazonaws.Request;

View File

@ -13,7 +13,11 @@
*/ */
package datadog.trace.instrumentation.aws.v106; package datadog.trace.instrumentation.aws.v106;
import static io.opentracing.log.Fields.*; import static io.opentracing.log.Fields.ERROR_KIND;
import static io.opentracing.log.Fields.ERROR_OBJECT;
import static io.opentracing.log.Fields.EVENT;
import static io.opentracing.log.Fields.MESSAGE;
import static io.opentracing.log.Fields.STACK;
import com.amazonaws.AmazonWebServiceResponse; import com.amazonaws.AmazonWebServiceResponse;
import com.amazonaws.Request; import com.amazonaws.Request;

View File

@ -13,7 +13,11 @@
*/ */
package datadog.trace.instrumentation.datastax.cassandra; package datadog.trace.instrumentation.datastax.cassandra;
import static io.opentracing.log.Fields.*; import static io.opentracing.log.Fields.ERROR_KIND;
import static io.opentracing.log.Fields.ERROR_OBJECT;
import static io.opentracing.log.Fields.EVENT;
import static io.opentracing.log.Fields.MESSAGE;
import static io.opentracing.log.Fields.STACK;
import com.datastax.driver.core.BoundStatement; import com.datastax.driver.core.BoundStatement;
import com.datastax.driver.core.CloseFuture; import com.datastax.driver.core.CloseFuture;
@ -244,7 +248,7 @@ class TracingSession implements Session {
public void run() { public void run() {
try { try {
finishSpan(span, future.get()); finishSpan(span, future.get());
} catch (InterruptedException | ExecutionException e) { } catch (final InterruptedException | ExecutionException e) {
finishSpan(span, e); finishSpan(span, e);
} }
} }

View File

@ -40,7 +40,7 @@ class CassandraClientTest extends AgentTestRunner {
session.execute("DROP KEYSPACE IF EXISTS sync_test") session.execute("DROP KEYSPACE IF EXISTS sync_test")
session.execute( session.execute(
"CREATE KEYSPACE sync_test WITH REPLICATION = {'class':'SimpleStrategy', 'replication_factor':3}") "CREATE KEYSPACE sync_test WITH REPLICATION = {'class':'SimpleStrategy', 'replication_factor':3}")
session.execute("CREATE TABLE sync_test.users ( id UUID PRIMARY KEY, name text )") session.execute("CREATE TABLE sync_test.users ( id UUID PRIMARY KEY, name text )")
session.execute("INSERT INTO sync_test.users (id, name) values (uuid(), 'alice')") session.execute("INSERT INTO sync_test.users (id, name) values (uuid(), 'alice')")
session.execute("SELECT * FROM sync_test.users where name = 'alice' ALLOW FILTERING") session.execute("SELECT * FROM sync_test.users where name = 'alice' ALLOW FILTERING")
@ -72,15 +72,15 @@ class CassandraClientTest extends AgentTestRunner {
session.executeAsync("DROP KEYSPACE IF EXISTS async_test").get() session.executeAsync("DROP KEYSPACE IF EXISTS async_test").get()
session session
.executeAsync( .executeAsync(
"CREATE KEYSPACE async_test WITH REPLICATION = {'class':'SimpleStrategy', 'replication_factor':3}") "CREATE KEYSPACE async_test WITH REPLICATION = {'class':'SimpleStrategy', 'replication_factor':3}")
.get() .get()
session.executeAsync("CREATE TABLE async_test.users ( id UUID PRIMARY KEY, name text )").get() session.executeAsync("CREATE TABLE async_test.users ( id UUID PRIMARY KEY, name text )").get()
session.executeAsync("INSERT INTO async_test.users (id, name) values (uuid(), 'alice')").get() session.executeAsync("INSERT INTO async_test.users (id, name) values (uuid(), 'alice')").get()
TEST_WRITER.waitForTraces(4) TEST_WRITER.waitForTraces(4)
session session
.executeAsync("SELECT * FROM async_test.users where name = 'alice' ALLOW FILTERING") .executeAsync("SELECT * FROM async_test.users where name = 'alice' ALLOW FILTERING")
.get() .get()
TEST_WRITER.waitForTraces(5) TEST_WRITER.waitForTraces(5)
def query = "SELECT * FROM async_test.users where name = 'alice' ALLOW FILTERING" def query = "SELECT * FROM async_test.users where name = 'alice' ALLOW FILTERING"

View File

@ -39,7 +39,7 @@ class Elasticsearch2NodeClientTest extends AgentTestRunner {
def settings = Settings.builder() def settings = Settings.builder()
.put("path.home", esWorkingDir.path) .put("path.home", esWorkingDir.path)
// Since we use listeners to close spans this should make our span closing deterministic which is good for tests // Since we use listeners to close spans this should make our span closing deterministic which is good for tests
.put("threadpool.listener.size", 1) .put("threadpool.listener.size", 1)
.put("http.port", httpPort) .put("http.port", httpPort)
.put("transport.tcp.port", tcpPort) .put("transport.tcp.port", tcpPort)

View File

@ -50,7 +50,7 @@ class Elasticsearch2SpringTemplateTest extends AgentTestRunner {
def settings = Settings.builder() def settings = Settings.builder()
.put("path.home", esWorkingDir.path) .put("path.home", esWorkingDir.path)
// Since we use listeners to close spans this should make our span closing deterministic which is good for tests // Since we use listeners to close spans this should make our span closing deterministic which is good for tests
.put("threadpool.listener.size", 1) .put("threadpool.listener.size", 1)
.put("http.port", httpPort) .put("http.port", httpPort)
.put("transport.tcp.port", tcpPort) .put("transport.tcp.port", tcpPort)

View File

@ -51,7 +51,7 @@ class Elasticsearch2TransportClientTest extends AgentTestRunner {
client = TransportClient.builder().settings( client = TransportClient.builder().settings(
Settings.builder() Settings.builder()
// Since we use listeners to close spans this should make our span closing deterministic which is good for tests // Since we use listeners to close spans this should make our span closing deterministic which is good for tests
.put("threadpool.listener.size", 1) .put("threadpool.listener.size", 1)
.put("cluster.name", "test-cluster") .put("cluster.name", "test-cluster")
.build() .build()

View File

@ -42,7 +42,7 @@ class Elasticsearch5NodeClientTest extends AgentTestRunner {
def settings = Settings.builder() def settings = Settings.builder()
.put("path.home", esWorkingDir.path) .put("path.home", esWorkingDir.path)
// Since we use listeners to close spans this should make our span closing deterministic which is good for tests // Since we use listeners to close spans this should make our span closing deterministic which is good for tests
.put("thread_pool.listener.size", 1) .put("thread_pool.listener.size", 1)
.put("http.port", httpPort) .put("http.port", httpPort)
.put("transport.tcp.port", tcpPort) .put("transport.tcp.port", tcpPort)

View File

@ -58,7 +58,7 @@ class Elasticsearch5TransportClientTest extends AgentTestRunner {
client = new PreBuiltTransportClient( client = new PreBuiltTransportClient(
Settings.builder() Settings.builder()
// Since we use listeners to close spans this should make our span closing deterministic which is good for tests // Since we use listeners to close spans this should make our span closing deterministic which is good for tests
.put("thread_pool.listener.size", 1) .put("thread_pool.listener.size", 1)
.put(CLUSTER_NAME_SETTING.getKey(), "test-cluster") .put(CLUSTER_NAME_SETTING.getKey(), "test-cluster")
.build() .build()

View File

@ -41,7 +41,7 @@ class Elasticsearch6NodeClientTest extends AgentTestRunner {
def settings = Settings.builder() def settings = Settings.builder()
.put("path.home", esWorkingDir.path) .put("path.home", esWorkingDir.path)
// Since we use listeners to close spans this should make our span closing deterministic which is good for tests // Since we use listeners to close spans this should make our span closing deterministic which is good for tests
.put("thread_pool.listener.size", 1) .put("thread_pool.listener.size", 1)
.put("http.port", httpPort) .put("http.port", httpPort)
.put("transport.tcp.port", tcpPort) .put("transport.tcp.port", tcpPort)

View File

@ -55,7 +55,7 @@ class Elasticsearch6TransportClientTest extends AgentTestRunner {
client = new PreBuiltTransportClient( client = new PreBuiltTransportClient(
Settings.builder() Settings.builder()
// Since we use listeners to close spans this should make our span closing deterministic which is good for tests // Since we use listeners to close spans this should make our span closing deterministic which is good for tests
.put("thread_pool.listener.size", 1) .put("thread_pool.listener.size", 1)
.put(CLUSTER_NAME_SETTING.getKey(), "test-cluster") .put(CLUSTER_NAME_SETTING.getKey(), "test-cluster")
.build() .build()

View File

@ -14,7 +14,9 @@ import io.opentracing.Span;
import io.opentracing.tag.Tags; import io.opentracing.tag.Tags;
import io.opentracing.util.GlobalTracer; import io.opentracing.util.GlobalTracer;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.*; import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
@ -34,7 +36,7 @@ public class HystrixCommandInstrumentation extends Instrumenter.Default {
@Override @Override
public Map<ElementMatcher, String> transformers() { public Map<ElementMatcher, String> transformers() {
Map<ElementMatcher, String> transformers = new HashMap<>(); final Map<ElementMatcher, String> transformers = new HashMap<>();
transformers.put( transformers.put(
isMethod().and(named("run").or(named("getFallback"))), TraceAdvice.class.getName()); isMethod().and(named("run").or(named("getFallback"))), TraceAdvice.class.getName());
return transformers; return transformers;

View File

@ -10,7 +10,8 @@ import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.context.TraceScope; import datadog.trace.context.TraceScope;
import io.opentracing.Scope; import io.opentracing.Scope;
import io.opentracing.util.GlobalTracer; import io.opentracing.util.GlobalTracer;
import java.util.*; import java.util.HashMap;
import java.util.Map;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;

View File

@ -40,7 +40,7 @@ subprojects { subProj ->
} }
} }
excludedClassesConverage += [ 'datadog.trace.instrumentation.*' ] excludedClassesConverage += ['datadog.trace.instrumentation.*']
dependencies { dependencies {
compile(project(':dd-java-agent:agent-tooling')) { compile(project(':dd-java-agent:agent-tooling')) {

View File

@ -1,7 +1,7 @@
apply from: "${rootDir}/gradle/java.gradle" apply from: "${rootDir}/gradle/java.gradle"
apply plugin: 'scala' apply plugin: 'scala'
excludedClassesConverage += [ '*' ] excludedClassesConverage += ['*']
dependencies { dependencies {
compile project(':dd-trace-api') compile project(':dd-trace-api')

View File

@ -26,26 +26,28 @@ object AkkaActors {
} }
class AkkaActors { class AkkaActors {
import AkkaActors._ import AkkaActors._
import Greeter._ import Greeter._
implicit val timeout: Timeout = 5.minutes implicit val timeout: Timeout = 5.minutes
@Trace @Trace
def basicTell() : Unit = { def basicTell(): Unit = {
GlobalTracer.get().scopeManager().active().asInstanceOf[TraceScope].setAsyncPropagation(true) GlobalTracer.get().scopeManager().active().asInstanceOf[TraceScope].setAsyncPropagation(true)
howdyGreeter ! WhoToGreet("Akka") howdyGreeter ! WhoToGreet("Akka")
howdyGreeter ! Greet howdyGreeter ! Greet
} }
@Trace @Trace
def basicAsk() : Unit = { def basicAsk(): Unit = {
GlobalTracer.get().scopeManager().active().asInstanceOf[TraceScope].setAsyncPropagation(true) GlobalTracer.get().scopeManager().active().asInstanceOf[TraceScope].setAsyncPropagation(true)
howdyGreeter ! WhoToGreet("Akka") howdyGreeter ! WhoToGreet("Akka")
howdyGreeter ? Greet howdyGreeter ? Greet
} }
@Trace @Trace
def basicForward() : Unit = { def basicForward(): Unit = {
GlobalTracer.get().scopeManager().active().asInstanceOf[TraceScope].setAsyncPropagation(true) GlobalTracer.get().scopeManager().active().asInstanceOf[TraceScope].setAsyncPropagation(true)
helloGreeter ! WhoToGreet("Akka") helloGreeter ! WhoToGreet("Akka")
helloGreeter ? Greet helloGreeter ? Greet
@ -54,11 +56,15 @@ class AkkaActors {
object Greeter { object Greeter {
def props(message: String, receiverActor: ActorRef): Props = Props(new Greeter(message, receiverActor)) def props(message: String, receiverActor: ActorRef): Props = Props(new Greeter(message, receiverActor))
final case class WhoToGreet(who: String) final case class WhoToGreet(who: String)
case object Greet case object Greet
} }
class Greeter(message: String, receiverActor: ActorRef) extends Actor { class Greeter(message: String, receiverActor: ActorRef) extends Actor {
import Greeter._ import Greeter._
import Receiver._ import Receiver._
@ -67,17 +73,20 @@ class Greeter(message: String, receiverActor: ActorRef) extends Actor {
def receive = { def receive = {
case WhoToGreet(who) => case WhoToGreet(who) =>
greeting = s"$message, $who" greeting = s"$message, $who"
case Greet => case Greet =>
receiverActor ! Greeting(greeting) receiverActor ! Greeting(greeting)
} }
} }
object Receiver { object Receiver {
def props: Props = Props[Receiver] def props: Props = Props[Receiver]
final case class Greeting(greeting: String) final case class Greeting(greeting: String)
} }
class Receiver extends Actor with ActorLogging { class Receiver extends Actor with ActorLogging {
import Receiver._ import Receiver._
def receive = { def receive = {

View File

@ -12,7 +12,7 @@ class ScalaConcurrentTests {
* @return Number of expected spans in the trace * @return Number of expected spans in the trace
*/ */
@Trace @Trace
def traceWithFutureAndCallbacks() : Integer = { def traceWithFutureAndCallbacks(): Integer = {
GlobalTracer.get().scopeManager().active().asInstanceOf[TraceScope].setAsyncPropagation(true) GlobalTracer.get().scopeManager().active().asInstanceOf[TraceScope].setAsyncPropagation(true)
val goodFuture: Future[Integer] = Future { val goodFuture: Future[Integer] = Future {
tracedChild("goodFuture") tracedChild("goodFuture")
@ -33,7 +33,7 @@ class ScalaConcurrentTests {
} }
@Trace @Trace
def tracedAcrossThreadsWithNoTrace() :Integer = { def tracedAcrossThreadsWithNoTrace(): Integer = {
GlobalTracer.get().scopeManager().active().asInstanceOf[TraceScope].setAsyncPropagation(true) GlobalTracer.get().scopeManager().active().asInstanceOf[TraceScope].setAsyncPropagation(true)
val goodFuture: Future[Integer] = Future { val goodFuture: Future[Integer] = Future {
1 1
@ -53,7 +53,7 @@ class ScalaConcurrentTests {
* @return Number of expected spans in the trace * @return Number of expected spans in the trace
*/ */
@Trace @Trace
def traceWithPromises() : Integer = { def traceWithPromises(): Integer = {
GlobalTracer.get().scopeManager().active().asInstanceOf[TraceScope].setAsyncPropagation(true) GlobalTracer.get().scopeManager().active().asInstanceOf[TraceScope].setAsyncPropagation(true)
val keptPromise = Promise[Boolean]() val keptPromise = Promise[Boolean]()
val brokenPromise = Promise[Boolean]() val brokenPromise = Promise[Boolean]()
@ -86,7 +86,7 @@ class ScalaConcurrentTests {
* @return Number of expected spans in the trace * @return Number of expected spans in the trace
*/ */
@Trace @Trace
def tracedWithFutureFirstCompletions() :Integer = { def tracedWithFutureFirstCompletions(): Integer = {
GlobalTracer.get().scopeManager().active().asInstanceOf[TraceScope].setAsyncPropagation(true) GlobalTracer.get().scopeManager().active().asInstanceOf[TraceScope].setAsyncPropagation(true)
val completedVal = Future.firstCompletedOf( val completedVal = Future.firstCompletedOf(
List( List(
@ -114,7 +114,7 @@ class ScalaConcurrentTests {
GlobalTracer.get().scopeManager().active().asInstanceOf[TraceScope].setAsyncPropagation(true) GlobalTracer.get().scopeManager().active().asInstanceOf[TraceScope].setAsyncPropagation(true)
val f: Future[String] = Future { val f: Future[String] = Future {
tracedChild("timeoutChild") tracedChild("timeoutChild")
while(true) { while (true) {
// never actually finish // never actually finish
} }
"done" "done"

View File

@ -8,13 +8,19 @@ import static net.bytebuddy.matcher.ElementMatchers.not;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.*; import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.bootstrap.CallDepthThreadLocalMap; import datadog.trace.bootstrap.CallDepthThreadLocalMap;
import datadog.trace.context.TraceScope; import datadog.trace.context.TraceScope;
import io.opentracing.Scope; import io.opentracing.Scope;
import io.opentracing.util.GlobalTracer; import io.opentracing.util.GlobalTracer;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.*; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@ -98,7 +104,7 @@ public final class ExecutorInstrumentation extends Instrumenter.Default {
// Check for possible prefixes match only if not whitelisted already // Check for possible prefixes match only if not whitelisted already
if (!whitelisted) { if (!whitelisted) {
for (String name : WHITELISTED_EXECUTORS_PREFIXES) { for (final String name : WHITELISTED_EXECUTORS_PREFIXES) {
if (target.getName().startsWith(name)) { if (target.getName().startsWith(name)) {
whitelisted = true; whitelisted = true;
break; break;
@ -126,7 +132,7 @@ public final class ExecutorInstrumentation extends Instrumenter.Default {
@Override @Override
public Map<ElementMatcher, String> transformers() { public Map<ElementMatcher, String> transformers() {
Map<ElementMatcher, String> transformers = new HashMap<>(); final Map<ElementMatcher, String> transformers = new HashMap<>();
transformers.put( transformers.put(
named("execute").and(takesArgument(0, Runnable.class)), WrapRunnableAdvice.class.getName()); named("execute").and(takesArgument(0, Runnable.class)), WrapRunnableAdvice.class.getName());
transformers.put( transformers.put(
@ -141,7 +147,6 @@ public final class ExecutorInstrumentation extends Instrumenter.Default {
public static class WrapRunnableAdvice { public static class WrapRunnableAdvice {
@SuppressWarnings("unused")
@Advice.OnMethodEnter(suppress = Throwable.class) @Advice.OnMethodEnter(suppress = Throwable.class)
public static DatadogWrapper enterJobSubmit( public static DatadogWrapper enterJobSubmit(
@Advice.Argument(value = 0, readOnly = false) Runnable task) { @Advice.Argument(value = 0, readOnly = false) Runnable task) {
@ -153,7 +158,6 @@ public final class ExecutorInstrumentation extends Instrumenter.Default {
return null; return null;
} }
@SuppressWarnings("unused")
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void exitJobSubmit( public static void exitJobSubmit(
@Advice.Enter final DatadogWrapper wrapper, @Advice.Thrown final Throwable throwable) { @Advice.Enter final DatadogWrapper wrapper, @Advice.Thrown final Throwable throwable) {
@ -163,7 +167,6 @@ public final class ExecutorInstrumentation extends Instrumenter.Default {
public static class WrapCallableAdvice { public static class WrapCallableAdvice {
@SuppressWarnings("unused")
@Advice.OnMethodEnter(suppress = Throwable.class) @Advice.OnMethodEnter(suppress = Throwable.class)
public static DatadogWrapper enterJobSubmit( public static DatadogWrapper enterJobSubmit(
@Advice.Argument(value = 0, readOnly = false) Callable<?> task) { @Advice.Argument(value = 0, readOnly = false) Callable<?> task) {
@ -176,7 +179,6 @@ public final class ExecutorInstrumentation extends Instrumenter.Default {
return null; return null;
} }
@SuppressWarnings("unused")
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void exitJobSubmit( public static void exitJobSubmit(
@Advice.Enter final DatadogWrapper wrapper, @Advice.Thrown final Throwable throwable) { @Advice.Enter final DatadogWrapper wrapper, @Advice.Thrown final Throwable throwable) {
@ -186,7 +188,6 @@ public final class ExecutorInstrumentation extends Instrumenter.Default {
public static class WrapCallableCollectionAdvice { public static class WrapCallableCollectionAdvice {
@SuppressWarnings("unused")
@Advice.OnMethodEnter(suppress = Throwable.class) @Advice.OnMethodEnter(suppress = Throwable.class)
public static Collection<?> wrapJob( public static Collection<?> wrapJob(
@Advice.Argument(value = 0, readOnly = false) Collection<? extends Callable<?>> tasks) { @Advice.Argument(value = 0, readOnly = false) Collection<? extends Callable<?>> tasks) {
@ -196,7 +197,7 @@ public final class ExecutorInstrumentation extends Instrumenter.Default {
&& tasks != null && tasks != null
&& DatadogWrapper.isTopLevelCall()) { && DatadogWrapper.isTopLevelCall()) {
final Collection<Callable<?>> wrappedTasks = new ArrayList<>(tasks.size()); final Collection<Callable<?>> wrappedTasks = new ArrayList<>(tasks.size());
for (Callable<?> task : tasks) { for (final Callable<?> task : tasks) {
if (task != null && !(task instanceof CallableWrapper)) { if (task != null && !(task instanceof CallableWrapper)) {
wrappedTasks.add(new CallableWrapper<>(task, (TraceScope) scope)); wrappedTasks.add(new CallableWrapper<>(task, (TraceScope) scope));
} }
@ -207,7 +208,6 @@ public final class ExecutorInstrumentation extends Instrumenter.Default {
return null; return null;
} }
@SuppressWarnings("unused")
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void checkCancel( public static void checkCancel(
@Advice.Enter final Collection<?> wrappedJobs, @Advice.Thrown final Throwable throwable) { @Advice.Enter final Collection<?> wrappedJobs, @Advice.Thrown final Throwable throwable) {
@ -250,13 +250,11 @@ public final class ExecutorInstrumentation extends Instrumenter.Default {
* *
* @return true iff call is not nested * @return true iff call is not nested
*/ */
@SuppressWarnings("WeakerAccess")
public static boolean isTopLevelCall() { public static boolean isTopLevelCall() {
return CallDepthThreadLocalMap.incrementCallDepth(ExecutorService.class) <= 0; return CallDepthThreadLocalMap.incrementCallDepth(ExecutorService.class) <= 0;
} }
/** Reset nested calls to executor. */ /** Reset nested calls to executor. */
@SuppressWarnings("WeakerAccess")
public static void resetNestedCalls() { public static void resetNestedCalls() {
CallDepthThreadLocalMap.reset(ExecutorService.class); CallDepthThreadLocalMap.reset(ExecutorService.class);
} }
@ -265,8 +263,7 @@ public final class ExecutorInstrumentation extends Instrumenter.Default {
* @param task task object * @param task task object
* @return true iff given task object should be wrapped * @return true iff given task object should be wrapped
*/ */
@SuppressWarnings("WeakerAccess") public static boolean shouldWrapTask(final Object task) {
public static boolean shouldWrapTask(Object task) {
final Scope scope = GlobalTracer.get().scopeManager().active(); final Scope scope = GlobalTracer.get().scopeManager().active();
return (scope instanceof TraceScope return (scope instanceof TraceScope
&& ((TraceScope) scope).isAsyncPropagating() && ((TraceScope) scope).isAsyncPropagating()
@ -281,7 +278,6 @@ public final class ExecutorInstrumentation extends Instrumenter.Default {
* @param wrapper task wrapper * @param wrapper task wrapper
* @param throwable throwable that may have been thrown * @param throwable throwable that may have been thrown
*/ */
@SuppressWarnings("WeakerAccess")
public static void cleanUpOnMethodExit( public static void cleanUpOnMethodExit(
final DatadogWrapper wrapper, final Throwable throwable) { final DatadogWrapper wrapper, final Throwable throwable) {
if (null != wrapper) { if (null != wrapper) {
@ -356,7 +352,7 @@ public final class ExecutorInstrumentation extends Instrumenter.Default {
if (o instanceof DatadogWrapper) { if (o instanceof DatadogWrapper) {
return (DatadogWrapper) o; return (DatadogWrapper) o;
} }
} catch (IllegalArgumentException | IllegalAccessException e) { } catch (final IllegalArgumentException | IllegalAccessException e) {
} finally { } finally {
field.setAccessible(false); field.setAccessible(false);
} }

View File

@ -10,7 +10,12 @@ import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.instrumentation.java.concurrent.ExecutorInstrumentation.ConcurrentUtils; import datadog.trace.instrumentation.java.concurrent.ExecutorInstrumentation.ConcurrentUtils;
import datadog.trace.instrumentation.java.concurrent.ExecutorInstrumentation.DatadogWrapper; import datadog.trace.instrumentation.java.concurrent.ExecutorInstrumentation.DatadogWrapper;
import java.util.*; import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
@ -91,7 +96,7 @@ public final class FutureInstrumentation extends Instrumenter.Default {
@Override @Override
public Map<ElementMatcher, String> transformers() { public Map<ElementMatcher, String> transformers() {
Map<ElementMatcher, String> transformers = new HashMap<>(); final Map<ElementMatcher, String> transformers = new HashMap<>();
transformers.put( transformers.put(
named("cancel").and(returns(boolean.class)), CanceledFutureAdvice.class.getName()); named("cancel").and(returns(boolean.class)), CanceledFutureAdvice.class.getName());
return transformers; return transformers;

View File

@ -3,19 +3,20 @@ import datadog.trace.context.TraceScope
import io.opentracing.util.GlobalTracer import io.opentracing.util.GlobalTracer
import slick.jdbc.H2Profile.api._ import slick.jdbc.H2Profile.api._
import scala.concurrent.{Await, Future}
import scala.concurrent.duration.Duration import scala.concurrent.duration.Duration
import scala.concurrent.{Await, Future}
class SlickUtils { class SlickUtils {
import SlickUtils._ import SlickUtils._
val database = Database.forURL(Url, val database = Database.forURL(Url,
user=Username, user = Username,
driver="org.h2.Driver", driver = "org.h2.Driver",
keepAliveConnection=true, keepAliveConnection = true,
// Limit number of threads to hit Slick-specific case when we need to avoid re-wrapping // Limit number of threads to hit Slick-specific case when we need to avoid re-wrapping
// wrapped runnables. // wrapped runnables.
executor=AsyncExecutor("test", numThreads=1, queueSize=1000) executor = AsyncExecutor("test", numThreads = 1, queueSize = 1000)
) )
Await.result(database.run(sqlu"""CREATE ALIAS SLEEP FOR "java.lang.Thread.sleep(long)""""), Duration.Inf) Await.result(database.run(sqlu"""CREATE ALIAS SLEEP FOR "java.lang.Thread.sleep(long)""""), Duration.Inf)

View File

@ -14,7 +14,9 @@ import io.opentracing.tag.Tags;
import io.opentracing.util.GlobalTracer; import io.opentracing.util.GlobalTracer;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.*; import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import javax.ws.rs.HttpMethod; import javax.ws.rs.HttpMethod;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;

View File

@ -6,7 +6,7 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.returns; import static net.bytebuddy.matcher.ElementMatchers.returns;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.*; import datadog.trace.agent.tooling.Instrumenter;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.ClientBuilder;
@ -36,7 +36,7 @@ public final class JaxRsClientInstrumentation extends Instrumenter.Default {
@Override @Override
public Map<ElementMatcher, String> transformers() { public Map<ElementMatcher, String> transformers() {
Map<ElementMatcher, String> transformers = new HashMap<>(); final Map<ElementMatcher, String> transformers = new HashMap<>();
transformers.put( transformers.put(
named("build").and(returns(hasSuperType(named("javax.ws.rs.client.Client")))), named("build").and(returns(hasSuperType(named("javax.ws.rs.client.Client")))),
ClientBuilderAdvice.class.getName()); ClientBuilderAdvice.class.getName());

View File

@ -176,19 +176,19 @@ class JDBCInstrumentationTest extends AgentTestRunner {
connection.close() connection.close()
where: where:
driver | connection | username | query driver | connection | username | query
"h2" | new Driver().connect(jdbcUrls.get("h2"), null) | null | "SELECT 3" "h2" | new Driver().connect(jdbcUrls.get("h2"), null) | null | "SELECT 3"
"derby" | new EmbeddedDriver().connect(jdbcUrls.get("derby"), null)| "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" "derby" | new EmbeddedDriver().connect(jdbcUrls.get("derby"), null) | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1"
"hsqldb" | new JDBCDriver().connect(jdbcUrls.get("hsqldb"), null) | "SA" | "SELECT 3 FROM INFORMATION_SCHEMA.SYSTEM_USERS" "hsqldb" | new JDBCDriver().connect(jdbcUrls.get("hsqldb"), null) | "SA" | "SELECT 3 FROM INFORMATION_SCHEMA.SYSTEM_USERS"
"h2" | cpDatasources.get("tomcat").get("h2").getConnection() | null | "SELECT 3" "h2" | cpDatasources.get("tomcat").get("h2").getConnection() | null | "SELECT 3"
"derby" | cpDatasources.get("tomcat").get("derby").getConnection() | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" "derby" | cpDatasources.get("tomcat").get("derby").getConnection() | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1"
"hsqldb" | cpDatasources.get("tomcat").get("hsqldb").getConnection()| "SA" | "SELECT 3 FROM INFORMATION_SCHEMA.SYSTEM_USERS" "hsqldb" | cpDatasources.get("tomcat").get("hsqldb").getConnection() | "SA" | "SELECT 3 FROM INFORMATION_SCHEMA.SYSTEM_USERS"
"h2" | cpDatasources.get("hikari").get("h2").getConnection() | null | "SELECT 3" "h2" | cpDatasources.get("hikari").get("h2").getConnection() | null | "SELECT 3"
"derby" | cpDatasources.get("hikari").get("derby").getConnection() | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" "derby" | cpDatasources.get("hikari").get("derby").getConnection() | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1"
"hsqldb" | cpDatasources.get("hikari").get("hsqldb").getConnection()| "SA" | "SELECT 3 FROM INFORMATION_SCHEMA.SYSTEM_USERS" "hsqldb" | cpDatasources.get("hikari").get("hsqldb").getConnection() | "SA" | "SELECT 3 FROM INFORMATION_SCHEMA.SYSTEM_USERS"
"h2" | cpDatasources.get("c3p0").get("h2").getConnection() | null | "SELECT 3" "h2" | cpDatasources.get("c3p0").get("h2").getConnection() | null | "SELECT 3"
"derby" | cpDatasources.get("c3p0").get("derby").getConnection() | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" "derby" | cpDatasources.get("c3p0").get("derby").getConnection() | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1"
"hsqldb" | cpDatasources.get("c3p0").get("hsqldb").getConnection() | "SA" | "SELECT 3 FROM INFORMATION_SCHEMA.SYSTEM_USERS" "hsqldb" | cpDatasources.get("c3p0").get("hsqldb").getConnection() | "SA" | "SELECT 3 FROM INFORMATION_SCHEMA.SYSTEM_USERS"
} }
@Unroll @Unroll
@ -230,15 +230,15 @@ class JDBCInstrumentationTest extends AgentTestRunner {
connection.close() connection.close()
where: where:
driver | connection | username | query driver | connection | username | query
"h2" | new Driver().connect(jdbcUrls.get("h2"), null) | null | "SELECT 3" "h2" | new Driver().connect(jdbcUrls.get("h2"), null) | null | "SELECT 3"
"derby" | new EmbeddedDriver().connect(jdbcUrls.get("derby"), null)| "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" "derby" | new EmbeddedDriver().connect(jdbcUrls.get("derby"), null) | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1"
"h2" | cpDatasources.get("tomcat").get("h2").getConnection() | null | "SELECT 3" "h2" | cpDatasources.get("tomcat").get("h2").getConnection() | null | "SELECT 3"
"derby" | cpDatasources.get("tomcat").get("derby").getConnection() | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" "derby" | cpDatasources.get("tomcat").get("derby").getConnection() | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1"
"h2" | cpDatasources.get("hikari").get("h2").getConnection() | null | "SELECT 3" "h2" | cpDatasources.get("hikari").get("h2").getConnection() | null | "SELECT 3"
"derby" | cpDatasources.get("hikari").get("derby").getConnection() | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" "derby" | cpDatasources.get("hikari").get("derby").getConnection() | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1"
"h2" | cpDatasources.get("c3p0").get("h2").getConnection() | null | "SELECT 3" "h2" | cpDatasources.get("c3p0").get("h2").getConnection() | null | "SELECT 3"
"derby" | cpDatasources.get("c3p0").get("derby").getConnection() | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" "derby" | cpDatasources.get("c3p0").get("derby").getConnection() | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1"
} }
@Unroll @Unroll
@ -279,15 +279,15 @@ class JDBCInstrumentationTest extends AgentTestRunner {
connection.close() connection.close()
where: where:
driver | connection | username | query driver | connection | username | query
"h2" | new Driver().connect(jdbcUrls.get("h2"), null) | null | "SELECT 3" "h2" | new Driver().connect(jdbcUrls.get("h2"), null) | null | "SELECT 3"
"derby" | new EmbeddedDriver().connect(jdbcUrls.get("derby"), null)| "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" "derby" | new EmbeddedDriver().connect(jdbcUrls.get("derby"), null) | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1"
"h2" | cpDatasources.get("tomcat").get("h2").getConnection() | null | "SELECT 3" "h2" | cpDatasources.get("tomcat").get("h2").getConnection() | null | "SELECT 3"
"derby" | cpDatasources.get("tomcat").get("derby").getConnection() | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" "derby" | cpDatasources.get("tomcat").get("derby").getConnection() | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1"
"h2" | cpDatasources.get("hikari").get("h2").getConnection() | null | "SELECT 3" "h2" | cpDatasources.get("hikari").get("h2").getConnection() | null | "SELECT 3"
"derby" | cpDatasources.get("hikari").get("derby").getConnection() | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" "derby" | cpDatasources.get("hikari").get("derby").getConnection() | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1"
"h2" | cpDatasources.get("c3p0").get("h2").getConnection() | null | "SELECT 3" "h2" | cpDatasources.get("c3p0").get("h2").getConnection() | null | "SELECT 3"
"derby" | cpDatasources.get("c3p0").get("derby").getConnection() | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" "derby" | cpDatasources.get("c3p0").get("derby").getConnection() | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1"
} }
@Unroll @Unroll
@ -328,19 +328,19 @@ class JDBCInstrumentationTest extends AgentTestRunner {
connection.close() connection.close()
where: where:
driver | connection | username | query driver | connection | username | query
"h2" | new Driver().connect(jdbcUrls.get("h2"), null) | null | "CREATE TABLE S_H2 (id INTEGER not NULL, PRIMARY KEY ( id ))" "h2" | new Driver().connect(jdbcUrls.get("h2"), null) | null | "CREATE TABLE S_H2 (id INTEGER not NULL, PRIMARY KEY ( id ))"
"derby" | new EmbeddedDriver().connect(jdbcUrls.get("derby"), null)| "APP" | "CREATE TABLE S_DERBY (id INTEGER not NULL, PRIMARY KEY ( id ))" "derby" | new EmbeddedDriver().connect(jdbcUrls.get("derby"), null) | "APP" | "CREATE TABLE S_DERBY (id INTEGER not NULL, PRIMARY KEY ( id ))"
"hsqldb" | new JDBCDriver().connect(jdbcUrls.get("hsqldb"), null) | "SA" | "CREATE TABLE PUBLIC.S_HSQLDB (id INTEGER not NULL, PRIMARY KEY ( id ))" "hsqldb" | new JDBCDriver().connect(jdbcUrls.get("hsqldb"), null) | "SA" | "CREATE TABLE PUBLIC.S_HSQLDB (id INTEGER not NULL, PRIMARY KEY ( id ))"
"h2" | cpDatasources.get("tomcat").get("h2").getConnection() | null | "CREATE TABLE S_H2_TOMCAT (id INTEGER not NULL, PRIMARY KEY ( id ))" "h2" | cpDatasources.get("tomcat").get("h2").getConnection() | null | "CREATE TABLE S_H2_TOMCAT (id INTEGER not NULL, PRIMARY KEY ( id ))"
"derby" | cpDatasources.get("tomcat").get("derby").getConnection() | "APP" | "CREATE TABLE S_DERBY_TOMCAT (id INTEGER not NULL, PRIMARY KEY ( id ))" "derby" | cpDatasources.get("tomcat").get("derby").getConnection() | "APP" | "CREATE TABLE S_DERBY_TOMCAT (id INTEGER not NULL, PRIMARY KEY ( id ))"
"hsqldb" | cpDatasources.get("tomcat").get("hsqldb").getConnection()| "SA" | "CREATE TABLE PUBLIC.S_HSQLDB_TOMCAT (id INTEGER not NULL, PRIMARY KEY ( id ))" "hsqldb" | cpDatasources.get("tomcat").get("hsqldb").getConnection() | "SA" | "CREATE TABLE PUBLIC.S_HSQLDB_TOMCAT (id INTEGER not NULL, PRIMARY KEY ( id ))"
"h2" | cpDatasources.get("hikari").get("h2").getConnection() | null | "CREATE TABLE S_H2_HIKARI (id INTEGER not NULL, PRIMARY KEY ( id ))" "h2" | cpDatasources.get("hikari").get("h2").getConnection() | null | "CREATE TABLE S_H2_HIKARI (id INTEGER not NULL, PRIMARY KEY ( id ))"
"derby" | cpDatasources.get("hikari").get("derby").getConnection() | "APP" | "CREATE TABLE S_DERBY_HIKARI (id INTEGER not NULL, PRIMARY KEY ( id ))" "derby" | cpDatasources.get("hikari").get("derby").getConnection() | "APP" | "CREATE TABLE S_DERBY_HIKARI (id INTEGER not NULL, PRIMARY KEY ( id ))"
"hsqldb" | cpDatasources.get("hikari").get("hsqldb").getConnection()| "SA" | "CREATE TABLE PUBLIC.S_HSQLDB_HIKARI (id INTEGER not NULL, PRIMARY KEY ( id ))" "hsqldb" | cpDatasources.get("hikari").get("hsqldb").getConnection() | "SA" | "CREATE TABLE PUBLIC.S_HSQLDB_HIKARI (id INTEGER not NULL, PRIMARY KEY ( id ))"
"h2" | cpDatasources.get("c3p0").get("h2").getConnection() | null | "CREATE TABLE S_H2_C3P0 (id INTEGER not NULL, PRIMARY KEY ( id ))" "h2" | cpDatasources.get("c3p0").get("h2").getConnection() | null | "CREATE TABLE S_H2_C3P0 (id INTEGER not NULL, PRIMARY KEY ( id ))"
"derby" | cpDatasources.get("c3p0").get("derby").getConnection() | "APP" | "CREATE TABLE S_DERBY_C3P0 (id INTEGER not NULL, PRIMARY KEY ( id ))" "derby" | cpDatasources.get("c3p0").get("derby").getConnection() | "APP" | "CREATE TABLE S_DERBY_C3P0 (id INTEGER not NULL, PRIMARY KEY ( id ))"
"hsqldb" | cpDatasources.get("c3p0").get("hsqldb").getConnection() | "SA" | "CREATE TABLE PUBLIC.S_HSQLDB_C3P0 (id INTEGER not NULL, PRIMARY KEY ( id ))" "hsqldb" | cpDatasources.get("c3p0").get("hsqldb").getConnection() | "SA" | "CREATE TABLE PUBLIC.S_HSQLDB_C3P0 (id INTEGER not NULL, PRIMARY KEY ( id ))"
} }
@Unroll @Unroll
@ -380,15 +380,15 @@ class JDBCInstrumentationTest extends AgentTestRunner {
connection.close() connection.close()
where: where:
driver | connection | username | query driver | connection | username | query
"h2" | new Driver().connect(jdbcUrls.get("h2"), null) | null | "CREATE TABLE PS_H2 (id INTEGER not NULL, PRIMARY KEY ( id ))" "h2" | new Driver().connect(jdbcUrls.get("h2"), null) | null | "CREATE TABLE PS_H2 (id INTEGER not NULL, PRIMARY KEY ( id ))"
"derby" | new EmbeddedDriver().connect(jdbcUrls.get("derby"), null)| "APP" | "CREATE TABLE PS_DERBY (id INTEGER not NULL, PRIMARY KEY ( id ))" "derby" | new EmbeddedDriver().connect(jdbcUrls.get("derby"), null) | "APP" | "CREATE TABLE PS_DERBY (id INTEGER not NULL, PRIMARY KEY ( id ))"
"h2" | cpDatasources.get("tomcat").get("h2").getConnection() | null | "CREATE TABLE PS_H2_TOMCAT (id INTEGER not NULL, PRIMARY KEY ( id ))" "h2" | cpDatasources.get("tomcat").get("h2").getConnection() | null | "CREATE TABLE PS_H2_TOMCAT (id INTEGER not NULL, PRIMARY KEY ( id ))"
"derby" | cpDatasources.get("tomcat").get("derby").getConnection() | "APP" | "CREATE TABLE PS_DERBY_TOMCAT (id INTEGER not NULL, PRIMARY KEY ( id ))" "derby" | cpDatasources.get("tomcat").get("derby").getConnection() | "APP" | "CREATE TABLE PS_DERBY_TOMCAT (id INTEGER not NULL, PRIMARY KEY ( id ))"
"h2" | cpDatasources.get("hikari").get("h2").getConnection() | null | "CREATE TABLE PS_H2_HIKARI (id INTEGER not NULL, PRIMARY KEY ( id ))" "h2" | cpDatasources.get("hikari").get("h2").getConnection() | null | "CREATE TABLE PS_H2_HIKARI (id INTEGER not NULL, PRIMARY KEY ( id ))"
"derby" | cpDatasources.get("hikari").get("derby").getConnection() | "APP" | "CREATE TABLE PS_DERBY_HIKARI (id INTEGER not NULL, PRIMARY KEY ( id ))" "derby" | cpDatasources.get("hikari").get("derby").getConnection() | "APP" | "CREATE TABLE PS_DERBY_HIKARI (id INTEGER not NULL, PRIMARY KEY ( id ))"
"h2" | cpDatasources.get("c3p0").get("h2").getConnection() | null | "CREATE TABLE PS_H2_C3P0 (id INTEGER not NULL, PRIMARY KEY ( id ))" "h2" | cpDatasources.get("c3p0").get("h2").getConnection() | null | "CREATE TABLE PS_H2_C3P0 (id INTEGER not NULL, PRIMARY KEY ( id ))"
"derby" | cpDatasources.get("c3p0").get("derby").getConnection() | "APP" | "CREATE TABLE PS_DERBY_C3P0 (id INTEGER not NULL, PRIMARY KEY ( id ))" "derby" | cpDatasources.get("c3p0").get("derby").getConnection() | "APP" | "CREATE TABLE PS_DERBY_C3P0 (id INTEGER not NULL, PRIMARY KEY ( id ))"
} }
@ -454,11 +454,11 @@ class JDBCInstrumentationTest extends AgentTestRunner {
} }
where: where:
prepareStatement | driver | driverClass | url | username | query prepareStatement | driver | driverClass | url | username | query
true | "h2" | new Driver() | "jdbc:h2:mem:" + dbName | null | "SELECT 3;" true | "h2" | new Driver() | "jdbc:h2:mem:" + dbName | null | "SELECT 3;"
true | "derby" | new EmbeddedDriver() | "jdbc:derby:memory:" + dbName + ";create=true" | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" true | "derby" | new EmbeddedDriver() | "jdbc:derby:memory:" + dbName + ";create=true" | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1"
false | "h2" | new Driver() | "jdbc:h2:mem:" + dbName | null | "SELECT 3;" false | "h2" | new Driver() | "jdbc:h2:mem:" + dbName | null | "SELECT 3;"
false | "derby" | new EmbeddedDriver() | "jdbc:derby:memory:" + dbName + ";create=true" | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1" false | "derby" | new EmbeddedDriver() | "jdbc:derby:memory:" + dbName + ";create=true" | "APP" | "SELECT 3 FROM SYSIBM.SYSDUMMY1"
} }
@Unroll @Unroll

View File

@ -11,7 +11,7 @@ import static net.bytebuddy.matcher.ElementMatchers.not;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments; import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.*; 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 datadog.trace.instrumentation.jms.util.MessagePropertyTextMap;
@ -23,7 +23,9 @@ import io.opentracing.propagation.Format;
import io.opentracing.tag.Tags; import io.opentracing.tag.Tags;
import io.opentracing.util.GlobalTracer; import io.opentracing.util.GlobalTracer;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.*; import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.jms.Message; import javax.jms.Message;
import javax.jms.MessageConsumer; import javax.jms.MessageConsumer;

View File

@ -1,7 +1,12 @@
package datadog.trace.instrumentation.jsp; package datadog.trace.instrumentation.jsp;
import static io.opentracing.log.Fields.ERROR_OBJECT; import static io.opentracing.log.Fields.ERROR_OBJECT;
import static net.bytebuddy.matcher.ElementMatchers.*; import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
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 com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.Instrumenter;

View File

@ -2,7 +2,9 @@ package datadog.trace.instrumentation.jsp;
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses; import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
import static io.opentracing.log.Fields.ERROR_OBJECT; import static io.opentracing.log.Fields.ERROR_OBJECT;
import static net.bytebuddy.matcher.ElementMatchers.*; import static net.bytebuddy.matcher.ElementMatchers.isPublic;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.Instrumenter;

View File

@ -144,10 +144,10 @@ class JSPInstrumentationBasicTests extends AgentTestRunner {
res.close() res.close()
where: where:
test | jspFileName | jspClassName | jspClassNamePrefix test | jspFileName | jspClassName | jspClassNamePrefix
"no java jsp" | "nojava.jsp" | "nojava_jsp" | "" "no java jsp" | "nojava.jsp" | "nojava_jsp" | ""
"basic loop jsp"|"common/loop.jsp" | "loop_jsp" | "common." "basic loop jsp" | "common/loop.jsp" | "loop_jsp" | "common."
"invalid HTML markup"|"invalidMarkup.jsp" | "invalidMarkup_jsp" | "" "invalid HTML markup" | "invalidMarkup.jsp" | "invalidMarkup_jsp" | ""
} }
def "non-erroneous GET with query string"() { def "non-erroneous GET with query string"() {
@ -368,10 +368,10 @@ class JSPInstrumentationBasicTests extends AgentTestRunner {
res.close() res.close()
where: where:
test | jspFileName | jspClassName | exceptionClass | errorMessage test | jspFileName | jspClassName | exceptionClass | errorMessage
"java runtime error" | "runtimeError.jsp" | "runtimeError_jsp" | ArithmeticException | String "java runtime error" | "runtimeError.jsp" | "runtimeError_jsp" | ArithmeticException | String
"invalid write" | "invalidWrite.jsp" | "invalidWrite_jsp" | StringIndexOutOfBoundsException | String "invalid write" | "invalidWrite.jsp" | "invalidWrite_jsp" | StringIndexOutOfBoundsException | String
"missing query gives null" | "getQuery.jsp" | "getQuery_jsp" | NullPointerException | null "missing query gives null" | "getQuery.jsp" | "getQuery_jsp" | NullPointerException | null
} }
def "non-erroneous include plain HTML GET"() { def "non-erroneous include plain HTML GET"() {
@ -638,8 +638,8 @@ class JSPInstrumentationBasicTests extends AgentTestRunner {
res.close() res.close()
where: where:
test | jspFileName | jspClassName | jspClassNamePrefix test | jspFileName | jspClassName | jspClassNamePrefix
"normal" | "compileError.jsp" | "compileError_jsp" | "" "normal" | "compileError.jsp" | "compileError_jsp" | ""
"forward"|"forwards/forwardWithCompileError.jsp" | "forwardWithCompileError_jsp" | "forwards." "forward" | "forwards/forwardWithCompileError.jsp" | "forwardWithCompileError_jsp" | "forwards."
} }
} }

View File

@ -4,7 +4,9 @@ import datadog.trace.agent.test.OkHttpUtils
import datadog.trace.agent.test.TestUtils import datadog.trace.agent.test.TestUtils
import datadog.trace.api.DDSpanTypes import datadog.trace.api.DDSpanTypes
import io.netty.handler.codec.http.HttpResponseStatus import io.netty.handler.codec.http.HttpResponseStatus
import okhttp3.* import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import org.apache.catalina.Context import org.apache.catalina.Context
import org.apache.catalina.startup.Tomcat import org.apache.catalina.startup.Tomcat
import org.apache.jasper.JasperException import org.apache.jasper.JasperException
@ -174,9 +176,9 @@ class JSPInstrumentationForwardTests extends AgentTestRunner {
res.close() res.close()
where: where:
forwardTo | forwardFromFileName | forwardDestFileName | jspForwardFromClassName | jspForwardFromClassPrefix | jspForwardDestClassName | jspForwardDestClassPrefix forwardTo | forwardFromFileName | forwardDestFileName | jspForwardFromClassName | jspForwardFromClassPrefix | jspForwardDestClassName | jspForwardDestClassPrefix
"no java jsp" | "forwards/forwardToNoJavaJsp.jsp" | "nojava.jsp" | "forwardToNoJavaJsp_jsp" | "forwards." | "nojava_jsp" | "" "no java jsp" | "forwards/forwardToNoJavaJsp.jsp" | "nojava.jsp" | "forwardToNoJavaJsp_jsp" | "forwards." | "nojava_jsp" | ""
"normal java jsp" | "forwards/forwardToSimpleJava.jsp" | "common/loop.jsp" | "forwardToSimpleJava_jsp" | "forwards." | "loop_jsp" | "common." "normal java jsp" | "forwards/forwardToSimpleJava.jsp" | "common/loop.jsp" | "forwardToSimpleJava_jsp" | "forwards." | "loop_jsp" | "common."
} }
def "non-erroneous GET forward to plain HTML"() { def "non-erroneous GET forward to plain HTML"() {

View File

@ -5,7 +5,7 @@ versionScan {
module = "kafka-streams" module = "kafka-streams"
versions = "[0.11.0.0,)" versions = "[0.11.0.0,)"
verifyPresent = [ verifyPresent = [
'org.apache.kafka.streams.state.internals.OrderedBytes' : null 'org.apache.kafka.streams.state.internals.OrderedBytes': null
] ]
} }

View File

@ -1,7 +1,9 @@
package datadog.trace.instrumentation.lettuce; package datadog.trace.instrumentation.lettuce;
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses; import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
import static net.bytebuddy.matcher.ElementMatchers.*; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.Instrumenter;
@ -38,7 +40,7 @@ public class LettuceAsyncCommandsInstrumentation extends Instrumenter.Default {
@Override @Override
public Map<ElementMatcher, String> transformers() { public Map<ElementMatcher, String> transformers() {
Map<ElementMatcher, String> transformers = new HashMap<>(); final Map<ElementMatcher, String> transformers = new HashMap<>();
transformers.put( transformers.put(
isMethod() isMethod()
.and(named("dispatch")) .and(named("dispatch"))

View File

@ -1,7 +1,13 @@
package datadog.trace.instrumentation.lettuce; package datadog.trace.instrumentation.lettuce;
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses; import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
import static net.bytebuddy.matcher.ElementMatchers.*; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.isPrivate;
import static net.bytebuddy.matcher.ElementMatchers.nameEndsWith;
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.returns;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.Instrumenter;
@ -42,7 +48,7 @@ public final class LettuceClientInstrumentation extends Instrumenter.Default {
@Override @Override
public Map<ElementMatcher, String> transformers() { public Map<ElementMatcher, String> transformers() {
Map<ElementMatcher, String> transformers = new HashMap<>(); final Map<ElementMatcher, String> transformers = new HashMap<>();
transformers.put( transformers.put(
isMethod() isMethod()
.and(isPrivate()) .and(isPrivate())

View File

@ -1,7 +1,12 @@
package datadog.trace.instrumentation.lettuce; package datadog.trace.instrumentation.lettuce;
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses; import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
import static net.bytebuddy.matcher.ElementMatchers.*; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.nameEndsWith;
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.returns;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.Instrumenter;
@ -43,7 +48,7 @@ public class LettuceReactiveCommandsInstrumentation extends Instrumenter.Default
@Override @Override
public Map<ElementMatcher, String> transformers() { public Map<ElementMatcher, String> transformers() {
Map<ElementMatcher, String> transformers = new HashMap<>(); final Map<ElementMatcher, String> transformers = new HashMap<>();
transformers.put( transformers.put(
isMethod() isMethod()
.and(named("createMono")) .and(named("createMono"))

View File

@ -1,7 +1,9 @@
package datadog.trace.instrumentation.lettuce; package datadog.trace.instrumentation.lettuce;
import io.lettuce.core.protocol.RedisCommand; import io.lettuce.core.protocol.RedisCommand;
import java.util.*; import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class LettuceInstrumentationUtil { public class LettuceInstrumentationUtil {
@ -30,7 +32,7 @@ public class LettuceInstrumentationUtil {
* @param commandName a redis command, without any prefixes * @param commandName a redis command, without any prefixes
* @return true if finish the span early (the command will not have a return value) * @return true if finish the span early (the command will not have a return value)
*/ */
public static boolean doFinishSpanEarly(String commandName) { public static boolean doFinishSpanEarly(final String commandName) {
return nonInstrumentingCommands.contains(commandName); return nonInstrumentingCommands.contains(commandName);
} }
@ -51,7 +53,7 @@ public class LettuceInstrumentationUtil {
* @return the redis command with a prefix if it is a command that will crash the trace agent, * @return the redis command with a prefix if it is a command that will crash the trace agent,
* otherwise, the original command is returned. * otherwise, the original command is returned.
*/ */
public static String getCommandResourceName(String actualCommandName) { public static String getCommandResourceName(final String actualCommandName) {
if (agentCrashingCommands.contains(actualCommandName)) { if (agentCrashingCommands.contains(actualCommandName)) {
return AGENT_CRASHING_COMMAND_PREFIX + actualCommandName; return AGENT_CRASHING_COMMAND_PREFIX + actualCommandName;
} }
@ -64,7 +66,7 @@ public class LettuceInstrumentationUtil {
* @param command the lettuce RedisCommand object * @param command the lettuce RedisCommand object
* @return the redis command as a string * @return the redis command as a string
*/ */
public static String getCommandName(RedisCommand command) { public static String getCommandName(final RedisCommand command) {
String commandName = "Redis Command"; String commandName = "Redis Command";
if (command != null) { if (command != null) {
/* /*

View File

@ -50,9 +50,9 @@ class LettuceAsyncClientTest extends AgentTestRunner {
@Shared @Shared
Map<String, String> testHashMap = [ Map<String, String> testHashMap = [
firstname: "John", firstname: "John",
lastname: "Doe", lastname : "Doe",
age: "53" age : "53"
] ]
RedisClient redisClient RedisClient redisClient
@ -254,7 +254,7 @@ class LettuceAsyncClientTest extends AgentTestRunner {
BiFunction<String, Throwable, String> firstStage = new BiFunction<String, Throwable, String>() { BiFunction<String, Throwable, String> firstStage = new BiFunction<String, Throwable, String>() {
@Override @Override
String apply(String res, Throwable throwable) { String apply(String res, Throwable throwable) {
conds.evaluate{ conds.evaluate {
assert res == null assert res == null
assert throwable == null assert throwable == null
} }
@ -264,7 +264,7 @@ class LettuceAsyncClientTest extends AgentTestRunner {
Function<String, Object> secondStage = new Function<String, Object>() { Function<String, Object> secondStage = new Function<String, Object>() {
@Override @Override
Object apply(String input) { Object apply(String input) {
conds.evaluate{ conds.evaluate {
assert input == successStr assert input == successStr
} }
return null return null
@ -304,7 +304,7 @@ class LettuceAsyncClientTest extends AgentTestRunner {
BiConsumer<String, Throwable> biConsumer = new BiConsumer<String, Throwable>() { BiConsumer<String, Throwable> biConsumer = new BiConsumer<String, Throwable>() {
@Override @Override
void accept(String keyRetrieved, Throwable throwable) { void accept(String keyRetrieved, Throwable throwable) {
conds.evaluate{ conds.evaluate {
assert keyRetrieved != null assert keyRetrieved != null
} }
} }
@ -419,7 +419,7 @@ class LettuceAsyncClientTest extends AgentTestRunner {
def conds = new AsyncConditions() def conds = new AsyncConditions()
RedisFuture redisFuture = asyncCommands.del("key1", "key2") RedisFuture redisFuture = asyncCommands.del("key1", "key2")
boolean completedExceptionally = ((AsyncCommand) redisFuture).completeExceptionally(new IllegalStateException("TestException")) boolean completedExceptionally = ((AsyncCommand) redisFuture).completeExceptionally(new IllegalStateException("TestException"))
redisFuture.exceptionally ({ redisFuture.exceptionally({
throwable -> throwable ->
conds.evaluate { conds.evaluate {
assert throwable != null assert throwable != null
@ -466,10 +466,11 @@ class LettuceAsyncClientTest extends AgentTestRunner {
def conds = new AsyncConditions() def conds = new AsyncConditions()
RedisFuture redisFuture = asyncCommands.sadd("SKEY", "1", "2") RedisFuture redisFuture = asyncCommands.sadd("SKEY", "1", "2")
redisFuture.whenCompleteAsync({ redisFuture.whenCompleteAsync({
res, throwable -> conds.evaluate { res, throwable ->
assert throwable != null conds.evaluate {
assert throwable instanceof CancellationException assert throwable != null
} assert throwable instanceof CancellationException
}
}) })
when: when:

View File

@ -1,6 +1,7 @@
import datadog.trace.agent.test.AgentTestRunner import datadog.trace.agent.test.AgentTestRunner
import datadog.trace.agent.test.TestUtils import datadog.trace.agent.test.TestUtils
import io.lettuce.core.* import io.lettuce.core.ClientOptions
import io.lettuce.core.RedisClient
import io.lettuce.core.api.StatefulConnection import io.lettuce.core.api.StatefulConnection
import io.lettuce.core.api.reactive.RedisReactiveCommands import io.lettuce.core.api.reactive.RedisReactiveCommands
import io.lettuce.core.api.sync.RedisCommands import io.lettuce.core.api.sync.RedisCommands
@ -36,9 +37,9 @@ class LettuceReactiveClientTest extends AgentTestRunner {
embeddedDbUri = "redis://" + dbAddr embeddedDbUri = "redis://" + dbAddr
redisServer = RedisServer.builder() redisServer = RedisServer.builder()
// bind to localhost to avoid firewall popup // bind to localhost to avoid firewall popup
.setting("bind " + HOST) .setting("bind " + HOST)
// set max memory to avoid problems in CI // set max memory to avoid problems in CI
.setting("maxmemory 128M") .setting("maxmemory 128M")
.port(port).build() .port(port).build()
} }
@ -109,7 +110,7 @@ class LettuceReactiveClientTest extends AgentTestRunner {
def conds = new AsyncConditions() def conds = new AsyncConditions()
when: when:
reactiveCommands.get("TESTKEY").subscribe { res -> conds.evaluate { assert res == "TESTVAL"} } reactiveCommands.get("TESTKEY").subscribe { res -> conds.evaluate { assert res == "TESTVAL" } }
then: then:
conds.await() conds.await()
@ -143,9 +144,10 @@ class LettuceReactiveClientTest extends AgentTestRunner {
when: when:
reactiveCommands.get("NON_EXISTENT_KEY").defaultIfEmpty(defaultVal).subscribe { reactiveCommands.get("NON_EXISTENT_KEY").defaultIfEmpty(defaultVal).subscribe {
res -> conds.evaluate { res ->
assert res == defaultVal conds.evaluate {
} assert res == defaultVal
}
} }
then: then:
@ -178,9 +180,10 @@ class LettuceReactiveClientTest extends AgentTestRunner {
when: when:
reactiveCommands.randomkey().subscribe { reactiveCommands.randomkey().subscribe {
res -> conds.evaluate { res ->
assert res == "TESTKEY" conds.evaluate {
} assert res == "TESTKEY"
}
} }
then: then:

View File

@ -37,9 +37,9 @@ class LettuceSyncClientTest extends AgentTestRunner {
@Shared @Shared
Map<String, String> testHashMap = [ Map<String, String> testHashMap = [
firstname: "John", firstname: "John",
lastname: "Doe", lastname : "Doe",
age: "53" age : "53"
] ]
RedisClient redisClient RedisClient redisClient
@ -55,9 +55,9 @@ class LettuceSyncClientTest extends AgentTestRunner {
embeddedDbUri = "redis://" + dbAddr embeddedDbUri = "redis://" + dbAddr
redisServer = RedisServer.builder() redisServer = RedisServer.builder()
// bind to localhost to avoid firewall popup // bind to localhost to avoid firewall popup
.setting("bind " + HOST) .setting("bind " + HOST)
// set max memory to avoid problems in CI // set max memory to avoid problems in CI
.setting("maxmemory 128M") .setting("maxmemory 128M")
.port(port).build() .port(port).build()
} }

View File

@ -6,7 +6,7 @@ versionScan {
scanMethods = true scanMethods = true
versions = "[3.3,)" versions = "[3.3,)"
verifyPresent = [ verifyPresent = [
'com.mongodb.async.client.MongoClientSettings$Builder': 'addCommandListener' 'com.mongodb.async.client.MongoClientSettings$Builder': 'addCommandListener'
] ]
} }

View File

@ -28,7 +28,7 @@ class Play26Test extends AgentTestRunner {
testServer.stop() testServer.stop()
} }
def "request traces" () { def "request traces"() {
setup: setup:
OkHttpClient client = new OkHttpClient.Builder().build() OkHttpClient client = new OkHttpClient.Builder().build()
def request = new Request.Builder() def request = new Request.Builder()
@ -83,7 +83,7 @@ class Play26Test extends AgentTestRunner {
} }
} }
def "5xx errors trace" () { def "5xx errors trace"() {
setup: setup:
OkHttpClient client = new OkHttpClient.Builder().build() OkHttpClient client = new OkHttpClient.Builder().build()
def request = new Request.Builder() def request = new Request.Builder()
@ -132,7 +132,7 @@ class Play26Test extends AgentTestRunner {
} }
} }
def "error thrown in request" () { def "error thrown in request"() {
setup: setup:
OkHttpClient client = new OkHttpClient.Builder().build() OkHttpClient client = new OkHttpClient.Builder().build()
def request = new Request.Builder() def request = new Request.Builder()
@ -185,7 +185,7 @@ class Play26Test extends AgentTestRunner {
} }
} }
def "4xx errors trace" () { def "4xx errors trace"() {
setup: setup:
OkHttpClient client = new OkHttpClient.Builder().build() OkHttpClient client = new OkHttpClient.Builder().build()
def request = new Request.Builder() def request = new Request.Builder()

View File

@ -1,21 +1,19 @@
import play.api.mvc.Action
import play.api.routing.{HandlerDef, Router}
import play.api.mvc._
import play.api.routing.sird._
import java.lang.reflect.Field import java.lang.reflect.Field
import datadog.trace.api.Trace import datadog.trace.api.Trace
import play.api.libs.typedmap.TypedKey
import play.api.mvc.request.RequestAttrKey import play.api.mvc.request.RequestAttrKey
import play.api.mvc.{Action, _}
import play.api.routing.sird._
import play.api.routing.{HandlerDef, Router}
import scala.concurrent.{Await, Future}
import scala.concurrent.duration._ import scala.concurrent.duration._
import scala.concurrent.{Await, Future}
object Play26TestUtils { object Play26TestUtils {
def buildTestApp(): play.Application = { def buildTestApp(): play.Application = {
// build play.api.Application with desired setting and pass into play.Application for testing // build play.api.Application with desired setting and pass into play.Application for testing
val apiApp :play.api.Application = new play.api.inject.guice.GuiceApplicationBuilder() val apiApp: play.api.Application = new play.api.inject.guice.GuiceApplicationBuilder()
.requireAtInjectOnConstructors(true) .requireAtInjectOnConstructors(true)
.router( .router(
Router.from { Router.from {

View File

@ -3,11 +3,14 @@ package datadog.trace.instrumentation.play;
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClassWithMethod; import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClassWithMethod;
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses; import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
import static io.opentracing.log.Fields.ERROR_OBJECT; import static io.opentracing.log.Fields.ERROR_OBJECT;
import static net.bytebuddy.matcher.ElementMatchers.*; import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.returns;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import akka.japi.JavaPartialFunction; import akka.japi.JavaPartialFunction;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.*; 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;
@ -18,7 +21,10 @@ import io.opentracing.propagation.Format;
import io.opentracing.propagation.TextMap; import io.opentracing.propagation.TextMap;
import io.opentracing.tag.Tags; import io.opentracing.tag.Tags;
import io.opentracing.util.GlobalTracer; import io.opentracing.util.GlobalTracer;
import java.util.*; import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
@ -66,7 +72,7 @@ public final class PlayInstrumentation extends Instrumenter.Default {
@Override @Override
public Map<ElementMatcher, String> transformers() { public Map<ElementMatcher, String> transformers() {
Map<ElementMatcher, String> transformers = new HashMap<>(); final Map<ElementMatcher, String> transformers = new HashMap<>();
transformers.put( transformers.put(
named("apply") named("apply")
.and(takesArgument(0, named("play.api.mvc.Request"))) .and(takesArgument(0, named("play.api.mvc.Request")))
@ -149,7 +155,7 @@ public final class PlayInstrumentation extends Instrumenter.Default {
public static class PlayHeaders implements TextMap { public static class PlayHeaders implements TextMap {
private final Request request; private final Request request;
public PlayHeaders(Request request) { public PlayHeaders(final Request request) {
this.request = request; this.request = request;
} }
@ -166,7 +172,7 @@ public final class PlayInstrumentation extends Instrumenter.Default {
} }
@Override @Override
public void put(String s, String s1) { public void put(final String s, final String s1) {
throw new IllegalStateException("play headers can only be extracted"); throw new IllegalStateException("play headers can only be extracted");
} }
} }
@ -174,18 +180,18 @@ public final class PlayInstrumentation extends Instrumenter.Default {
public static class RequestError extends JavaPartialFunction<Throwable, Object> { public static class RequestError extends JavaPartialFunction<Throwable, Object> {
private final Span span; private final Span span;
public RequestError(Span span) { public RequestError(final Span span) {
this.span = span; this.span = span;
} }
@Override @Override
public Object apply(Throwable t, boolean isCheck) throws Exception { public Object apply(final Throwable t, final boolean isCheck) throws Exception {
try { try {
if (GlobalTracer.get().scopeManager().active() instanceof TraceScope) { if (GlobalTracer.get().scopeManager().active() instanceof TraceScope) {
((TraceScope) GlobalTracer.get().scopeManager().active()).setAsyncPropagation(false); ((TraceScope) GlobalTracer.get().scopeManager().active()).setAsyncPropagation(false);
} }
onError(span, t); onError(span, t);
} catch (Throwable t2) { } catch (final Throwable t2) {
LoggerFactory.getLogger(RequestCallback.class).debug("error in play instrumentation", t); LoggerFactory.getLogger(RequestCallback.class).debug("error in play instrumentation", t);
} }
span.finish(); span.finish();
@ -203,18 +209,18 @@ public final class PlayInstrumentation extends Instrumenter.Default {
public static class RequestCallback extends scala.runtime.AbstractFunction1<Result, Result> { public static class RequestCallback extends scala.runtime.AbstractFunction1<Result, Result> {
private final Span span; private final Span span;
public RequestCallback(Span span) { public RequestCallback(final Span span) {
this.span = span; this.span = span;
} }
@Override @Override
public Result apply(Result result) { public Result apply(final Result result) {
if (GlobalTracer.get().scopeManager().active() instanceof TraceScope) { if (GlobalTracer.get().scopeManager().active() instanceof TraceScope) {
((TraceScope) GlobalTracer.get().scopeManager().active()).setAsyncPropagation(false); ((TraceScope) GlobalTracer.get().scopeManager().active()).setAsyncPropagation(false);
} }
try { try {
Tags.HTTP_STATUS.set(span, result.header().status()); Tags.HTTP_STATUS.set(span, result.header().status());
} catch (Throwable t) { } catch (final Throwable t) {
log.debug("error in play instrumentation", t); log.debug("error in play instrumentation", t);
} }
span.finish(); span.finish();

View File

@ -23,7 +23,7 @@ class Play24Test extends AgentTestRunner {
testServer.stop() testServer.stop()
} }
def "request traces" () { def "request traces"() {
setup: setup:
OkHttpClient client = new OkHttpClient.Builder().build() OkHttpClient client = new OkHttpClient.Builder().build()
def request = new Request.Builder() def request = new Request.Builder()
@ -59,7 +59,7 @@ class Play24Test extends AgentTestRunner {
root.context().tags["component"] == "play-action" root.context().tags["component"] == "play-action"
} }
def "5xx errors trace" () { def "5xx errors trace"() {
setup: setup:
OkHttpClient client = new OkHttpClient.Builder().build() OkHttpClient client = new OkHttpClient.Builder().build()
def request = new Request.Builder() def request = new Request.Builder()
@ -86,7 +86,7 @@ class Play24Test extends AgentTestRunner {
root.context().tags["component"] == "play-action" root.context().tags["component"] == "play-action"
} }
def "error thrown in request" () { def "error thrown in request"() {
setup: setup:
OkHttpClient client = new OkHttpClient.Builder().build() OkHttpClient client = new OkHttpClient.Builder().build()
def request = new Request.Builder() def request = new Request.Builder()
@ -116,7 +116,7 @@ class Play24Test extends AgentTestRunner {
root.context().tags["component"] == "play-action" root.context().tags["component"] == "play-action"
} }
def "4xx errors trace" () { def "4xx errors trace"() {
setup: setup:
OkHttpClient client = new OkHttpClient.Builder().build() OkHttpClient client = new OkHttpClient.Builder().build()
def request = new Request.Builder() def request = new Request.Builder()

View File

@ -1,46 +1,44 @@
import java.lang.reflect.Field import java.lang.reflect.Field
import play.api.mvc.Action
import play.api.routing.Router
import play.api.mvc._
import play.api.routing.sird._
import datadog.trace.api.Trace import datadog.trace.api.Trace
import play.api.inject.bind
import play.api.mvc.{Action, _}
import play.api.routing.Router
import play.api.routing.sird._
import play.inject.DelegateInjector import play.inject.DelegateInjector
import scala.concurrent.{Await, Future}
import scala.concurrent.duration._
import play.api.inject.bind
import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scala.concurrent.{Await, Future}
object Play24TestUtils { object Play24TestUtils {
def buildTestApp(): play.Application = { def buildTestApp(): play.Application = {
// build play.api.Application with desired setting and pass into play.Application for testing // build play.api.Application with desired setting and pass into play.Application for testing
val apiApp :play.api.Application = new play.api.inject.guice.GuiceApplicationBuilder() val apiApp: play.api.Application = new play.api.inject.guice.GuiceApplicationBuilder()
.overrides(bind[Router].toInstance(Router.from { .overrides(bind[Router].toInstance(Router.from {
case GET(p"/helloplay/$from") => Action { req: RequestHeader => case GET(p"/helloplay/$from") => Action { req: RequestHeader =>
HandlerSetter.setHandler(req, "/helloplay/:from") HandlerSetter.setHandler(req, "/helloplay/:from")
val f: Future[String] = Future[String] { val f: Future[String] = Future[String] {
TracedWork.doWork() TracedWork.doWork()
from from
}
Results.Ok(s"hello " + Await.result(f, 5 seconds))
} }
case GET(p"/make-error") => Action { req: RequestHeader => Results.Ok(s"hello " + Await.result(f, 5 seconds))
HandlerSetter.setHandler(req, "/make-error") }
Results.InternalServerError("Really sorry...") case GET(p"/make-error") => Action { req: RequestHeader =>
HandlerSetter.setHandler(req, "/make-error")
Results.InternalServerError("Really sorry...")
}
case GET(p"/exception") => Action { req: RequestHeader =>
HandlerSetter.setHandler(req, "/exception")
if (System.currentTimeMillis() > 0) {
throw new RuntimeException("oh no")
} }
case GET(p"/exception") => Action { req: RequestHeader => Results.Ok("hello")
HandlerSetter.setHandler(req, "/exception") }
if (System.currentTimeMillis() > 0) { case _ => Action {
throw new RuntimeException("oh no") Results.NotFound("Sorry..")
} }
Results.Ok("hello") }))
}
case _ => Action {
Results.NotFound("Sorry..")
}
}))
.build() .build()
@ -64,7 +62,7 @@ object HandlerSetter {
f.setAccessible(false) f.setAccessible(false)
} }
private def getField(o: Object, fieldName :String): Object = { private def getField(o: Object, fieldName: String): Object = {
val f: Field = o.getClass().getDeclaredField(fieldName) val f: Field = o.getClass().getDeclaredField(fieldName)
f.setAccessible(true) f.setAccessible(true)
val result: Object = f.get(o) val result: Object = f.get(o)

View File

@ -1,7 +1,14 @@
package datadog.trace.instrumentation.ratpack; package datadog.trace.instrumentation.ratpack;
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClassWithMethod; import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClassWithMethod;
import static net.bytebuddy.matcher.ElementMatchers.*; 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.isStatic;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.not;
import static net.bytebuddy.matcher.ElementMatchers.returns;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.Instrumenter;
@ -63,7 +70,7 @@ public final class RatpackInstrumentation extends Instrumenter.Default {
@Override @Override
public Map<ElementMatcher, String> transformers() { public Map<ElementMatcher, String> transformers() {
Map<ElementMatcher, String> transformers = new HashMap<>(); final Map<ElementMatcher, String> transformers = new HashMap<>();
transformers.put( transformers.put(
isMethod().and(isStatic()).and(named("buildBaseRegistry")), isMethod().and(isStatic()).and(named("buildBaseRegistry")),
RatpackServerAdvice.RatpackServerRegistryAdvice.class.getName()); RatpackServerAdvice.RatpackServerRegistryAdvice.class.getName());
@ -106,7 +113,7 @@ public final class RatpackInstrumentation extends Instrumenter.Default {
@Override @Override
public Map<ElementMatcher, String> transformers() { public Map<ElementMatcher, String> transformers() {
Map<ElementMatcher, String> transformers = new HashMap<>(); final Map<ElementMatcher, String> transformers = new HashMap<>();
transformers.put( transformers.put(
named("register").and(takesArguments(ACTION_TYPE_DESCRIPTION)), named("register").and(takesArguments(ACTION_TYPE_DESCRIPTION)),
RatpackServerAdvice.ExecStarterAdvice.class.getName()); RatpackServerAdvice.ExecStarterAdvice.class.getName());
@ -148,7 +155,7 @@ public final class RatpackInstrumentation extends Instrumenter.Default {
@Override @Override
public Map<ElementMatcher, String> transformers() { public Map<ElementMatcher, String> transformers() {
Map<ElementMatcher, String> transformers = new HashMap<>(); final Map<ElementMatcher, String> transformers = new HashMap<>();
transformers.put( transformers.put(
named("fork").and(returns(named("ratpack.exec.ExecStarter"))), named("fork").and(returns(named("ratpack.exec.ExecStarter"))),
RatpackServerAdvice.ExecutionAdvice.class.getName()); RatpackServerAdvice.ExecutionAdvice.class.getName());

View File

@ -1,7 +1,8 @@
package datadog.trace.instrumentation.ratpack.impl; package datadog.trace.instrumentation.ratpack.impl;
import io.opentracing.propagation.TextMap; import io.opentracing.propagation.TextMap;
import java.util.*; import java.util.Iterator;
import java.util.Map;
import ratpack.http.Request; import ratpack.http.Request;
import ratpack.util.MultiValueMap; import ratpack.util.MultiValueMap;
@ -12,8 +13,8 @@ import ratpack.util.MultiValueMap;
public class RatpackRequestExtractAdapter implements TextMap { public class RatpackRequestExtractAdapter implements TextMap {
private final MultiValueMap<String, String> headers; private final MultiValueMap<String, String> headers;
RatpackRequestExtractAdapter(Request request) { RatpackRequestExtractAdapter(final Request request) {
this.headers = request.getHeaders().asMultiValueMap(); headers = request.getHeaders().asMultiValueMap();
} }
@Override @Override
@ -22,7 +23,7 @@ public class RatpackRequestExtractAdapter implements TextMap {
} }
@Override @Override
public void put(String key, String value) { public void put(final String key, final String value) {
throw new UnsupportedOperationException("This class should be used only with Tracer.inject()!"); throw new UnsupportedOperationException("This class should be used only with Tracer.inject()!");
} }
} }

View File

@ -33,8 +33,8 @@ dependencies {
testCompile project(':dd-java-agent:testing') testCompile project(':dd-java-agent:testing')
testCompile group: 'net.spy', name: 'spymemcached', version: '2.12.0' testCompile group: 'net.spy', name: 'spymemcached', version: '2.12.0'
testCompile group: 'org.spockframework', name:'spock-core', version:'1.1-groovy-2.4' testCompile group: 'org.spockframework', name: 'spock-core', version: '1.1-groovy-2.4'
testCompile group: 'org.testcontainers', name:'testcontainers', version:'1.7.3' testCompile group: 'org.testcontainers', name: 'testcontainers', version: '1.7.3'
} }
configurations.latestDepTestCompile { configurations.latestDepTestCompile {

View File

@ -3,21 +3,21 @@ package datadog.trace.instrumentation.spymemcached;
import io.opentracing.Span; import io.opentracing.Span;
import io.opentracing.Tracer; import io.opentracing.Tracer;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import net.spy.memcached.internal.*; import net.spy.memcached.internal.BulkGetFuture;
public class BulkGetCompletionListener extends CompletionListener<BulkGetFuture<?>> public class BulkGetCompletionListener extends CompletionListener<BulkGetFuture<?>>
implements net.spy.memcached.internal.BulkGetCompletionListener { implements net.spy.memcached.internal.BulkGetCompletionListener {
public BulkGetCompletionListener(Tracer tracer, String methodName) { public BulkGetCompletionListener(final Tracer tracer, final String methodName) {
super(tracer, methodName, true); super(tracer, methodName, true);
} }
@Override @Override
public void onComplete(BulkGetFuture<?> future) { public void onComplete(final BulkGetFuture<?> future) {
closeAsyncSpan(future); closeAsyncSpan(future);
} }
@Override @Override
protected void processResult(Span span, BulkGetFuture<?> future) protected void processResult(final Span span, final BulkGetFuture<?> future)
throws ExecutionException, InterruptedException { throws ExecutionException, InterruptedException {
/* /*
Note: for now we do not have an affective way of representing results of bulk operations, Note: for now we do not have an affective way of representing results of bulk operations,

View File

@ -1,7 +1,11 @@
package datadog.trace.instrumentation.spymemcached; package datadog.trace.instrumentation.spymemcached;
import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClassWithMethod; import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClassWithMethod;
import static net.bytebuddy.matcher.ElementMatchers.*; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
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.returns;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.Instrumenter;
@ -55,7 +59,7 @@ public final class MemcachedClientInstrumentation extends Instrumenter.Default {
@Override @Override
public Map<ElementMatcher, String> transformers() { public Map<ElementMatcher, String> transformers() {
Map<ElementMatcher, String> transformers = new HashMap<>(); final Map<ElementMatcher, String> transformers = new HashMap<>();
transformers.put( transformers.put(
isMethod() isMethod()
.and(isPublic()) .and(isPublic())
@ -96,7 +100,7 @@ public final class MemcachedClientInstrumentation extends Instrumenter.Default {
@Advice.Origin final Method method, @Advice.Origin final Method method,
@Advice.Return final OperationFuture future) { @Advice.Return final OperationFuture future) {
if (shouldInjectListener && future != null) { if (shouldInjectListener && future != null) {
OperationCompletionListener listener = final OperationCompletionListener listener =
new OperationCompletionListener(GlobalTracer.get(), method.getName()); new OperationCompletionListener(GlobalTracer.get(), method.getName());
future.addListener(listener); future.addListener(listener);
CallDepthThreadLocalMap.reset(MemcachedClient.class); CallDepthThreadLocalMap.reset(MemcachedClient.class);
@ -117,7 +121,7 @@ public final class MemcachedClientInstrumentation extends Instrumenter.Default {
@Advice.Origin final Method method, @Advice.Origin final Method method,
@Advice.Return final GetFuture future) { @Advice.Return final GetFuture future) {
if (shouldInjectListener && future != null) { if (shouldInjectListener && future != null) {
GetCompletionListener listener = final GetCompletionListener listener =
new GetCompletionListener(GlobalTracer.get(), method.getName()); new GetCompletionListener(GlobalTracer.get(), method.getName());
future.addListener(listener); future.addListener(listener);
CallDepthThreadLocalMap.reset(MemcachedClient.class); CallDepthThreadLocalMap.reset(MemcachedClient.class);
@ -138,7 +142,7 @@ public final class MemcachedClientInstrumentation extends Instrumenter.Default {
@Advice.Origin final Method method, @Advice.Origin final Method method,
@Advice.Return final BulkFuture future) { @Advice.Return final BulkFuture future) {
if (shouldInjectListener && future != null) { if (shouldInjectListener && future != null) {
BulkGetCompletionListener listener = final BulkGetCompletionListener listener =
new BulkGetCompletionListener(GlobalTracer.get(), method.getName()); new BulkGetCompletionListener(GlobalTracer.get(), method.getName());
future.addListener(listener); future.addListener(listener);
CallDepthThreadLocalMap.reset(MemcachedClient.class); CallDepthThreadLocalMap.reset(MemcachedClient.class);

View File

@ -22,11 +22,11 @@ import java.util.concurrent.BlockingQueue
import java.util.concurrent.ExecutorService import java.util.concurrent.ExecutorService
import java.util.concurrent.locks.ReentrantLock import java.util.concurrent.locks.ReentrantLock
import static datadog.trace.agent.test.ListWriterAssert.assertTraces
import static CompletionListener.COMPONENT_NAME import static CompletionListener.COMPONENT_NAME
import static CompletionListener.OPERATION_NAME import static CompletionListener.OPERATION_NAME
import static CompletionListener.SERVICE_NAME import static CompletionListener.SERVICE_NAME
import static CompletionListener.SPAN_TYPE import static CompletionListener.SPAN_TYPE
import static datadog.trace.agent.test.ListWriterAssert.assertTraces
import static datadog.trace.agent.test.TestUtils.runUnderTrace import static datadog.trace.agent.test.TestUtils.runUnderTrace
import static net.spy.memcached.ConnectionFactoryBuilder.Protocol.BINARY import static net.spy.memcached.ConnectionFactoryBuilder.Protocol.BINARY
@ -124,16 +124,16 @@ class SpymemcachedTest extends AgentTestRunner {
// Add some keys to test on later: // Add some keys to test on later:
def valuesToSet = [ def valuesToSet = [
"test-get": "get test", "test-get" : "get test",
"test-get-2": "get test 2", "test-get-2" : "get test 2",
"test-append": "append test", "test-append" : "append test",
"test-prepend": "prepend test", "test-prepend": "prepend test",
"test-delete": "delete test", "test-delete" : "delete test",
"test-replace": "replace test", "test-replace": "replace test",
"test-touch": "touch test", "test-touch" : "touch test",
"test-cas": "cas test", "test-cas" : "cas test",
"test-decr": "200", "test-decr" : "200",
"test-incr": "100" "test-incr" : "100"
] ]
runUnderTrace("setup") { runUnderTrace("setup") {
valuesToSet.each { k, v -> assert memcached.set(key(k), expiration, v).get() } valuesToSet.each { k, v -> assert memcached.set(key(k), expiration, v).get() }
@ -152,7 +152,7 @@ class SpymemcachedTest extends AgentTestRunner {
assertTraces(TEST_WRITER, 1) { assertTraces(TEST_WRITER, 1) {
trace(0, 2) { trace(0, 2) {
getParentSpan(it, 0) getParentSpan(it, 0)
getSpan(it, 1, "get", null,"hit") getSpan(it, 1, "get", null, "hit")
} }
} }
} }
@ -167,7 +167,7 @@ class SpymemcachedTest extends AgentTestRunner {
assertTraces(TEST_WRITER, 1) { assertTraces(TEST_WRITER, 1) {
trace(0, 2) { trace(0, 2) {
getParentSpan(it, 0) getParentSpan(it, 0)
getSpan(it, 1, "get", null,"miss") getSpan(it, 1, "get", null, "miss")
} }
} }
} }
@ -223,7 +223,7 @@ class SpymemcachedTest extends AgentTestRunner {
assertTraces(TEST_WRITER, 1) { assertTraces(TEST_WRITER, 1) {
trace(0, 2) { trace(0, 2) {
getParentSpan(it, 0) getParentSpan(it, 0)
getSpan(it, 1, "getBulk", null,null) getSpan(it, 1, "getBulk", null, null)
} }
} }
} }
@ -271,7 +271,7 @@ class SpymemcachedTest extends AgentTestRunner {
assertTraces(TEST_WRITER, 1) { assertTraces(TEST_WRITER, 1) {
trace(0, 3) { trace(0, 3) {
getParentSpan(it, 0) getParentSpan(it, 0)
getSpan(it, 1, "get", null,"hit") getSpan(it, 1, "get", null, "hit")
getSpan(it, 2, "add") getSpan(it, 2, "add")
} }
} }
@ -305,7 +305,7 @@ class SpymemcachedTest extends AgentTestRunner {
assertTraces(TEST_WRITER, 1) { assertTraces(TEST_WRITER, 1) {
trace(0, 3) { trace(0, 3) {
getParentSpan(it, 0) getParentSpan(it, 0)
getSpan(it, 1, "get", null,"miss") getSpan(it, 1, "get", null, "miss")
getSpan(it, 2, "delete") getSpan(it, 2, "delete")
} }
} }
@ -337,7 +337,7 @@ class SpymemcachedTest extends AgentTestRunner {
assertTraces(TEST_WRITER, 1) { assertTraces(TEST_WRITER, 1) {
trace(0, 3) { trace(0, 3) {
getParentSpan(it, 0) getParentSpan(it, 0)
getSpan(it, 1, "get", null,"hit") getSpan(it, 1, "get", null, "hit")
getSpan(it, 2, "replace") getSpan(it, 2, "replace")
} }
} }
@ -370,7 +370,7 @@ class SpymemcachedTest extends AgentTestRunner {
assertTraces(TEST_WRITER, 1) { assertTraces(TEST_WRITER, 1) {
trace(0, 4) { trace(0, 4) {
getParentSpan(it, 0) getParentSpan(it, 0)
getSpan(it, 1, "get", null,"hit") getSpan(it, 1, "get", null, "hit")
getSpan(it, 2, "append") getSpan(it, 2, "append")
getSpan(it, 3, "gets") getSpan(it, 3, "gets")
} }
@ -389,7 +389,7 @@ class SpymemcachedTest extends AgentTestRunner {
assertTraces(TEST_WRITER, 1) { assertTraces(TEST_WRITER, 1) {
trace(0, 4) { trace(0, 4) {
getParentSpan(it, 0) getParentSpan(it, 0)
getSpan(it, 1, "get", null,"hit") getSpan(it, 1, "get", null, "hit")
getSpan(it, 2, "prepend") getSpan(it, 2, "prepend")
getSpan(it, 3, "gets") getSpan(it, 3, "gets")
} }
@ -503,7 +503,7 @@ class SpymemcachedTest extends AgentTestRunner {
assertTraces(TEST_WRITER, 1) { assertTraces(TEST_WRITER, 1) {
trace(0, 3) { trace(0, 3) {
getParentSpan(it, 0) getParentSpan(it, 0)
getSpan(it, 1, "get", null,"hit") getSpan(it, 1, "get", null, "hit")
getSpan(it, 2, "decr") getSpan(it, 2, "decr")
} }
} }
@ -552,7 +552,7 @@ class SpymemcachedTest extends AgentTestRunner {
assertTraces(TEST_WRITER, 1) { assertTraces(TEST_WRITER, 1) {
trace(0, 3) { trace(0, 3) {
getParentSpan(it, 0) getParentSpan(it, 0)
getSpan(it, 1, "get", null,"hit") getSpan(it, 1, "get", null, "hit")
getSpan(it, 2, "incr") getSpan(it, 2, "incr")
} }
} }
@ -590,7 +590,7 @@ class SpymemcachedTest extends AgentTestRunner {
keyPrefix + k keyPrefix + k
} }
def longString(char c='s' as char) { def longString(char c = 's' as char) {
char[] chars = new char[250] char[] chars = new char[250]
Arrays.fill(chars, 's' as char) Arrays.fill(chars, 's' as char)
return new String(chars) return new String(chars)
@ -622,7 +622,7 @@ class SpymemcachedTest extends AgentTestRunner {
} }
} }
def getSpan(TraceAssert trace, int index, String operation, String error=null, String result=null) { def getSpan(TraceAssert trace, int index, String operation, String error = null, String result = null) {
return trace.span(index) { return trace.span(index) {
if (index > 0) { if (index > 0) {
childOf(trace.span(0)) childOf(trace.span(0))
@ -632,7 +632,7 @@ class SpymemcachedTest extends AgentTestRunner {
operationName OPERATION_NAME operationName OPERATION_NAME
resourceName operation resourceName operation
spanType SPAN_TYPE spanType SPAN_TYPE
errored (error != null && error != "canceled") errored(error != null && error != "canceled")
tags { tags {
defaultTags() defaultTags()

View File

@ -16,7 +16,12 @@
*/ */
package datadog.trace.agent; package datadog.trace.agent;
import java.io.*; import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.lang.instrument.Instrumentation; import java.lang.instrument.Instrumentation;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
@ -91,8 +96,8 @@ public class TracingAgent {
* @param toolingJar jar to use for the classpath of the datadog classloader * @param toolingJar jar to use for the classpath of the datadog classloader
* @return Datadog Classloader * @return Datadog Classloader
*/ */
private static ClassLoader createDatadogClassLoader(File bootstrapJar, File toolingJar) private static ClassLoader createDatadogClassLoader(
throws Exception { final File bootstrapJar, final File toolingJar) throws Exception {
final ClassLoader agentParent; final ClassLoader agentParent;
final String javaVersion = System.getProperty("java.version"); final String javaVersion = System.getProperty("java.version");
if (javaVersion.startsWith("1.7") || javaVersion.startsWith("1.8")) { if (javaVersion.startsWith("1.7") || javaVersion.startsWith("1.8")) {
@ -101,9 +106,9 @@ public class TracingAgent {
// platform classloader is parent of system in java 9+ // platform classloader is parent of system in java 9+
agentParent = getPlatformClassLoader(); agentParent = getPlatformClassLoader();
} }
Class<?> loaderClass = final Class<?> loaderClass =
ClassLoader.getSystemClassLoader().loadClass("datadog.trace.bootstrap.DatadogClassLoader"); ClassLoader.getSystemClassLoader().loadClass("datadog.trace.bootstrap.DatadogClassLoader");
Constructor constructor = final Constructor constructor =
loaderClass.getDeclaredConstructor(URL.class, URL.class, ClassLoader.class); loaderClass.getDeclaredConstructor(URL.class, URL.class, ClassLoader.class);
return (ClassLoader) return (ClassLoader)
constructor.newInstance( constructor.newInstance(
@ -111,8 +116,8 @@ public class TracingAgent {
} }
/** Extract sourcePath out of loader to a temporary file named destName. */ /** Extract sourcePath out of loader to a temporary file named destName. */
private static File extractToTmpFile(ClassLoader loader, String sourcePath, String destName) private static File extractToTmpFile(
throws Exception { final ClassLoader loader, final String sourcePath, final String destName) throws Exception {
final String destPrefix; final String destPrefix;
final String destSuffix; final String destSuffix;
{ {
@ -171,7 +176,7 @@ public class TracingAgent {
public static void main(final String... args) { public static void main(final String... args) {
try { try {
System.out.println(getAgentVersion()); System.out.println(getAgentVersion());
} catch (Exception e) { } catch (final Exception e) {
System.out.println("Failed to parse agent version"); System.out.println("Failed to parse agent version");
e.printStackTrace(); e.printStackTrace();
} }

View File

@ -1,10 +1,9 @@
import datadog.trace.agent.test.AgentTestRunner
import datadog.trace.agent.test.TestUtils import datadog.trace.agent.test.TestUtils
import io.opentracing.Tracer import io.opentracing.Tracer
import java.lang.reflect.Field import java.lang.reflect.Field
import datadog.trace.agent.test.AgentTestRunner
class AgentTestRunnerTest extends AgentTestRunner { class AgentTestRunnerTest extends AgentTestRunner {
private static final ClassLoader BOOTSTRAP_CLASSLOADER = null private static final ClassLoader BOOTSTRAP_CLASSLOADER = null
private static final ClassLoader OT_LOADER private static final ClassLoader OT_LOADER

View File

@ -6,7 +6,7 @@ import io.opentracing.util.GlobalTracer
class TraceCorrelationTest extends AgentTestRunner { class TraceCorrelationTest extends AgentTestRunner {
def "access trace correlation only under trace" () { def "access trace correlation only under trace"() {
when: when:
Scope scope = GlobalTracer.get().buildSpan("myspan").startActive(true) Scope scope = GlobalTracer.get().buildSpan("myspan").startActive(true)
DDSpan span = (DDSpan) scope.span() DDSpan span = (DDSpan) scope.span()

View File

@ -2,9 +2,9 @@ package muzzle
import datadog.trace.agent.test.AgentTestRunner import datadog.trace.agent.test.AgentTestRunner
import datadog.trace.agent.test.TestUtils import datadog.trace.agent.test.TestUtils
import datadog.trace.agent.tooling.muzzle.Reference
import datadog.trace.agent.tooling.muzzle.ReferenceCreator import datadog.trace.agent.tooling.muzzle.ReferenceCreator
import datadog.trace.agent.tooling.muzzle.ReferenceMatcher import datadog.trace.agent.tooling.muzzle.ReferenceMatcher
import datadog.trace.agent.tooling.muzzle.Reference
class AdviceReferenceVisitorTest extends AgentTestRunner { class AdviceReferenceVisitorTest extends AgentTestRunner {
@ -25,12 +25,12 @@ class AdviceReferenceVisitorTest extends AgentTestRunner {
Reference[] refs = ReferenceCreator.createReferencesFrom(AdviceClass.getName(), this.getClass().getClassLoader()).values().toArray(new Reference[0]) Reference[] refs = ReferenceCreator.createReferencesFrom(AdviceClass.getName(), this.getClass().getClassLoader()).values().toArray(new Reference[0])
ReferenceMatcher refMatcher = new ReferenceMatcher(refs) ReferenceMatcher refMatcher = new ReferenceMatcher(refs)
ClassLoader safeClassloader = new URLClassLoader([TestUtils.createJarWithClasses(AdviceClass$A, ClassLoader safeClassloader = new URLClassLoader([TestUtils.createJarWithClasses(AdviceClass$A,
AdviceClass$SomeInterface, AdviceClass$SomeInterface,
AdviceClass$SomeImplementation)] as URL[], AdviceClass$SomeImplementation)] as URL[],
(ClassLoader) null) (ClassLoader) null)
ClassLoader unsafeClassloader = new URLClassLoader([TestUtils.createJarWithClasses(AdviceClass$SomeInterface, ClassLoader unsafeClassloader = new URLClassLoader([TestUtils.createJarWithClasses(AdviceClass$SomeInterface,
AdviceClass$SomeImplementation)] as URL[], AdviceClass$SomeImplementation)] as URL[],
(ClassLoader) null) (ClassLoader) null)
expect: expect:
refMatcher.getMismatchedReferenceSources(safeClassloader).size() == 0 refMatcher.getMismatchedReferenceSources(safeClassloader).size() == 0

View File

@ -4,7 +4,10 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
import datadog.opentracing.decorators.AbstractDecorator; import datadog.opentracing.decorators.AbstractDecorator;
import datadog.trace.api.DDTags; import datadog.trace.api.DDTags;
import datadog.trace.api.sampling.PrioritySampling; import datadog.trace.api.sampling.PrioritySampling;
import java.util.*; import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -115,15 +118,15 @@ public class DDSpanContext implements io.opentracing.SpanContext {
} }
public String getTraceId() { public String getTraceId() {
return this.traceId; return traceId;
} }
public String getParentId() { public String getParentId() {
return this.parentId; return parentId;
} }
public String getSpanId() { public String getSpanId() {
return this.spanId; return spanId;
} }
public String getServiceName() { public String getServiceName() {
@ -135,9 +138,7 @@ public class DDSpanContext implements io.opentracing.SpanContext {
} }
public String getResourceName() { public String getResourceName() {
return this.resourceName == null || this.resourceName.isEmpty() return resourceName == null || resourceName.isEmpty() ? operationName : resourceName;
? this.operationName
: this.resourceName;
} }
public void setResourceName(final String resourceName) { public void setResourceName(final String resourceName) {
@ -170,7 +171,7 @@ public class DDSpanContext implements io.opentracing.SpanContext {
public void setSamplingPriority(final int newPriority) { public void setSamplingPriority(final int newPriority) {
if (trace != null) { if (trace != null) {
DDSpan rootSpan = trace.getRootSpan(); final DDSpan rootSpan = trace.getRootSpan();
if (null != rootSpan && rootSpan.context() != this) { if (null != rootSpan && rootSpan.context() != this) {
rootSpan.context().setSamplingPriority(newPriority); rootSpan.context().setSamplingPriority(newPriority);
return; return;
@ -197,7 +198,7 @@ public class DDSpanContext implements io.opentracing.SpanContext {
/** @return the sampling priority of this span's trace, or null if no priority has been set */ /** @return the sampling priority of this span's trace, or null if no priority has been set */
public int getSamplingPriority() { public int getSamplingPriority() {
if (trace != null) { if (trace != null) {
DDSpan rootSpan = trace.getRootSpan(); final DDSpan rootSpan = trace.getRootSpan();
if (null != rootSpan && rootSpan.context() != this) { if (null != rootSpan && rootSpan.context() != this) {
return rootSpan.context().getSamplingPriority(); return rootSpan.context().getSamplingPriority();
} }
@ -217,7 +218,7 @@ public class DDSpanContext implements io.opentracing.SpanContext {
*/ */
public boolean lockSamplingPriority() { public boolean lockSamplingPriority() {
if (trace != null) { if (trace != null) {
DDSpan rootSpan = trace.getRootSpan(); final DDSpan rootSpan = trace.getRootSpan();
if (null != rootSpan && rootSpan.context() != this) { if (null != rootSpan && rootSpan.context() != this) {
return rootSpan.context().lockSamplingPriority(); return rootSpan.context().lockSamplingPriority();
} }
@ -236,11 +237,11 @@ public class DDSpanContext implements io.opentracing.SpanContext {
} }
public void setBaggageItem(final String key, final String value) { public void setBaggageItem(final String key, final String value) {
this.baggageItems.put(key, value); baggageItems.put(key, value);
} }
public String getBaggageItem(final String key) { public String getBaggageItem(final String key) {
return this.baggageItems.get(key); return baggageItems.get(key);
} }
public Map<String, String> getBaggageItems() { public Map<String, String> getBaggageItems() {
@ -252,17 +253,17 @@ public class DDSpanContext implements io.opentracing.SpanContext {
*/ */
@Override @Override
public Iterable<Map.Entry<String, String>> baggageItems() { public Iterable<Map.Entry<String, String>> baggageItems() {
return this.baggageItems.entrySet(); return baggageItems.entrySet();
} }
@JsonIgnore @JsonIgnore
public PendingTrace getTrace() { public PendingTrace getTrace() {
return this.trace; return trace;
} }
@JsonIgnore @JsonIgnore
public DDTracer getTracer() { public DDTracer getTracer() {
return this.tracer; return tracer;
} }
public Map<String, Number> getMetrics() { public Map<String, Number> getMetrics() {
@ -270,7 +271,7 @@ public class DDSpanContext implements io.opentracing.SpanContext {
return metrics == null ? EMPTY_METRICS : metrics; return metrics == null ? EMPTY_METRICS : metrics;
} }
public void setMetric(String key, Number value) { public void setMetric(final String key, final Number value) {
if (metrics.get() == null) { if (metrics.get() == null) {
metrics.compareAndSet(null, new ConcurrentHashMap<String, Number>()); metrics.compareAndSet(null, new ConcurrentHashMap<String, Number>());
} }
@ -306,7 +307,7 @@ public class DDSpanContext implements io.opentracing.SpanContext {
} }
if (addTag) { if (addTag) {
this.tags.put(tag, value); tags.put(tag, value);
} }
} }

View File

@ -265,7 +265,7 @@ class DDSpanBuilderTest extends Specification {
span.context().@tags == extractedContext.tags span.context().@tags == extractedContext.tags
where: where:
extractedContext | _ extractedContext | _
new ExtractedContext("1", "2", 0, [:], [:]) | _ new ExtractedContext("1", "2", 0, [:], [:]) | _
new ExtractedContext("3", "4", 1, ["asdf": "qwer"], ["zxcv": "1234"]) | _ new ExtractedContext("3", "4", 1, ["asdf": "qwer"], ["zxcv": "1234"]) | _
} }

View File

@ -22,10 +22,10 @@ class DDSpanContextTest extends Specification {
where: where:
name | extra | tags name | extra | tags
DDTags.SERVICE_NAME | "some.tag=asdf, " | ["some.tag": "asdf", (DDTags.SPAN_TYPE):"fakeType", (DDTags.THREAD_NAME): Thread.currentThread().name, (DDTags.THREAD_ID): Thread.currentThread().id] DDTags.SERVICE_NAME | "some.tag=asdf, " | ["some.tag": "asdf", (DDTags.SPAN_TYPE): "fakeType", (DDTags.THREAD_NAME): Thread.currentThread().name, (DDTags.THREAD_ID): Thread.currentThread().id]
DDTags.RESOURCE_NAME | "some.tag=asdf, " | ["some.tag": "asdf", (DDTags.SPAN_TYPE):"fakeType", (DDTags.THREAD_NAME): Thread.currentThread().name, (DDTags.THREAD_ID): Thread.currentThread().id] DDTags.RESOURCE_NAME | "some.tag=asdf, " | ["some.tag": "asdf", (DDTags.SPAN_TYPE): "fakeType", (DDTags.THREAD_NAME): Thread.currentThread().name, (DDTags.THREAD_ID): Thread.currentThread().id]
DDTags.SPAN_TYPE | "some.tag=asdf, " | ["some.tag": "asdf", (DDTags.SPAN_TYPE):"fakeType", (DDTags.THREAD_NAME): Thread.currentThread().name, (DDTags.THREAD_ID): Thread.currentThread().id] DDTags.SPAN_TYPE | "some.tag=asdf, " | ["some.tag": "asdf", (DDTags.SPAN_TYPE): "fakeType", (DDTags.THREAD_NAME): Thread.currentThread().name, (DDTags.THREAD_ID): Thread.currentThread().id]
"some.tag" | "" | [ (DDTags.SPAN_TYPE):"fakeType", (DDTags.THREAD_NAME): Thread.currentThread().name, (DDTags.THREAD_ID): Thread.currentThread().id] "some.tag" | "" | [(DDTags.SPAN_TYPE): "fakeType", (DDTags.THREAD_NAME): Thread.currentThread().name, (DDTags.THREAD_ID): Thread.currentThread().id]
} }
def "special tags set certain values"() { def "special tags set certain values"() {

View File

@ -3,6 +3,6 @@
apply plugin: 'scala' apply plugin: 'scala'
compileTestGroovy { compileTestGroovy {
classpath = classpath.plus(files(compileTestScala.destinationDir)) classpath = classpath.plus(files(compileTestScala.destinationDir))
dependsOn compileTestScala dependsOn compileTestScala
} }