Change agent jar inclusion in tests that launch a process
The tests were the main problem. By using a different approach to pass in the agent jar, the TracingAgent code can be much simpler
This commit is contained in:
parent
a9d0d2cbbe
commit
ba6ff678db
|
@ -78,7 +78,7 @@ jar {
|
||||||
|
|
||||||
shadowJar {
|
shadowJar {
|
||||||
configurations = [project.configurations.shadowInclude]
|
configurations = [project.configurations.shadowInclude]
|
||||||
|
|
||||||
classifier null
|
classifier null
|
||||||
|
|
||||||
mergeServiceFiles()
|
mergeServiceFiles()
|
||||||
|
@ -114,22 +114,18 @@ dependencies {
|
||||||
testCompile deps.opentracingMock
|
testCompile deps.opentracingMock
|
||||||
testCompile deps.testLogging
|
testCompile deps.testLogging
|
||||||
testCompile deps.guava
|
testCompile deps.guava
|
||||||
|
|
||||||
shadowInclude project(':dd-java-agent:agent-bootstrap')
|
shadowInclude project(':dd-java-agent:agent-bootstrap')
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType(Test).configureEach {
|
tasks.withType(Test).configureEach {
|
||||||
jvmArgs "-Ddd.service.name=java-agent-tests"
|
jvmArgs "-Ddd.service.name=java-agent-tests"
|
||||||
jvmArgs "-Ddd.writer.type=LoggingWriter"
|
jvmArgs "-Ddd.writer.type=LoggingWriter"
|
||||||
|
jvmArgs "-Dagent.jar.to.forward=${shadowJar.archivePath}"
|
||||||
// Multi-threaded logging seems to be causing deadlocks with Gradle's log capture.
|
// Multi-threaded logging seems to be causing deadlocks with Gradle's log capture.
|
||||||
// jvmArgs "-Ddatadog.slf4j.simpleLogger.defaultLogLevel=debug"
|
// jvmArgs "-Ddatadog.slf4j.simpleLogger.defaultLogLevel=debug"
|
||||||
// jvmArgs "-Dorg.slf4j.simpleLogger.defaultLogLevel=debug"
|
// jvmArgs "-Dorg.slf4j.simpleLogger.defaultLogLevel=debug"
|
||||||
|
|
||||||
doFirst {
|
|
||||||
// Defining here to allow jacoco to be first on the command line.
|
|
||||||
jvmArgs "-javaagent:${shadowJar.archivePath}"
|
|
||||||
}
|
|
||||||
|
|
||||||
testLogging {
|
testLogging {
|
||||||
events "started"
|
events "started"
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,32 +152,16 @@ public class TracingAgent {
|
||||||
private static synchronized URL installBootstrapJar(
|
private static synchronized URL installBootstrapJar(
|
||||||
final Instrumentation inst, final boolean usingCustomLogManager)
|
final Instrumentation inst, final boolean usingCustomLogManager)
|
||||||
throws IOException, URISyntaxException, ClassNotFoundException {
|
throws IOException, URISyntaxException, ClassNotFoundException {
|
||||||
URL bootstrapURL = null;
|
|
||||||
File bootstrapFile = null;
|
|
||||||
|
|
||||||
final CodeSource codeSource = TracingAgent.class.getProtectionDomain().getCodeSource();
|
final CodeSource codeSource = TracingAgent.class.getProtectionDomain().getCodeSource();
|
||||||
|
|
||||||
if (codeSource != null) {
|
if (codeSource != null) {
|
||||||
bootstrapURL = codeSource.getLocation();
|
final URL bootstrapURL = codeSource.getLocation();
|
||||||
|
|
||||||
bootstrapFile = new File(bootstrapURL.toURI());
|
inst.appendToBootstrapClassLoaderSearch(new JarFile(new File(bootstrapURL.toURI())));
|
||||||
|
return bootstrapURL;
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Unable to install bootstrap jar. Code source not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bootstrapFile == null || bootstrapFile.isDirectory()) {
|
|
||||||
// At most one of ( DatadogClassLoader.class , TracingAgent.class ) has a CodeSource that
|
|
||||||
// doesn't lead to the agent jar
|
|
||||||
|
|
||||||
bootstrapURL =
|
|
||||||
ClassLoader.getSystemClassLoader()
|
|
||||||
.loadClass("datadog.trace.bootstrap.DatadogClassLoader")
|
|
||||||
.getProtectionDomain()
|
|
||||||
.getCodeSource()
|
|
||||||
.getLocation();
|
|
||||||
|
|
||||||
bootstrapFile = new File(bootstrapURL.toURI());
|
|
||||||
}
|
|
||||||
|
|
||||||
inst.appendToBootstrapClassLoaderSearch(new JarFile(bootstrapFile));
|
|
||||||
return bootstrapURL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -186,11 +170,11 @@ public class TracingAgent {
|
||||||
*
|
*
|
||||||
* @param innerJarFilename Filename of internal jar to use for the classpath of the datadog
|
* @param innerJarFilename Filename of internal jar to use for the classpath of the datadog
|
||||||
* classloader
|
* classloader
|
||||||
* @param bootStrapURL
|
* @param bootstrapURL
|
||||||
* @return Datadog Classloader
|
* @return Datadog Classloader
|
||||||
*/
|
*/
|
||||||
private static ClassLoader createDatadogClassLoader(
|
private static ClassLoader createDatadogClassLoader(
|
||||||
final String innerJarFilename, final URL bootStrapURL) throws Exception {
|
final String innerJarFilename, final URL bootstrapURL) 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")) {
|
||||||
|
@ -204,7 +188,7 @@ public class TracingAgent {
|
||||||
ClassLoader.getSystemClassLoader().loadClass("datadog.trace.bootstrap.DatadogClassLoader");
|
ClassLoader.getSystemClassLoader().loadClass("datadog.trace.bootstrap.DatadogClassLoader");
|
||||||
final Constructor constructor =
|
final Constructor constructor =
|
||||||
loaderClass.getDeclaredConstructor(URL.class, String.class, ClassLoader.class);
|
loaderClass.getDeclaredConstructor(URL.class, String.class, ClassLoader.class);
|
||||||
return (ClassLoader) constructor.newInstance(bootStrapURL, innerJarFilename, agentParent);
|
return (ClassLoader) constructor.newInstance(bootstrapURL, innerJarFilename, agentParent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ClassLoader getPlatformClassLoader()
|
private static ClassLoader getPlatformClassLoader()
|
||||||
|
|
|
@ -2,31 +2,15 @@ package datadog.trace.agent
|
||||||
|
|
||||||
import datadog.trace.agent.test.IntegrationTestUtils
|
import datadog.trace.agent.test.IntegrationTestUtils
|
||||||
import jvmbootstraptest.AgentLoadedChecker
|
import jvmbootstraptest.AgentLoadedChecker
|
||||||
import spock.lang.Shared
|
|
||||||
import spock.lang.Specification
|
import spock.lang.Specification
|
||||||
|
|
||||||
import java.lang.management.ManagementFactory
|
|
||||||
import java.lang.management.RuntimeMXBean
|
|
||||||
|
|
||||||
class AgentLoadedIntoBootstrapTest extends Specification {
|
class AgentLoadedIntoBootstrapTest extends Specification {
|
||||||
@Shared
|
|
||||||
private agentArg
|
|
||||||
|
|
||||||
def setupSpec() {
|
|
||||||
final RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean()
|
|
||||||
for (String arg : runtimeMxBean.getInputArguments()) {
|
|
||||||
if (arg.startsWith("-javaagent")) {
|
|
||||||
agentArg = arg
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert agentArg != null
|
|
||||||
}
|
|
||||||
|
|
||||||
def "Agent loads in when separate jvm is launched"() {
|
def "Agent loads in when separate jvm is launched"() {
|
||||||
expect:
|
expect:
|
||||||
IntegrationTestUtils.runOnSeparateJvm(AgentLoadedChecker.getName()
|
IntegrationTestUtils.runOnSeparateJvm(AgentLoadedChecker.getName()
|
||||||
, [agentArg] as String[]
|
, "" as String[]
|
||||||
, "" as String[]
|
, "" as String[]
|
||||||
, [:]
|
, [:]
|
||||||
, true) == 0
|
, true) == 0
|
||||||
|
|
|
@ -4,38 +4,19 @@ import datadog.trace.agent.test.IntegrationTestUtils
|
||||||
import jvmbootstraptest.LogManagerSetter
|
import jvmbootstraptest.LogManagerSetter
|
||||||
import spock.lang.Requires
|
import spock.lang.Requires
|
||||||
import spock.lang.Retry
|
import spock.lang.Retry
|
||||||
import spock.lang.Shared
|
|
||||||
import spock.lang.Specification
|
import spock.lang.Specification
|
||||||
import spock.lang.Timeout
|
import spock.lang.Timeout
|
||||||
|
|
||||||
import java.lang.management.ManagementFactory
|
|
||||||
import java.lang.management.RuntimeMXBean
|
|
||||||
|
|
||||||
// Note: this test is fails on IBM JVM, we would need to investigate this at some point
|
// Note: this test is fails on IBM JVM, we would need to investigate this at some point
|
||||||
@Requires({ !System.getProperty("java.vm.name").contains("IBM J9 VM") })
|
@Requires({ !System.getProperty("java.vm.name").contains("IBM J9 VM") })
|
||||||
@Retry
|
@Retry
|
||||||
@Timeout(30)
|
@Timeout(30)
|
||||||
class CustomLogManagerTest extends Specification {
|
class CustomLogManagerTest extends Specification {
|
||||||
// Run all tests using forked jvm because groovy has already set the global log manager
|
// Run all tests using forked jvm because groovy has already set the global log manager
|
||||||
|
|
||||||
@Shared
|
|
||||||
private agentArg
|
|
||||||
|
|
||||||
def setupSpec() {
|
|
||||||
final RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean()
|
|
||||||
for (String arg : runtimeMxBean.getInputArguments()) {
|
|
||||||
if (arg.startsWith("-javaagent")) {
|
|
||||||
agentArg = arg
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert agentArg != null
|
|
||||||
}
|
|
||||||
|
|
||||||
def "jmxfetch starts up in premain with no custom log manager set"() {
|
def "jmxfetch starts up in premain with no custom log manager set"() {
|
||||||
expect:
|
expect:
|
||||||
IntegrationTestUtils.runOnSeparateJvm(LogManagerSetter.getName()
|
IntegrationTestUtils.runOnSeparateJvm(LogManagerSetter.getName()
|
||||||
, [agentArg, "-Ddd.jmxfetch.enabled=true", "-Ddd.jmxfetch.refresh-beans-period=1", "-Ddatadog.slf4j.simpleLogger.defaultLogLevel=off"] as String[]
|
, ["-Ddd.jmxfetch.enabled=true", "-Ddd.jmxfetch.refresh-beans-period=1", "-Ddatadog.slf4j.simpleLogger.defaultLogLevel=off"] as String[]
|
||||||
, "" as String[]
|
, "" as String[]
|
||||||
, [:]
|
, [:]
|
||||||
, true) == 0
|
, true) == 0
|
||||||
|
@ -44,7 +25,7 @@ class CustomLogManagerTest extends Specification {
|
||||||
def "jmxfetch starts up in premain if configured log manager on system classpath"() {
|
def "jmxfetch starts up in premain if configured log manager on system classpath"() {
|
||||||
expect:
|
expect:
|
||||||
IntegrationTestUtils.runOnSeparateJvm(LogManagerSetter.getName()
|
IntegrationTestUtils.runOnSeparateJvm(LogManagerSetter.getName()
|
||||||
, [agentArg, "-Ddd.jmxfetch.enabled=true", "-Ddd.jmxfetch.refresh-beans-period=1", "-Ddatadog.slf4j.simpleLogger.defaultLogLevel=off", "-Djava.util.logging.manager=jvmbootstraptest.CustomLogManager"] as String[]
|
, ["-Ddd.jmxfetch.enabled=true", "-Ddd.jmxfetch.refresh-beans-period=1", "-Ddatadog.slf4j.simpleLogger.defaultLogLevel=off", "-Djava.util.logging.manager=jvmbootstraptest.CustomLogManager"] as String[]
|
||||||
, "" as String[]
|
, "" as String[]
|
||||||
, [:]
|
, [:]
|
||||||
, true) == 0
|
, true) == 0
|
||||||
|
@ -53,7 +34,7 @@ class CustomLogManagerTest extends Specification {
|
||||||
def "jmxfetch startup is delayed with java.util.logging.manager sysprop"() {
|
def "jmxfetch startup is delayed with java.util.logging.manager sysprop"() {
|
||||||
expect:
|
expect:
|
||||||
IntegrationTestUtils.runOnSeparateJvm(LogManagerSetter.getName()
|
IntegrationTestUtils.runOnSeparateJvm(LogManagerSetter.getName()
|
||||||
, [agentArg, "-Ddd.jmxfetch.enabled=true", "-Ddd.jmxfetch.refresh-beans-period=1", "-Ddatadog.slf4j.simpleLogger.defaultLogLevel=off", "-Djava.util.logging.manager=jvmbootstraptest.MissingLogManager"] as String[]
|
, ["-Ddd.jmxfetch.enabled=true", "-Ddd.jmxfetch.refresh-beans-period=1", "-Ddatadog.slf4j.simpleLogger.defaultLogLevel=off", "-Djava.util.logging.manager=jvmbootstraptest.MissingLogManager"] as String[]
|
||||||
, "" as String[]
|
, "" as String[]
|
||||||
, [:]
|
, [:]
|
||||||
, true) == 0
|
, true) == 0
|
||||||
|
@ -62,7 +43,7 @@ class CustomLogManagerTest extends Specification {
|
||||||
def "jmxfetch startup delayed with tracer custom log manager setting"() {
|
def "jmxfetch startup delayed with tracer custom log manager setting"() {
|
||||||
expect:
|
expect:
|
||||||
IntegrationTestUtils.runOnSeparateJvm(LogManagerSetter.getName()
|
IntegrationTestUtils.runOnSeparateJvm(LogManagerSetter.getName()
|
||||||
, [agentArg, "-Ddd.jmxfetch.enabled=true", "-Ddd.jmxfetch.refresh-beans-period=1", "-Ddatadog.slf4j.simpleLogger.defaultLogLevel=off", "-Ddd.app.customlogmanager=true"] as String[]
|
, ["-Ddd.jmxfetch.enabled=true", "-Ddd.jmxfetch.refresh-beans-period=1", "-Ddatadog.slf4j.simpleLogger.defaultLogLevel=off", "-Ddd.app.customlogmanager=true"] as String[]
|
||||||
, "" as String[]
|
, "" as String[]
|
||||||
, [:]
|
, [:]
|
||||||
, true) == 0
|
, true) == 0
|
||||||
|
@ -71,7 +52,7 @@ class CustomLogManagerTest extends Specification {
|
||||||
def "jmxfetch startup delayed with JBOSS_HOME environment variable"() {
|
def "jmxfetch startup delayed with JBOSS_HOME environment variable"() {
|
||||||
expect:
|
expect:
|
||||||
IntegrationTestUtils.runOnSeparateJvm(LogManagerSetter.getName()
|
IntegrationTestUtils.runOnSeparateJvm(LogManagerSetter.getName()
|
||||||
, [agentArg, "-Ddd.jmxfetch.enabled=true", "-Ddd.jmxfetch.refresh-beans-period=1", "-Ddatadog.slf4j.simpleLogger.defaultLogLevel=off", "-Ddd.app.customlogmanager=true"] as String[]
|
, ["-Ddd.jmxfetch.enabled=true", "-Ddd.jmxfetch.refresh-beans-period=1", "-Ddatadog.slf4j.simpleLogger.defaultLogLevel=off", "-Ddd.app.customlogmanager=true"] as String[]
|
||||||
, "" as String[]
|
, "" as String[]
|
||||||
, ["JBOSS_HOME": "/"]
|
, ["JBOSS_HOME": "/"]
|
||||||
, true) == 0
|
, true) == 0
|
||||||
|
@ -80,7 +61,7 @@ class CustomLogManagerTest extends Specification {
|
||||||
def "jmxfetch startup in premain forced by customlogmanager=false"() {
|
def "jmxfetch startup in premain forced by customlogmanager=false"() {
|
||||||
expect:
|
expect:
|
||||||
IntegrationTestUtils.runOnSeparateJvm(LogManagerSetter.getName()
|
IntegrationTestUtils.runOnSeparateJvm(LogManagerSetter.getName()
|
||||||
, [agentArg, "-Ddd.jmxfetch.enabled=true", "-Ddd.jmxfetch.refresh-beans-period=1", "-Ddatadog.slf4j.simpleLogger.defaultLogLevel=off", "-Ddd.app.customlogmanager=false", "-Djava.util.logging.manager=jvmbootstraptest.CustomLogManager"] as String[]
|
, ["-Ddd.jmxfetch.enabled=true", "-Ddd.jmxfetch.refresh-beans-period=1", "-Ddatadog.slf4j.simpleLogger.defaultLogLevel=off", "-Ddd.app.customlogmanager=false", "-Djava.util.logging.manager=jvmbootstraptest.CustomLogManager"] as String[]
|
||||||
, "" as String[]
|
, "" as String[]
|
||||||
, ["JBOSS_HOME": "/"]
|
, ["JBOSS_HOME": "/"]
|
||||||
, true) == 0
|
, true) == 0
|
||||||
|
|
|
@ -190,16 +190,29 @@ public class IntegrationTestUtils {
|
||||||
final Map<String, String> envVars,
|
final Map<String, String> envVars,
|
||||||
final boolean printOutputStreams)
|
final boolean printOutputStreams)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
final String separator = System.getProperty("file.separator");
|
final String separator = System.getProperty("file.separator");
|
||||||
final String classpath = System.getProperty("java.class.path");
|
final String agentJar = System.getProperty("agent.jar.to.forward");
|
||||||
|
|
||||||
|
if (agentJar == null) {
|
||||||
|
throw new RuntimeException("agent.jar.to.forward property must be set");
|
||||||
|
}
|
||||||
|
|
||||||
|
final String classpath =
|
||||||
|
agentJar + System.getProperty("path.separator") + System.getProperty("java.class.path");
|
||||||
final String path = System.getProperty("java.home") + separator + "bin" + separator + "java";
|
final String path = System.getProperty("java.home") + separator + "bin" + separator + "java";
|
||||||
|
|
||||||
|
final List<String> vmArgsList = new ArrayList<>(Arrays.asList(jvmArgs));
|
||||||
|
vmArgsList.add("-javaagent:" + agentJar);
|
||||||
|
|
||||||
final List<String> commands = new ArrayList<>();
|
final List<String> commands = new ArrayList<>();
|
||||||
commands.add(path);
|
commands.add(path);
|
||||||
commands.addAll(Arrays.asList(jvmArgs));
|
commands.addAll(vmArgsList);
|
||||||
commands.add("-cp");
|
commands.add("-cp");
|
||||||
commands.add(classpath);
|
commands.add(classpath);
|
||||||
commands.add(mainClassName);
|
commands.add(mainClassName);
|
||||||
commands.addAll(Arrays.asList(mainMethodArgs));
|
commands.addAll(Arrays.asList(mainMethodArgs));
|
||||||
|
|
||||||
final ProcessBuilder processBuilder = new ProcessBuilder(commands.toArray(new String[0]));
|
final ProcessBuilder processBuilder = new ProcessBuilder(commands.toArray(new String[0]));
|
||||||
processBuilder.environment().putAll(envVars);
|
processBuilder.environment().putAll(envVars);
|
||||||
final Process process = processBuilder.start();
|
final Process process = processBuilder.start();
|
||||||
|
|
|
@ -2,12 +2,9 @@ package jvmbootstraptest;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLClassLoader;
|
import java.net.URLClassLoader;
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
public class AgentLoadedChecker {
|
public class AgentLoadedChecker {
|
||||||
public static void main(final String[] args) throws ClassNotFoundException {
|
public static void main(final String[] args) throws ClassNotFoundException {
|
||||||
System.out.println(Arrays.toString(args));
|
|
||||||
|
|
||||||
// Empty classloader that delegates to bootstrap
|
// Empty classloader that delegates to bootstrap
|
||||||
final URLClassLoader emptyClassLoader = new URLClassLoader(new URL[] {}, null);
|
final URLClassLoader emptyClassLoader = new URLClassLoader(new URL[] {}, null);
|
||||||
final Class agentClass = emptyClassLoader.loadClass("datadog.trace.agent.TracingAgent");
|
final Class agentClass = emptyClassLoader.loadClass("datadog.trace.agent.TracingAgent");
|
||||||
|
|
Loading…
Reference in New Issue