Integration test to ensure custom log managers can be set
MODIFY
dd-java-agent-ittests/dd-java-agent-ittests.gradle
dd-java-agent-ittests/dd-java-agent-ittests.gradle
@@ -54,3 +54,16 @@ tasks.withType(Test) {
parent.subprojects.collect { it.tasks.withType(Test) } each {
test.shouldRunAfter it
}
+
+task jvmStartupTest(type: Exec) {
+ dependsOn project(':dd-java-agent').shadowJar
+ dependsOn project(':dd-java-agent-ittests').compileTestJava
+ workingDir "$buildDir/classes/java/test"
+ commandLine "java"
+ args "-javaagent:${project(':dd-java-agent').tasks.shadowJar.archivePath}"
+ args "-Ddd.jmxfetch.enabled=true"
+ args "-Djava.system.class.loader=jvmbootstraptest.CustomClassloader"
+ args "jvmbootstraptest.JvmBootstrapTest"
+ description = "Runs JVM Bootstrapping tests"
+}
+test.finalizedBy 'jvmStartupTest'

ADD
dd-java-agent-ittests/src/test/java/jvmbootstraptest/CustomClassloader.java
+package jvmbootstraptest;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+
+public class CustomClassloader extends URLClassLoader {
+ static {
+ ClassLoader.registerAsParallelCapable();
+ }
+
+ public CustomClassloader(ClassLoader parent) {
+ this(new URL[0], parent);
+ }
+
+ public CustomClassloader(URL[] urls, ClassLoader parent) {
+ super(urls, parent);
+ }
+
+ @Override
+ public Object getClassLoadingLock(String className) {
+ return super.getClassLoadingLock(className);
+ }
+}

ADD
dd-java-agent-ittests/src/test/java/jvmbootstraptest/CustomLogManager.java
+package jvmbootstraptest;
+
+import java.util.logging.LogManager;
+
+public class CustomLogManager extends LogManager {}

ADD
dd-java-agent-ittests/src/test/java/jvmbootstraptest/JvmBootstrapTest.java
+package jvmbootstraptest;
+
+import java.util.logging.LogManager;
+
+public class JvmBootstrapTest {
+ /**
+ * See gradle task `jvmStartupTest`. This runs a paired-down jvm in order to assert that the
+ * javaagent initializes correctly without interference by gradle/junit/spock.
+ */
+ public static void main(String... args) throws Exception {
+ // Sleeping here to give the agent more time to initialize and potentially do something wrong.
+ // This is an attempt to be as mean to the agent as possible.
+ Thread.sleep(2000);
+ final CustomClassloader systemLoader = (CustomClassloader) ClassLoader.getSystemClassLoader();
+
+ // sync around the classloading lock to guarantee datadog threads won't be able to see the
+ // logging manager property if they're currently initializing the logging manager.
+ synchronized (systemLoader.getClassLoadingLock("java.util.logging.LogManager")) {
+ System.setProperty("java.util.logging.manager", CustomLogManager.class.getName());
+ customAssert(
+ LogManager.getLogManager().getClass() == CustomLogManager.class,
+ true,
+ "Javaagent should not prevent setting a custom log manager");
+ }
+ }
+
+ private static void customAssert(boolean got, boolean expected, String assertionMessage) {
+ if (got != expected) {
+ throw new RuntimeException("Assertion failed: " + assertionMessage);
+ }
+ }
+}

Integration test to ensure custom log managers can be set