Merge pull request #416 from DataDog/tyler/contributing
Add contributing document and apply formatting.
This commit is contained in:
commit
12e41be258
|
@ -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:
|
||||||
|

|
||||||
|
* [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)
|
||||||
|

|
|
@ -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())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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 == []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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')
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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"() {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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')) {
|
||||||
|
|
|
@ -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')
|
||||||
|
|
|
@ -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 = {
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"() {
|
||||||
|
|
|
@ -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
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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"))
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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"))
|
||||||
|
|
|
@ -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) {
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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()!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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"]) | _
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"() {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue