diff --git a/dd-java-agent/src/main/java/datadog/trace/bootstrap/AgentBootstrap.java b/dd-java-agent/src/main/java/datadog/trace/bootstrap/AgentBootstrap.java index 90f6f8279c5..ed0db2fc50a 100644 --- a/dd-java-agent/src/main/java/datadog/trace/bootstrap/AgentBootstrap.java +++ b/dd-java-agent/src/main/java/datadog/trace/bootstrap/AgentBootstrap.java @@ -291,32 +291,45 @@ static int parseJavaMajorVersion(String version) { @SuppressForbidden static boolean shouldAbortDueToOtherJavaAgents() { - // Simply considering having multiple agents + // We don't abort if either + // * We are not using SSI + // * Injection is forced + // * There is only one agent + if (!getConfig(LIB_INJECTION_ENABLED_ENV_VAR) + || getConfig(LIB_INJECTION_FORCE_SYS_PROP) + || getAgentFilesFromVMArguments().size() <= 1) { + return false; + } - if (getConfig(LIB_INJECTION_ENABLED_ENV_VAR) - && !getConfig(LIB_INJECTION_FORCE_SYS_PROP) - && getAgentFilesFromVMArguments().size() > 1) { - // Formatting agent file list, Java 7 style - StringBuilder agentFiles = new StringBuilder(); - boolean first = true; + // If there are 2 agents and one of them is for patching log4j, it's fine + if (getAgentFilesFromVMArguments().size() == 2) { for (File agentFile : getAgentFilesFromVMArguments()) { - if (first) { - first = false; - } else { - agentFiles.append(", "); + if (agentFile.getName().toLowerCase().contains("log4j")) { + return false; } - agentFiles.append('"'); - agentFiles.append(agentFile.getAbsolutePath()); - agentFiles.append('"'); } - System.err.println( - "Info: multiple JVM agents detected, found " - + agentFiles - + ". Loading multiple APM/Tracing agent is not a recommended or supported configuration." - + "Please set the environment variable DD_INJECT_FORCE or the system property dd.inject.force to TRUE to load Datadog APM/Tracing agent."); - return true; } - return false; + + // Simply considering having multiple agents + // Formatting agent file list, Java 7 style + StringBuilder agentFiles = new StringBuilder(); + boolean first = true; + for (File agentFile : getAgentFilesFromVMArguments()) { + if (first) { + first = false; + } else { + agentFiles.append(", "); + } + agentFiles.append('"'); + agentFiles.append(agentFile.getAbsolutePath()); + agentFiles.append('"'); + } + System.err.println( + "Info: multiple JVM agents detected, found " + + agentFiles + + ". Loading multiple APM/Tracing agent is not a recommended or supported configuration." + + "Please set the environment variable DD_INJECT_FORCE or the system property dd.inject.force to TRUE to load Datadog APM/Tracing agent."); + return true; } public static void main(final String[] args) { diff --git a/dd-smoke-tests/lib-injection/src/test/groovy/datadog/smoketest/MultipleAgentGuardrailsTest.groovy b/dd-smoke-tests/lib-injection/src/test/groovy/datadog/smoketest/MultipleAgentGuardrailsTest.groovy index b644a87296a..c0e9350e468 100644 --- a/dd-smoke-tests/lib-injection/src/test/groovy/datadog/smoketest/MultipleAgentGuardrailsTest.groovy +++ b/dd-smoke-tests/lib-injection/src/test/groovy/datadog/smoketest/MultipleAgentGuardrailsTest.groovy @@ -1,16 +1,21 @@ package datadog.smoketest +import java.nio.file.Files +import java.nio.file.Paths + +import static java.nio.file.StandardCopyOption.REPLACE_EXISTING + abstract class MultipleAgentGuardrailsTest extends AbstractSmokeTest { static final String LIB_INJECTION_ENABLED_FLAG = 'DD_INJECTION_ENABLED' static final String LIB_INJECTION_FORCE_FLAG = 'DD_INJECT_FORCE' @Override ProcessBuilder createProcessBuilder() { - def jarPath = System.getProperty("datadog.smoketest.shadowJar.path") + def jarPath = System.getProperty('datadog.smoketest.shadowJar.path') def command = [] command+= javaPath() command.addAll(defaultJavaProperties) - command+= "-javaagent:${jarPath}" as String // Happen the fake agent too + command+= "-javaagent:${getFakeAgentPath(jarPath)}" as String // Happen the fake agent too command+= '-Ddd.trace.otel.enabled=true' command+= '-jar' command+= jarPath @@ -25,9 +30,23 @@ abstract class MultipleAgentGuardrailsTest extends AbstractSmokeTest { processBuilder.directory(new File(buildDirectory)) } + String getFakeAgentPath(String jarPath) { + if (overriddenFakeAgentFilename() != null) { + def buildFakeAgentPath = Paths.get(jarPath) + def overriddenFakeAgentPath = buildFakeAgentPath.getParent().resolve(overriddenFakeAgentFilename()) + Files.copy(buildFakeAgentPath, overriddenFakeAgentPath, REPLACE_EXISTING) + jarPath = overriddenFakeAgentPath.toString() + } + return jarPath + } + abstract boolean isLibInjectionEnabled() abstract boolean isLibInjectionForced() + String overriddenFakeAgentFilename() { + return null + } + boolean isExpectingTrace() { return !isLibInjectionEnabled() || isLibInjectionForced() } @@ -78,3 +97,26 @@ class LibInjectionForcedTest extends MultipleAgentGuardrailsTest { return true } } + +// Test that injection still works if we have to agent if one of them is the aws emr log4j patcher +class LibsInjectionLog4jExclusionTest extends MultipleAgentGuardrailsTest { + @Override + boolean isLibInjectionEnabled() { + return true + } + + @Override + boolean isLibInjectionForced() { + return false + } + + @Override + String overriddenFakeAgentFilename() { + return 'Log4jHotPatchFat.jar' + } + + @Override + boolean isExpectingTrace() { + return true + } +}