From a9d44005b362045881bd0b436af0b1eb1a428968 Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Mon, 10 Mar 2025 14:57:24 -0400 Subject: [PATCH 01/98] Abstract away getVMArgumentsThroughReflection into a VMArgsCache class --- .../trace/bootstrap/AgentBootstrap.java | 57 +----------- .../config/provider/VMArgsCache.java | 93 +++++++++++++++++++ 2 files changed, 95 insertions(+), 55 deletions(-) create mode 100644 internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java 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 095db7acc8c..d5d78f3b1b0 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 @@ -2,6 +2,7 @@ import static java.nio.charset.StandardCharsets.UTF_8; +import datadog.trace.bootstrap.config.provider.VMArgsCache; import de.thetaphi.forbiddenapis.SuppressForbidden; import java.io.BufferedReader; import java.io.File; @@ -9,15 +10,12 @@ import java.io.InputStreamReader; import java.io.PrintStream; import java.lang.instrument.Instrumentation; -import java.lang.management.ManagementFactory; -import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.security.CodeSource; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.IdentityHashMap; import java.util.List; @@ -383,7 +381,7 @@ private static List getAgentFilesFromVMArguments() { // - On IBM-based JDKs since at least 1.7 // This prevents custom log managers from working correctly // Use reflection to bypass the loading of the class~ - for (final String argument : getVMArgumentsThroughReflection()) { + for (final String argument : VMArgsCache.getVMArguments()) { if (argument.startsWith(JAVA_AGENT_ARGUMENT)) { int index = argument.indexOf('=', JAVA_AGENT_ARGUMENT.length()); String agentPathname = @@ -424,57 +422,6 @@ private static File getAgentFileUsingClassLoaderLookup() throws URISyntaxExcepti return javaagentFile; } - @SuppressForbidden - private static List getVMArgumentsThroughReflection() { - // Try Oracle-based - // IBM Semeru Runtime 1.8.0_345-b01 will throw UnsatisfiedLinkError here. - try { - final Class managementFactoryHelperClass = - Class.forName("sun.management.ManagementFactoryHelper"); - - final Class vmManagementClass = Class.forName("sun.management.VMManagement"); - - Object vmManagement; - - try { - vmManagement = - managementFactoryHelperClass.getDeclaredMethod("getVMManagement").invoke(null); - } catch (final NoSuchMethodException e) { - // Older vm before getVMManagement() existed - final Field field = managementFactoryHelperClass.getDeclaredField("jvm"); - field.setAccessible(true); - vmManagement = field.get(null); - field.setAccessible(false); - } - - //noinspection unchecked - return (List) vmManagementClass.getMethod("getVmArguments").invoke(vmManagement); - } catch (final ReflectiveOperationException | UnsatisfiedLinkError ignored) { - // Ignored exception - } - - // Try IBM-based. - try { - final Class VMClass = Class.forName("com.ibm.oti.vm.VM"); - final String[] argArray = (String[]) VMClass.getMethod("getVMArgs").invoke(null); - return Arrays.asList(argArray); - } catch (final ReflectiveOperationException ignored) { - // Ignored exception - } - - // Fallback to default - try { - System.err.println( - "WARNING: Unable to get VM args through reflection. A custom java.util.logging.LogManager may not work correctly"); - return ManagementFactory.getRuntimeMXBean().getInputArguments(); - } catch (final Throwable t) { - // Throws InvocationTargetException on modularized applications - // with non-opened java.management module - System.err.println("WARNING: Unable to get VM args using managed beans"); - } - return Collections.emptyList(); - } - private static void checkJarManifestMainClassIsThis(final URL jarUrl) throws IOException { final URL manifestUrl = new URL("jar:" + jarUrl + "!/META-INF/MANIFEST.MF"); final String mainClassLine = "Main-Class: " + thisClass.getCanonicalName(); diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java new file mode 100644 index 00000000000..3ad906dd3eb --- /dev/null +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java @@ -0,0 +1,93 @@ +package datadog.trace.bootstrap.config.provider; + +import de.thetaphi.forbiddenapis.SuppressForbidden; +import java.lang.management.ManagementFactory; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class VMArgsCache { + private static final class Singleton { + private static VMArgsCache INSTANCE = null; + } + + // TODO: Make this a smarter data structure + private final List args; + private boolean initialized; + + public VMArgsCache(List args) { + this.args = args; + } + + public List getArgs() { + return this.args; + } + + public boolean contains(String argument) { + for (String arg : this.args) { + if (arg.equals(argument)) { + return true; + } + } + return false; + } + + @SuppressForbidden + public static List getVMArguments() { + if (Singleton.INSTANCE == null) { + Singleton.INSTANCE = new VMArgsCache(getVMArgumentsThroughReflection()); + } + return Singleton.INSTANCE.getArgs(); + } + + private static List getVMArgumentsThroughReflection() { + // Try Oracle-based + // IBM Semeru Runtime 1.8.0_345-b01 will throw UnsatisfiedLinkError here. + try { + final Class managementFactoryHelperClass = + Class.forName("sun.management.ManagementFactoryHelper"); + + final Class vmManagementClass = Class.forName("sun.management.VMManagement"); + + Object vmManagement; + + try { + vmManagement = + managementFactoryHelperClass.getDeclaredMethod("getVMManagement").invoke(null); + } catch (final NoSuchMethodException e) { + // Older vm before getVMManagement() existed + final Field field = managementFactoryHelperClass.getDeclaredField("jvm"); + field.setAccessible(true); + vmManagement = field.get(null); + field.setAccessible(false); + } + + //noinspection unchecked + return (List) vmManagementClass.getMethod("getVmArguments").invoke(vmManagement); + } catch (final ReflectiveOperationException | UnsatisfiedLinkError ignored) { + // Ignored exception + } + + // Try IBM-based. + try { + final Class VMClass = Class.forName("com.ibm.oti.vm.VM"); + final String[] argArray = (String[]) VMClass.getMethod("getVMArgs").invoke(null); + return Arrays.asList(argArray); + } catch (final ReflectiveOperationException ignored) { + // Ignored exception + } + + // Fallback to default + try { + System.err.println( + "WARNING: Unable to get VM args through reflection. A custom java.util.logging.LogManager may not work correctly"); + return ManagementFactory.getRuntimeMXBean().getInputArguments(); + } catch (final Throwable t) { + // Throws InvocationTargetException on modularized applications + // with non-opened java.management module + System.err.println("WARNING: Unable to get VM args using managed beans"); + } + return Collections.emptyList(); + } +} From d688313da80638080f10ab79dad3041f7f5f17f9 Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Tue, 11 Mar 2025 16:27:28 -0400 Subject: [PATCH 02/98] Change underlying data structure of VMArgsCache to HashSet --- .../config/provider/VMArgsCache.java | 67 ++++++++++++++----- 1 file changed, 51 insertions(+), 16 deletions(-) diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java index 3ad906dd3eb..7011570a53c 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java @@ -1,47 +1,54 @@ package datadog.trace.bootstrap.config.provider; import de.thetaphi.forbiddenapis.SuppressForbidden; +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; import java.lang.management.ManagementFactory; import java.lang.reflect.Field; import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; import java.util.List; public class VMArgsCache { private static final class Singleton { - private static VMArgsCache INSTANCE = null; + private static final VMArgsCache INSTANCE = new VMArgsCache(getVMArgumentsThroughReflection()); } - // TODO: Make this a smarter data structure - private final List args; - private boolean initialized; + private final HashSet args; public VMArgsCache(List args) { - this.args = args; + this.args = new HashSet<>(args); } - public List getArgs() { + private HashSet getArgs() { return this.args; } public boolean contains(String argument) { - for (String arg : this.args) { - if (arg.equals(argument)) { - return true; - } - } - return false; + return this.args.contains(argument); } @SuppressForbidden - public static List getVMArguments() { - if (Singleton.INSTANCE == null) { - Singleton.INSTANCE = new VMArgsCache(getVMArgumentsThroughReflection()); - } + public static HashSet getVMArguments() { return Singleton.INSTANCE.getArgs(); } private static List getVMArgumentsThroughReflection() { + // TODO: equals, or contains? + if (System.getProperty("os.name").equalsIgnoreCase("linux")) { + // Get the current process PID from /proc/self/status + try { + String pid = getPidFromProcStatus(); + if (pid != null) { + // Get the JVM arguments from /proc/[pid]/cmdline + return getJvmArgsFromProcCmdline(pid); + } + } catch (IOException e) { + // ignore exception, try other methods + } + } // Try Oracle-based // IBM Semeru Runtime 1.8.0_345-b01 will throw UnsatisfiedLinkError here. try { @@ -90,4 +97,32 @@ private static List getVMArgumentsThroughReflection() { } return Collections.emptyList(); } + + // Helper methods for getting process information from linux proc dir + private static String getPidFromProcStatus() throws IOException { + String pid = null; + // Read /proc/self/status to find the current process's PID + try (BufferedReader pidReader = new BufferedReader(new FileReader("/proc/self/status"))) { + String line; + while ((line = pidReader.readLine()) != null) { + if (line.startsWith("Pid:")) { + pid = line.split(":")[1].trim(); + break; + } + } + } + return pid; + } + + private static List getJvmArgsFromProcCmdline(String pid) throws IOException { + // Read /proc/[pid]/cmdline to get JVM arguments + BufferedReader argsReader = new BufferedReader(new FileReader("/proc/" + pid + "/cmdline")); + String cmdLine = argsReader.readLine(); + if (cmdLine != null) { + // Return JVM arguments as a list of strings split by null characters + return Arrays.asList(cmdLine.split("\0")); + } else { + return null; + } + } } From d6344a8a8ee9cd82b722ed94a6d9405a444703b4 Mon Sep 17 00:00:00 2001 From: Mikayla Toffler <46911781+mtoffl01@users.noreply.github.com> Date: Tue, 11 Mar 2025 16:32:12 -0400 Subject: [PATCH 03/98] Update internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java Co-authored-by: datadog-datadog-prod-us1[bot] <88084959+datadog-datadog-prod-us1[bot]@users.noreply.github.com> --- .../datadog/trace/bootstrap/config/provider/VMArgsCache.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java index 7011570a53c..60bd4543b33 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java @@ -16,7 +16,7 @@ private static final class Singleton { private static final VMArgsCache INSTANCE = new VMArgsCache(getVMArgumentsThroughReflection()); } - private final HashSet args; + private final Set args; public VMArgsCache(List args) { this.args = new HashSet<>(args); From 6aba3f86159e44529a326e4eb85687c4bc8cf5fc Mon Sep 17 00:00:00 2001 From: Mikayla Toffler <46911781+mtoffl01@users.noreply.github.com> Date: Tue, 11 Mar 2025 16:32:19 -0400 Subject: [PATCH 04/98] Update internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java Co-authored-by: datadog-datadog-prod-us1[bot] <88084959+datadog-datadog-prod-us1[bot]@users.noreply.github.com> --- .../datadog/trace/bootstrap/config/provider/VMArgsCache.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java index 60bd4543b33..d040430ead2 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java @@ -22,7 +22,7 @@ public VMArgsCache(List args) { this.args = new HashSet<>(args); } - private HashSet getArgs() { + private Set getArgs() { return this.args; } From 8afbec1143f524a1cbc2ecf5d07e8b8817b8cc33 Mon Sep 17 00:00:00 2001 From: Mikayla Toffler <46911781+mtoffl01@users.noreply.github.com> Date: Tue, 11 Mar 2025 16:32:29 -0400 Subject: [PATCH 05/98] Update internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java Co-authored-by: datadog-datadog-prod-us1[bot] <88084959+datadog-datadog-prod-us1[bot]@users.noreply.github.com> --- .../datadog/trace/bootstrap/config/provider/VMArgsCache.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java index d040430ead2..676f43a25bb 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java @@ -31,7 +31,7 @@ public boolean contains(String argument) { } @SuppressForbidden - public static HashSet getVMArguments() { + public static Set getVMArguments() { return Singleton.INSTANCE.getArgs(); } From d807b02655172e6ad24fcb8b638e33400a9c2056 Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Wed, 12 Mar 2025 13:15:31 -0400 Subject: [PATCH 06/98] Clean up for initial review --- .../datadog/trace/bootstrap/AgentBootstrap.java | 2 +- .../bootstrap/config/provider/VMArgsCache.java | 16 +++++----------- 2 files changed, 6 insertions(+), 12 deletions(-) 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 d5d78f3b1b0..0ae3874dd77 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 @@ -381,7 +381,7 @@ private static List getAgentFilesFromVMArguments() { // - On IBM-based JDKs since at least 1.7 // This prevents custom log managers from working correctly // Use reflection to bypass the loading of the class~ - for (final String argument : VMArgsCache.getVMArguments()) { + for (final String argument : VMArgsCache.ARGS.getJvmArgs()) { if (argument.startsWith(JAVA_AGENT_ARGUMENT)) { int index = argument.indexOf('=', JAVA_AGENT_ARGUMENT.length()); String agentPathname = diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java index 7011570a53c..cac246e31d6 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java @@ -1,6 +1,5 @@ package datadog.trace.bootstrap.config.provider; -import de.thetaphi.forbiddenapis.SuppressForbidden; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; @@ -11,10 +10,9 @@ import java.util.HashSet; import java.util.List; +/** VMArgsCache stores JVM Arguments applied to the current process */ public class VMArgsCache { - private static final class Singleton { - private static final VMArgsCache INSTANCE = new VMArgsCache(getVMArgumentsThroughReflection()); - } + public static final VMArgsCache ARGS = new VMArgsCache(initJvmArgs()); private final HashSet args; @@ -22,7 +20,7 @@ public VMArgsCache(List args) { this.args = new HashSet<>(args); } - private HashSet getArgs() { + public HashSet getJvmArgs() { return this.args; } @@ -30,12 +28,8 @@ public boolean contains(String argument) { return this.args.contains(argument); } - @SuppressForbidden - public static HashSet getVMArguments() { - return Singleton.INSTANCE.getArgs(); - } - - private static List getVMArgumentsThroughReflection() { + private static List initJvmArgs() { + // If linux OS, use procfs // TODO: equals, or contains? if (System.getProperty("os.name").equalsIgnoreCase("linux")) { // Get the current process PID from /proc/self/status From 7ce49534699722d0186d1df21ab45769ac4fcbc0 Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Fri, 14 Mar 2025 11:48:00 -0400 Subject: [PATCH 07/98] move VMArgsCache to components/cli --- components/cli/build.gradle.kts | 9 +++++ .../src/main/java/datadog.cli/CLIHelper.java | 36 +++++-------------- dd-java-agent/build.gradle | 1 + .../trace/bootstrap/AgentBootstrap.java | 4 +-- settings.gradle | 1 + 5 files changed, 21 insertions(+), 30 deletions(-) create mode 100644 components/cli/build.gradle.kts rename internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java => components/cli/src/main/java/datadog.cli/CLIHelper.java (73%) diff --git a/components/cli/build.gradle.kts b/components/cli/build.gradle.kts new file mode 100644 index 00000000000..4dca7fc3036 --- /dev/null +++ b/components/cli/build.gradle.kts @@ -0,0 +1,9 @@ +plugins { + id("me.champeau.jmh") +} + +apply(from = "$rootDir/gradle/java.gradle") + +jmh { + version = "1.28" +} diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java b/components/cli/src/main/java/datadog.cli/CLIHelper.java similarity index 73% rename from internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java rename to components/cli/src/main/java/datadog.cli/CLIHelper.java index cac246e31d6..e06250df3a4 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/VMArgsCache.java +++ b/components/cli/src/main/java/datadog.cli/CLIHelper.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap.config.provider; +package datadog.cli; import java.io.BufferedReader; import java.io.FileReader; @@ -10,13 +10,12 @@ import java.util.HashSet; import java.util.List; -/** VMArgsCache stores JVM Arguments applied to the current process */ -public class VMArgsCache { - public static final VMArgsCache ARGS = new VMArgsCache(initJvmArgs()); +public class CLIHelper { + public static final CLIHelper ARGS = new CLIHelper(initJvmArgs()); private final HashSet args; - public VMArgsCache(List args) { + public CLIHelper(List args) { this.args = new HashSet<>(args); } @@ -34,11 +33,8 @@ private static List initJvmArgs() { if (System.getProperty("os.name").equalsIgnoreCase("linux")) { // Get the current process PID from /proc/self/status try { - String pid = getPidFromProcStatus(); - if (pid != null) { - // Get the JVM arguments from /proc/[pid]/cmdline - return getJvmArgsFromProcCmdline(pid); - } + // Get the JVM arguments from /proc/self/cmdline + return getJvmArgsFromProcCmdline(); } catch (IOException e) { // ignore exception, try other methods } @@ -92,25 +88,9 @@ private static List initJvmArgs() { return Collections.emptyList(); } - // Helper methods for getting process information from linux proc dir - private static String getPidFromProcStatus() throws IOException { - String pid = null; - // Read /proc/self/status to find the current process's PID - try (BufferedReader pidReader = new BufferedReader(new FileReader("/proc/self/status"))) { - String line; - while ((line = pidReader.readLine()) != null) { - if (line.startsWith("Pid:")) { - pid = line.split(":")[1].trim(); - break; - } - } - } - return pid; - } - - private static List getJvmArgsFromProcCmdline(String pid) throws IOException { + private static List getJvmArgsFromProcCmdline() throws IOException { // Read /proc/[pid]/cmdline to get JVM arguments - BufferedReader argsReader = new BufferedReader(new FileReader("/proc/" + pid + "/cmdline")); + BufferedReader argsReader = new BufferedReader(new FileReader("/proc/self/cmdline")); String cmdLine = argsReader.readLine(); if (cmdLine != null) { // Return JVM arguments as a list of strings split by null characters diff --git a/dd-java-agent/build.gradle b/dd-java-agent/build.gradle index 6528a2e3c2e..95737b79eeb 100644 --- a/dd-java-agent/build.gradle +++ b/dd-java-agent/build.gradle @@ -203,6 +203,7 @@ tasks.withType(GenerateMavenPom).configureEach { task -> dependencies { implementation project(path: ':components:json') + implementation project(path: ':components:cli') modules { module("com.squareup.okio:okio") { replacedBy("com.datadoghq.okio:okio") // embed our patched fork 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 0ae3874dd77..107a5e827d2 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 @@ -2,7 +2,7 @@ import static java.nio.charset.StandardCharsets.UTF_8; -import datadog.trace.bootstrap.config.provider.VMArgsCache; +import datadog.cli; import de.thetaphi.forbiddenapis.SuppressForbidden; import java.io.BufferedReader; import java.io.File; @@ -381,7 +381,7 @@ private static List getAgentFilesFromVMArguments() { // - On IBM-based JDKs since at least 1.7 // This prevents custom log managers from working correctly // Use reflection to bypass the loading of the class~ - for (final String argument : VMArgsCache.ARGS.getJvmArgs()) { + for (final String argument : cli.ARGS.getJvmArgs()) { if (argument.startsWith(JAVA_AGENT_ARGUMENT)) { int index = argument.indexOf('=', JAVA_AGENT_ARGUMENT.length()); String agentPathname = diff --git a/settings.gradle b/settings.gradle index 3ba7be61fe5..8dd42b9cab9 100644 --- a/settings.gradle +++ b/settings.gradle @@ -66,6 +66,7 @@ include ':dd-java-agent:agent-otel:otel-shim' include ':dd-java-agent:agent-otel:otel-tooling' include ':communication' +include ':components:cli' include ':components:context' include ':components:json' include ':telemetry' From 7a9f694eea8e0126bee1f7731f68298b4ee95107 Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Fri, 14 Mar 2025 12:06:22 -0400 Subject: [PATCH 08/98] fix datadog.cli import --- .../src/main/java/datadog/trace/bootstrap/AgentBootstrap.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 107a5e827d2..d715c1f3277 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 @@ -2,7 +2,7 @@ import static java.nio.charset.StandardCharsets.UTF_8; -import datadog.cli; +import datadog.cli.CLIHelper; import de.thetaphi.forbiddenapis.SuppressForbidden; import java.io.BufferedReader; import java.io.File; @@ -381,7 +381,7 @@ private static List getAgentFilesFromVMArguments() { // - On IBM-based JDKs since at least 1.7 // This prevents custom log managers from working correctly // Use reflection to bypass the loading of the class~ - for (final String argument : cli.ARGS.getJvmArgs()) { + for (final String argument : CLIHelper.ARGS.getJvmArgs()) { if (argument.startsWith(JAVA_AGENT_ARGUMENT)) { int index = argument.indexOf('=', JAVA_AGENT_ARGUMENT.length()); String agentPathname = From dd17ca24b359de701d892acb4695e13fad584c4e Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Fri, 14 Mar 2025 12:11:17 -0400 Subject: [PATCH 09/98] nits: remove outdated comments --- components/cli/src/main/java/datadog.cli/CLIHelper.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/components/cli/src/main/java/datadog.cli/CLIHelper.java b/components/cli/src/main/java/datadog.cli/CLIHelper.java index e06250df3a4..5befd50f71f 100644 --- a/components/cli/src/main/java/datadog.cli/CLIHelper.java +++ b/components/cli/src/main/java/datadog.cli/CLIHelper.java @@ -31,7 +31,6 @@ private static List initJvmArgs() { // If linux OS, use procfs // TODO: equals, or contains? if (System.getProperty("os.name").equalsIgnoreCase("linux")) { - // Get the current process PID from /proc/self/status try { // Get the JVM arguments from /proc/self/cmdline return getJvmArgsFromProcCmdline(); @@ -89,7 +88,6 @@ private static List initJvmArgs() { } private static List getJvmArgsFromProcCmdline() throws IOException { - // Read /proc/[pid]/cmdline to get JVM arguments BufferedReader argsReader = new BufferedReader(new FileReader("/proc/self/cmdline")); String cmdLine = argsReader.readLine(); if (cmdLine != null) { From 2798bed48a728273d1d027b737431a22aefd8b49 Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Mon, 17 Mar 2025 10:32:44 -0400 Subject: [PATCH 10/98] annotate initJvmArgs with @SuppressForbidden to allow Class.forName() usage --- components/cli/src/main/java/datadog.cli/CLIHelper.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/cli/src/main/java/datadog.cli/CLIHelper.java b/components/cli/src/main/java/datadog.cli/CLIHelper.java index 5befd50f71f..4fdfcc92e7d 100644 --- a/components/cli/src/main/java/datadog.cli/CLIHelper.java +++ b/components/cli/src/main/java/datadog.cli/CLIHelper.java @@ -1,5 +1,6 @@ package datadog.cli; +import de.thetaphi.forbiddenapis.SuppressForbidden; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; @@ -27,6 +28,7 @@ public boolean contains(String argument) { return this.args.contains(argument); } + @SuppressForbidden private static List initJvmArgs() { // If linux OS, use procfs // TODO: equals, or contains? From f5d89a3279b61d1f1924f3369333d6486c726b9a Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Fri, 7 Mar 2025 12:44:50 -0500 Subject: [PATCH 11/98] initial implementation using snakeyaml + StableConfigYaml for parsing; passing tests --- components/yaml/build.gradle.kts | 14 ++ .../main/java/datadog.yaml/YamlParser.java | 19 ++ internal-api/build.gradle | 1 + .../config/provider/ConfigurationMap.java | 18 ++ .../config/provider/StableConfigParser.java | 117 +++++----- .../config/provider/StableConfigSource.java | 8 +- .../provider/StableConfigYaml/Rule.java | 26 +++ .../provider/StableConfigYaml/Selector.java | 43 ++++ .../StableConfigYaml/StableConfigYaml.java | 35 +++ .../provider/StableConfigParserTest.groovy | 218 +++++++++++------- settings.gradle | 1 + 11 files changed, 351 insertions(+), 149 deletions(-) create mode 100644 components/yaml/build.gradle.kts create mode 100644 components/yaml/src/main/java/datadog.yaml/YamlParser.java create mode 100644 internal-api/src/main/java/datadog/trace/bootstrap/config/provider/ConfigurationMap.java create mode 100644 internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/Rule.java create mode 100644 internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/Selector.java create mode 100644 internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/StableConfigYaml.java diff --git a/components/yaml/build.gradle.kts b/components/yaml/build.gradle.kts new file mode 100644 index 00000000000..5acc8dd4cc2 --- /dev/null +++ b/components/yaml/build.gradle.kts @@ -0,0 +1,14 @@ +plugins { + id("me.champeau.jmh") +} + +apply(from = "$rootDir/gradle/java.gradle") + +jmh { + version = "1.28" +} + +// https://repo1.maven.org/maven2/org/yaml/snakeyaml/2.4/snakeyaml-2.4.pom +dependencies { + implementation("org.yaml", "snakeyaml", "2.4") +} diff --git a/components/yaml/src/main/java/datadog.yaml/YamlParser.java b/components/yaml/src/main/java/datadog.yaml/YamlParser.java new file mode 100644 index 00000000000..01aa7216fc1 --- /dev/null +++ b/components/yaml/src/main/java/datadog.yaml/YamlParser.java @@ -0,0 +1,19 @@ +package datadog.yaml; + +import java.io.FileInputStream; +import java.io.IOException; +import org.yaml.snakeyaml.Yaml; + +public class YamlParser { + // Supports clazz == null for default yaml parsing + public static T parse(String filePath, Class clazz) throws IOException { + Yaml yaml = new Yaml(); + try (FileInputStream fis = new FileInputStream(filePath)) { + if (clazz == null) { + return yaml.load(fis); + } else { + return yaml.loadAs(fis, clazz); + } + } + } +} diff --git a/internal-api/build.gradle b/internal-api/build.gradle index 4731d37a255..e9fff4e2686 100644 --- a/internal-api/build.gradle +++ b/internal-api/build.gradle @@ -232,6 +232,7 @@ dependencies { api project(':dd-trace-api') api libs.slf4j api project(':components:context') + api project(':components:yaml') api project(":utils:time-utils") // has to be loaded by system classloader: diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/ConfigurationMap.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/ConfigurationMap.java new file mode 100644 index 00000000000..315e8a306d3 --- /dev/null +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/ConfigurationMap.java @@ -0,0 +1,18 @@ +package datadog.trace.bootstrap.config.provider; + +import java.util.HashMap; + +public class ConfigurationMap extends HashMap {} + +class ConfigurationValue { + private final String value; + + public ConfigurationValue(String value) { + this.value = value; + } + + @Override + public String toString() { + return value; + } +} diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java index bb651e11588..1e943c6dc58 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java @@ -1,77 +1,74 @@ package datadog.trace.bootstrap.config.provider; -import java.io.File; +import datadog.trace.bootstrap.config.provider.StableConfigYaml.Rule; +import datadog.trace.bootstrap.config.provider.StableConfigYaml.Selector; +import datadog.trace.bootstrap.config.provider.StableConfigYaml.StableConfigYaml; +import datadog.yaml.YamlParser; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; import java.util.HashMap; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Stream; +import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class StableConfigParser { private static final Logger log = LoggerFactory.getLogger(StableConfigParser.class); - // Match config_id: - private static final Pattern idPattern = Pattern.compile("^config_id\\s*:(.*)$"); - // Match 'apm_configuration_default:' - private static final Pattern apmConfigPattern = Pattern.compile("^apm_configuration_default:$"); - // Match indented (2 spaces) key-value pairs, either with double quotes or without - private static final Pattern keyValPattern = - Pattern.compile("^\\s{2}([^:]+):\\s*(\"[^\"]*\"|[^\"\\n]*)$");; public static StableConfigSource.StableConfig parse(String filePath) throws IOException { - File file = new File(filePath); - if (!file.exists()) { - log.debug("Stable configuration file not available at specified path: {}", file); - return StableConfigSource.StableConfig.EMPTY; - } - Map configMap = new HashMap<>(); - String[] configId = new String[1]; - try (Stream lines = Files.lines(Paths.get(filePath))) { - int apmConfigNotFound = -1, apmConfigStarted = 0, apmConfigComplete = 1; - int[] apmConfigFound = {apmConfigNotFound}; - lines.forEach( - line -> { - Matcher matcher = idPattern.matcher(line); - if (matcher.find()) { - // Do not allow duplicate config_id keys - if (configId[0] != null) { - throw new RuntimeException("Duplicate config_id keys found; file may be malformed"); - } - configId[0] = trimQuotes(matcher.group(1).trim()); - return; // go to next line - } - // TODO: Do not allow duplicate apm_configuration_default keys; and/or return early once - // apmConfigFound[0] == apmConfigComplete - if (apmConfigFound[0] == apmConfigNotFound - && apmConfigPattern.matcher(line).matches()) { - apmConfigFound[0] = apmConfigStarted; - return; // go to next line + try { + StableConfigYaml data = YamlParser.parse(filePath, StableConfigYaml.class); + ConfigurationMap configMap = data.getApm_configuration_default(); + // TODO: Support multiple sets of rules + configs. + List rules = data.getApm_configuration_rules(); + if (rules != null) { + for (Rule rule : rules) { + List selectors = rule.getSelectors(); + boolean match = true; + for (Selector selector : selectors) { + if (!selectorMatch( + selector.getOrigin(), + selector.getMatches(), + selector.getOperator(), + selector.getKey())) { + match = false; + break; } - if (apmConfigFound[0] == apmConfigStarted) { - Matcher keyValueMatcher = keyValPattern.matcher(line); - if (keyValueMatcher.matches()) { - configMap.put( - keyValueMatcher.group(1).trim(), - trimQuotes(keyValueMatcher.group(2).trim())); // Store key-value pair in map - } else { - // If we encounter a non-indented or non-key-value line, stop processing - apmConfigFound[0] = apmConfigComplete; - } - } - }); - return new StableConfigSource.StableConfig(configId[0], configMap); + } + // Use the first selector that matches; return early + if (match) { + configMap.putAll(rule.getConfiguration()); + return new StableConfigSource.StableConfig( + data.getConfig_id(), new HashMap<>(configMap)); + } + } + } + // If configs were found in apm_configuration_default, use them + if (!configMap.isEmpty()) { + return new StableConfigSource.StableConfig(data.getConfig_id(), new HashMap<>(configMap)); + } + } catch (IOException e) { + // TODO: Update this log from "stable configuration" to the official name of the feature, once + // determined + log.debug( + "Stable configuration file either not found or not readable at filepath {}", filePath); } + return StableConfigSource.StableConfig.EMPTY; } - private static String trimQuotes(String value) { - if (value.length() > 1 && (value.startsWith("'") && value.endsWith("'")) - || (value.startsWith("\"") && value.endsWith("\""))) { - return value.substring(1, value.length() - 1); - } - return value; + // TODO: Create strict types for origin and operator values + private static boolean selectorMatch( + String origin, List matches, String operator, String key) { + // if(origin.equals("language")) { + // List matchesList = Arrays.asList(matches); + // return matchesList.contains("Java") || matchesList.contains("java") && + // operator.equals("equals"); + // } + // else if(origin.equals("tags")) { + // + // } else if(origin.equals("environment_variables")) { + // + // } else if(origin.equals("process_arguments")) { + // + // } + return true; } } diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java index df4603e891f..ff30321c5ae 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java @@ -61,16 +61,18 @@ public String getConfigId() { public static class StableConfig { public static final StableConfig EMPTY = new StableConfig(null, Collections.emptyMap()); - private final Map apmConfiguration; + private final Map apmConfiguration; private final String configId; - StableConfig(String configId, Map configMap) { + public StableConfig(String configId, Map configMap) { this.configId = configId; this.apmConfiguration = configMap; } public String get(String key) { - return this.apmConfiguration.get(key); + Object value = this.apmConfiguration.get(key); + // TODO: Handle this more safely, e.g. for an array + return (value != null) ? value.toString() : null; } public Set getKeys() { diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/Rule.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/Rule.java new file mode 100644 index 00000000000..52ac972c07b --- /dev/null +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/Rule.java @@ -0,0 +1,26 @@ +package datadog.trace.bootstrap.config.provider.StableConfigYaml; + +import datadog.trace.bootstrap.config.provider.ConfigurationMap; +import java.util.List; + +public class Rule { + private List selectors; + private ConfigurationMap configuration; + + // Getters and setters + public List getSelectors() { + return selectors; + } + + public void setSelectors(List selectors) { + this.selectors = selectors; + } + + public ConfigurationMap getConfiguration() { + return configuration; + } + + public void setConfiguration(ConfigurationMap configuration) { + this.configuration = configuration; + } +} diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/Selector.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/Selector.java new file mode 100644 index 00000000000..634af44ae68 --- /dev/null +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/Selector.java @@ -0,0 +1,43 @@ +package datadog.trace.bootstrap.config.provider.StableConfigYaml; + +import java.util.List; + +public class Selector { + private String origin; + private String key; + private List matches; + private String operator; + + // Getters and setters + public String getOrigin() { + return origin; + } + + public void setOrigin(String origin) { + this.origin = origin; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public List getMatches() { + return matches; + } + + public void setMatches(List matches) { + this.matches = matches; + } + + public String getOperator() { + return operator; + } + + public void setOperator(String operator) { + this.operator = operator; + } +} diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/StableConfigYaml.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/StableConfigYaml.java new file mode 100644 index 00000000000..c9c06d14cfe --- /dev/null +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/StableConfigYaml.java @@ -0,0 +1,35 @@ +package datadog.trace.bootstrap.config.provider.StableConfigYaml; + +import datadog.trace.bootstrap.config.provider.ConfigurationMap; +import java.util.List; + +public class StableConfigYaml { + private String config_id; // optional + private ConfigurationMap apm_configuration_default; + private List apm_configuration_rules; + + // Getters and setters + public String getConfig_id() { + return config_id; + } + + public void setConfig_id(String config_id) { + this.config_id = config_id; + } + + public ConfigurationMap getApm_configuration_default() { + return apm_configuration_default; + } + + public void setApm_configuration_default(ConfigurationMap apm_configuration_default) { + this.apm_configuration_default = apm_configuration_default; + } + + public List getApm_configuration_rules() { + return apm_configuration_rules; + } + + public void setApm_configuration_rules(List apm_configuration_rules) { + this.apm_configuration_rules = apm_configuration_rules; + } +} diff --git a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy index f7cc3a0101c..98e07817db5 100644 --- a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy +++ b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy @@ -6,7 +6,6 @@ import java.nio.file.Files import java.nio.file.Path class StableConfigParserTest extends DDSpecification { - def "test parser"() { when: Path filePath = StableConfigSourceTest.tempFile() @@ -14,21 +13,18 @@ class StableConfigParserTest extends DDSpecification { throw new AssertionError("Failed to create test file") } String yaml = """ -something-irrelevant: "" config_id: 12345 -something : not : expected << and weird format - inufjka << - [a, - b, - c, - d] apm_configuration_default: - KEY_ONE: value_one - KEY_TWO: "value_two" - KEY_THREE: 100 - KEY_FOUR: true - KEY_FIVE: [a,b,c,d] -something-else-irrelevant: value-irrelevant + KEY_ONE: "default" + KEY_TWO: true +apm_configuration_rules: + - selectors: + - origin: language + matches: ["Java"] + operator: equals + configuration: + KEY_ONE: "rules" + KEY_THREE: 1 """ try { StableConfigSourceTest.writeFileRaw(filePath, yaml) @@ -45,83 +41,133 @@ something-else-irrelevant: value-irrelevant then: def keys = cfg.getKeys() - keys.size() == 5 - !keys.contains("something-irrelevant") - !keys.contains("something-else-irrelevant") + keys.size() == 3 cfg.getConfigId().trim() == ("12345") - cfg.get("KEY_ONE") == "value_one" - cfg.get("KEY_TWO") == "value_two" - cfg.get("KEY_THREE") == "100" - cfg.get("KEY_FOUR") == "true" - cfg.get("KEY_FIVE") == "[a,b,c,d]" + cfg.get("KEY_ONE") == "rules" + cfg.get("KEY_TWO") == "true" + cfg.get("KEY_THREE") == "1" Files.delete(filePath) } - def "test duplicate config_id"() { - when: - Path filePath = StableConfigSourceTest.tempFile() - if (filePath == null) { - throw new AssertionError("Failed to create test file") - } - String yaml = """ -config_id: 12345 -something-irrelevant: "" -apm_configuration_default: - DD_KEY: value -config_id: 67890 -""" - - try { - StableConfigSourceTest.writeFileRaw(filePath, yaml) - } catch (IOException e) { - throw new AssertionError("Failed to write to file: ${e.message}") - } - - Exception exception - StableConfigSource.StableConfig cfg - try { - cfg = StableConfigParser.parse(filePath.toString()) - } catch (Exception e) { - exception = e - } - - then: - cfg == null - exception != null - exception.getMessage() == "Duplicate config_id keys found; file may be malformed" + def "test selectorMatch"() { + // TODO } - def "test duplicate apm_configuration_default"() { - // Assert that only the first entry is used - when: - Path filePath = StableConfigSourceTest.tempFile() - if (filePath == null) { - throw new AssertionError("Failed to create test file") - } - String yaml = """ -apm_configuration_default: - KEY_1: value_1 -something-else-irrelevant: value-irrelevant -apm_configuration_default: - KEY_2: value_2 -""" - try { - StableConfigSourceTest.writeFileRaw(filePath, yaml) - } catch (IOException e) { - throw new AssertionError("Failed to write to file: ${e.message}") - } - - StableConfigSource.StableConfig cfg - try { - cfg = StableConfigParser.parse(filePath.toString()) - } catch (Exception e) { - throw new AssertionError("Failed to parse the file: ${e.message}") - } + // def "test parser"() { + // when: + // Path filePath = StableConfigSourceTest.tempFile() + // if (filePath == null) { + // throw new AssertionError("Failed to create test file") + // } + // String yaml = """ + //something-irrelevant: "" + //config_id: 12345 + //something : not : expected << and weird format + // inufjka << + // [a, + // b, + // c, + // d] + //apm_configuration_default: + // KEY_ONE: value_one + // KEY_TWO: "value_two" + // KEY_THREE: 100 + // KEY_FOUR: true + // KEY_FIVE: [a,b,c,d] + //something-else-irrelevant: value-irrelevant + //""" + // try { + // StableConfigSourceTest.writeFileRaw(filePath, yaml) + // } catch (IOException e) { + // throw new AssertionError("Failed to write to file: ${e.message}") + // } + // + // StableConfigSource.StableConfig cfg + // try { + // cfg = StableConfigParser.parse(filePath.toString()) + // } catch (Exception e) { + // throw new AssertionError("Failed to parse the file: ${e.message}") + // } + // + // then: + // def keys = cfg.getKeys() + // keys.size() == 5 + // !keys.contains("something-irrelevant") + // !keys.contains("something-else-irrelevant") + // cfg.getConfigId().trim() == ("12345") + // cfg.get("KEY_ONE") == "value_one" + // cfg.get("KEY_TWO") == "value_two" + // cfg.get("KEY_THREE") == "100" + // cfg.get("KEY_FOUR") == "true" + // cfg.get("KEY_FIVE") == "[a,b,c,d]" + // Files.delete(filePath) + // } - then: - def keys = cfg.getKeys() - keys.size() == 1 - !keys.contains("KEY_2") - cfg.get("KEY_1") == "value_1" - } + // def "test duplicate config_id"() { + // when: + // Path filePath = StableConfigSourceTest.tempFile() + // if (filePath == null) { + // throw new AssertionError("Failed to create test file") + // } + // String yaml = """ + //config_id: 12345 + //something-irrelevant: "" + //apm_configuration_default: + // DD_KEY: value + //config_id: 67890 + //""" + // + // try { + // StableConfigSourceTest.writeFileRaw(filePath, yaml) + // } catch (IOException e) { + // throw new AssertionError("Failed to write to file: ${e.message}") + // } + // + // Exception exception + // StableConfigSource.StableConfig cfg + // try { + // cfg = StableConfigParser.parse(filePath.toString()) + // } catch (Exception e) { + // exception = e + // } + // + // then: + // cfg == null + // exception != null + // exception.getMessage() == "Duplicate config_id keys found; file may be malformed" + // } + // + // def "test duplicate apm_configuration_default"() { + // // Assert that only the first entry is used + // when: + // Path filePath = StableConfigSourceTest.tempFile() + // if (filePath == null) { + // throw new AssertionError("Failed to create test file") + // } + // String yaml = """ + //apm_configuration_default: + // KEY_1: value_1 + //something-else-irrelevant: value-irrelevant + //apm_configuration_default: + // KEY_2: value_2 + //""" + // try { + // StableConfigSourceTest.writeFileRaw(filePath, yaml) + // } catch (IOException e) { + // throw new AssertionError("Failed to write to file: ${e.message}") + // } + // + // StableConfigSource.StableConfig cfg + // try { + // cfg = StableConfigParser.parse(filePath.toString()) + // } catch (Exception e) { + // throw new AssertionError("Failed to parse the file: ${e.message}") + // } + // + // then: + // def keys = cfg.getKeys() + // keys.size() == 1 + // !keys.contains("KEY_2") + // cfg.get("KEY_1") == "value_1" + // } } diff --git a/settings.gradle b/settings.gradle index 8dd42b9cab9..ae394bf910f 100644 --- a/settings.gradle +++ b/settings.gradle @@ -69,6 +69,7 @@ include ':communication' include ':components:cli' include ':components:context' include ':components:json' +include ':components:yaml' include ':telemetry' include ':remote-config:remote-config-api' include ':remote-config:remote-config-core' From 0f54ff19eac478408f1b19494792d6e4ada32de7 Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Mon, 10 Mar 2025 13:07:04 -0400 Subject: [PATCH 12/98] Clean up tests + expand selectorMatch to cover environment_variables and language --- .../trace/bootstrap/AgentBootstrap.java | 2 +- .../config/provider/StableConfigParser.java | 61 ++++- .../StableConfigYaml/StableConfigYaml.java | 8 +- .../provider/StableConfigParserTest.groovy | 224 +++++++++--------- .../provider/StableConfigSourceTest.groovy | 123 ++++++---- 5 files changed, 235 insertions(+), 183 deletions(-) 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 d715c1f3277..7d7aa09b41c 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 @@ -421,7 +421,7 @@ private static File getAgentFileUsingClassLoaderLookup() throws URISyntaxExcepti javaagentFile = new File(new URI(thisClassUrl.getFile().split("!")[0])); return javaagentFile; } - + private static void checkJarManifestMainClassIsThis(final URL jarUrl) throws IOException { final URL manifestUrl = new URL("jar:" + jarUrl + "!/META-INF/MANIFEST.MF"); final String mainClassLine = "Main-Class: " + thisClass.getCanonicalName(); diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java index 1e943c6dc58..ef4ca7a4fbe 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java @@ -17,7 +17,6 @@ public static StableConfigSource.StableConfig parse(String filePath) throws IOEx try { StableConfigYaml data = YamlParser.parse(filePath, StableConfigYaml.class); ConfigurationMap configMap = data.getApm_configuration_default(); - // TODO: Support multiple sets of rules + configs. List rules = data.getApm_configuration_rules(); if (rules != null) { for (Rule rule : rules) { @@ -33,7 +32,7 @@ public static StableConfigSource.StableConfig parse(String filePath) throws IOEx break; } } - // Use the first selector that matches; return early + // Use the first rule that matches; return early if (match) { configMap.putAll(rule.getConfiguration()); return new StableConfigSource.StableConfig( @@ -54,18 +53,58 @@ public static StableConfigSource.StableConfig parse(String filePath) throws IOEx return StableConfigSource.StableConfig.EMPTY; } - // TODO: Create strict types for origin and operator values - private static boolean selectorMatch( + // TODO: Make this private again after testing + public static boolean selectorMatch( String origin, List matches, String operator, String key) { - // if(origin.equals("language")) { - // List matchesList = Arrays.asList(matches); - // return matchesList.contains("Java") || matchesList.contains("java") && - // operator.equals("equals"); - // } + switch (origin) { + case "language": + return matches.contains("Java") || matches.contains("java") && operator.equals("equals"); + case "environment_variables": + String envValue = System.getenv(key); + if (envValue == null) { + return false; + } + switch (operator) { + case "exists": + // We don't care about the value + return true; + // TODO: Determine if substrings are case insensitive + case "equals": + for (String value : matches) { + if (value.equals(envValue)) { + return true; + } + } + break; + case "starts_with": + for (String value : matches) { + if (envValue.startsWith(value)) { + return true; + } + } + break; + case "ends_with": + for (String value : matches) { + if (envValue.endsWith(value)) { + return true; + } + } + break; + case "contains": + for (String value : matches) { + if (envValue.contains(value)) { + return true; + } + } + } + return false; + case "process_arguments": + // TODO: export getVMArgumentsThroughReflection to a utility class and cache its results, so + // as not to re-run this query + break; + } // else if(origin.equals("tags")) { // - // } else if(origin.equals("environment_variables")) { - // // } else if(origin.equals("process_arguments")) { // // } diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/StableConfigYaml.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/StableConfigYaml.java index c9c06d14cfe..73d58dd9560 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/StableConfigYaml.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/StableConfigYaml.java @@ -6,7 +6,13 @@ public class StableConfigYaml { private String config_id; // optional private ConfigurationMap apm_configuration_default; - private List apm_configuration_rules; + private List apm_configuration_rules; // optional + + public StableConfigYaml() { + this.config_id = null; + this.apm_configuration_default = null; + this.apm_configuration_rules = null; + } // Getters and setters public String getConfig_id() { diff --git a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy index 98e07817db5..17913ac49d3 100644 --- a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy +++ b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy @@ -6,7 +6,7 @@ import java.nio.file.Files import java.nio.file.Path class StableConfigParserTest extends DDSpecification { - def "test parser"() { + def "test parse valid"() { when: Path filePath = StableConfigSourceTest.tempFile() if (filePath == null) { @@ -49,125 +49,113 @@ apm_configuration_rules: Files.delete(filePath) } + // TODO: This test will fail if we make selectorMatch private again def "test selectorMatch"() { - // TODO + when: + injectEnvConfig("DD_PROFILING_ENABLED", "true") + injectEnvConfig("DD_SERVICE", "mysvc") + injectEnvConfig("DD_TAGS", "team:apm,component:web") + def match = StableConfigParser.selectorMatch(origin, matches, operator, key) + + then: + match == expectMatch + + where: + origin | matches | operator | key | expectMatch + "language" | ["java"] | "equals" | "" | true + "language" | ["java", "golang"] | "equals" | "" | true + "language" | ["java"] | "starts_with" | "" | false + "language" | ["golang"] | "equals" | "" | false + "environment_variables" | [] | "exists" | "DD_TAGS" | true + "environment_variables" | ["team:apm"] | "equals" | "DD_TAGS" | false + "environment_variables" | ["team:apm"] | "contains" | "DD_TAGS" | true + "environment_variables" | ["team:apm"] | "starts_with" | "DD_TAGS" | true + "environment_variables" | ["true"] | "equals" | "DD_PROFILING_ENABLED" | true + "environment_variables" | ["abcdefg"] | "equals" | "DD_PROFILING_ENABLED" | false + "environment_variables" | ["true"] | "equals" | "DD_PROFILING_ENABLED" | true + "environment_variables" | ["mysvc", "othersvc"] | "equals" | "DD_SERVICE" | true + "environment_variables" | ["my"] | "starts_with" | "DD_SERVICE" | true + "environment_variables" | ["svc"] | "ends_with" | "DD_SERVICE" | true + "environment_variables" | ["svc"] | "contains" | "DD_SERVICE" | true + "environment_variables" | ["other"] | "contains" | "DD_SERVICE" | false } - // def "test parser"() { - // when: - // Path filePath = StableConfigSourceTest.tempFile() - // if (filePath == null) { - // throw new AssertionError("Failed to create test file") - // } - // String yaml = """ - //something-irrelevant: "" - //config_id: 12345 - //something : not : expected << and weird format - // inufjka << - // [a, - // b, - // c, - // d] - //apm_configuration_default: - // KEY_ONE: value_one - // KEY_TWO: "value_two" - // KEY_THREE: 100 - // KEY_FOUR: true - // KEY_FIVE: [a,b,c,d] - //something-else-irrelevant: value-irrelevant - //""" - // try { - // StableConfigSourceTest.writeFileRaw(filePath, yaml) - // } catch (IOException e) { - // throw new AssertionError("Failed to write to file: ${e.message}") - // } - // - // StableConfigSource.StableConfig cfg - // try { - // cfg = StableConfigParser.parse(filePath.toString()) - // } catch (Exception e) { - // throw new AssertionError("Failed to parse the file: ${e.message}") - // } - // - // then: - // def keys = cfg.getKeys() - // keys.size() == 5 - // !keys.contains("something-irrelevant") - // !keys.contains("something-else-irrelevant") - // cfg.getConfigId().trim() == ("12345") - // cfg.get("KEY_ONE") == "value_one" - // cfg.get("KEY_TWO") == "value_two" - // cfg.get("KEY_THREE") == "100" - // cfg.get("KEY_FOUR") == "true" - // cfg.get("KEY_FIVE") == "[a,b,c,d]" - // Files.delete(filePath) - // } + def "test duplicate entries"() { + // When duplicate keys are encountered, snakeyaml preserves the last value by default + when: + Path filePath = StableConfigSourceTest.tempFile() + if (filePath == null) { + throw new AssertionError("Failed to create test file") + } + String yaml = """ + config_id: 12345 + config_id: 67890 + apm_configuration_default: + DD_KEY: value_1 + apm_configuration_default: + DD_KEY: value_2 + """ + + try { + StableConfigSourceTest.writeFileRaw(filePath, yaml) + } catch (IOException e) { + throw new AssertionError("Failed to write to file: ${e.message}") + } + + StableConfigSource.StableConfig cfg + try { + cfg = StableConfigParser.parse(filePath.toString()) + } catch (Exception e) { + throw new AssertionError("Failed to parse the file: ${e.message}") + } - // def "test duplicate config_id"() { - // when: - // Path filePath = StableConfigSourceTest.tempFile() - // if (filePath == null) { - // throw new AssertionError("Failed to create test file") - // } - // String yaml = """ - //config_id: 12345 - //something-irrelevant: "" - //apm_configuration_default: - // DD_KEY: value - //config_id: 67890 - //""" - // - // try { - // StableConfigSourceTest.writeFileRaw(filePath, yaml) - // } catch (IOException e) { - // throw new AssertionError("Failed to write to file: ${e.message}") - // } - // - // Exception exception - // StableConfigSource.StableConfig cfg - // try { - // cfg = StableConfigParser.parse(filePath.toString()) - // } catch (Exception e) { - // exception = e - // } - // - // then: - // cfg == null - // exception != null - // exception.getMessage() == "Duplicate config_id keys found; file may be malformed" - // } - // - // def "test duplicate apm_configuration_default"() { - // // Assert that only the first entry is used - // when: - // Path filePath = StableConfigSourceTest.tempFile() - // if (filePath == null) { - // throw new AssertionError("Failed to create test file") - // } - // String yaml = """ - //apm_configuration_default: - // KEY_1: value_1 - //something-else-irrelevant: value-irrelevant - //apm_configuration_default: - // KEY_2: value_2 - //""" - // try { - // StableConfigSourceTest.writeFileRaw(filePath, yaml) - // } catch (IOException e) { - // throw new AssertionError("Failed to write to file: ${e.message}") - // } - // - // StableConfigSource.StableConfig cfg - // try { - // cfg = StableConfigParser.parse(filePath.toString()) - // } catch (Exception e) { - // throw new AssertionError("Failed to parse the file: ${e.message}") - // } - // - // then: - // def keys = cfg.getKeys() - // keys.size() == 1 - // !keys.contains("KEY_2") - // cfg.get("KEY_1") == "value_1" - // } + then: + cfg != null + cfg.getConfigId() == "67890" + cfg.get("DD_KEY") == "value_2" + } + + def "test parse invalid"() { + // If any piece of the file is invalid, the whole file is rendered invalid and an exception is thrown + when: + Path filePath = StableConfigSourceTest.tempFile() + if (filePath == null) { + throw new AssertionError("Failed to create test file") + } + String yaml = """ + something-irrelevant: "" + config_id: 12345 + something : not : expected << and weird format + inufjka << + [a, + b, + c, + d] + apm_configuration_default: + KEY_ONE: value_one + KEY_TWO: "value_two" + KEY_THREE: 100 + KEY_FOUR: true + KEY_FIVE: [a,b,c,d] + something-else-irrelevant: value-irrelevant + """ + try { + StableConfigSourceTest.writeFileRaw(filePath, yaml) + } catch (IOException e) { + throw new AssertionError("Failed to write to file: ${e.message}") + } + + StableConfigSource.StableConfig cfg + Exception exception = null + try { + cfg = StableConfigParser.parse(filePath.toString()) + } catch (Exception e) { + exception = e + } + + then: + exception != null + cfg == null + Files.delete(filePath) + } } diff --git a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigSourceTest.groovy b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigSourceTest.groovy index 890ab15a7b9..b285e47cacb 100644 --- a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigSourceTest.groovy +++ b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigSourceTest.groovy @@ -1,9 +1,14 @@ package datadog.trace.bootstrap.config.provider import datadog.trace.api.ConfigOrigin +import datadog.trace.bootstrap.config.provider.StableConfigYaml.StableConfigYaml import datadog.trace.test.util.DDSpecification import org.yaml.snakeyaml.DumperOptions import org.yaml.snakeyaml.Yaml +import org.yaml.snakeyaml.introspector.Property +import org.yaml.snakeyaml.nodes.NodeTuple +import org.yaml.snakeyaml.nodes.Tag +import org.yaml.snakeyaml.representer.Representer import spock.lang.Shared import java.nio.file.Path @@ -34,34 +39,8 @@ class StableConfigSourceTest extends DDSpecification { config.getConfigId() == null } - def "test get"() { - when: - Path filePath = tempFile() - if (filePath == null) { - throw new AssertionError("Failed to create test file") - } - - def configs = new HashMap<>() << ["DD_SERVICE": "svc", "DD_ENV": "env", "CONFIG_NO_DD": "value123"] - - try { - writeFileYaml(filePath, "12345", configs) - } catch (IOException e) { - throw new AssertionError("Failed to write to file: ${e.message}") - } - - StableConfigSource cfg = new StableConfigSource(filePath.toString(), ConfigOrigin.LOCAL_STABLE_CONFIG) - - then: - cfg.get("service") == "svc" - cfg.get("env") == "env" - cfg.get("config_no_dd") == null - cfg.get("config_nonexistent") == null - cfg.getKeys().size() == 3 - cfg.getConfigId() == "12345" - Files.delete(filePath) - } - def "test file invalid format"() { + // StableConfigSource must handle the exception thrown by StableConfigParser.parse(filePath) gracefully when: Path filePath = tempFile() if (filePath == null) { @@ -69,7 +48,7 @@ class StableConfigSourceTest extends DDSpecification { } try { - writeFileRaw(filePath, configId, configs) + writeFileRaw(filePath, configId, data) } catch (IOException e) { throw new AssertionError("Failed to write to file: ${e.message}") } @@ -82,7 +61,7 @@ class StableConfigSourceTest extends DDSpecification { Files.delete(filePath) where: - configId | configs + configId | data null | corruptYaml "12345" | "this is not yaml format!" } @@ -93,9 +72,12 @@ class StableConfigSourceTest extends DDSpecification { if (filePath == null) { throw new AssertionError("Failed to create test file") } + StableConfigYaml stableConfigYaml = new StableConfigYaml() + stableConfigYaml.setConfig_id(configId) + stableConfigYaml.setApm_configuration_default(defaultConfigs as ConfigurationMap) try { - writeFileYaml(filePath, configId, configs) + writeFileYaml(filePath, stableConfigYaml) } catch (IOException e) { throw new AssertionError("Failed to write to file: ${e.message}") } @@ -103,15 +85,16 @@ class StableConfigSourceTest extends DDSpecification { StableConfigSource stableCfg = new StableConfigSource(filePath.toString(), ConfigOrigin.LOCAL_STABLE_CONFIG) then: - for (key in configs.keySet()) { + for (key in defaultConfigs.keySet()) { String keyString = (String) key keyString = keyString.substring(4) // Cut `DD_` - stableCfg.get(keyString) == configs.get(key) + stableCfg.get(keyString) == defaultConfigs.get(key) } Files.delete(filePath) where: - configId | configs + // TODO: Add ruleConfigs + configId | defaultConfigs "" | new HashMap<>() "12345" | new HashMap<>() << ["DD_KEY_ONE": "one", "DD_KEY_TWO": "two"] } @@ -135,34 +118,70 @@ class StableConfigSourceTest extends DDSpecification { } } - static writeFileYaml(Path filePath, String configId, Map configs) { - DumperOptions options = new DumperOptions() - options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK) - - // Prepare to write the data map to the file in yaml format - Yaml yaml = new Yaml(options) - String yamlString - Map data = new HashMap<>() - if (configId != null) { - data.put("config_id", configId) - } - if (configs instanceof HashMap) { - data.put("apm_configuration_default", configs) - } + def stableConfigYamlWriter = getStableConfigYamlWriter() - yamlString = yaml.dump(data) + Yaml getStableConfigYamlWriter() { + DumperOptions options = new DumperOptions() + // Create the Representer, configure it to omit nulls + Representer representer = new Representer(options) { + @Override + protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) { + if (propertyValue == null) { + return null // Skip null values + } else { + return super.representJavaBeanProperty(javaBean, property, propertyValue, customTag) + } + } + } + // Exclude class tag from the resulting yaml string + representer.addClassTag(StableConfigYaml.class, Tag.MAP) + + // YAML instance with custom Representer + return new Yaml(representer, options) + } - StandardOpenOption[] openOpts = [StandardOpenOption.WRITE] as StandardOpenOption[] - Files.write(filePath, yamlString.getBytes(), openOpts) + // def generateYaml(configId, apmConfigurationDefault, apmConfigurationRules, miscData) { + // // Construct the YAML dynamically using GString interpolation + // def yaml = """ + //config_id: ${configId} + //apm_configuration_default: + // ${apmConfigurationDefault.collect { key, value -> "$key: $value" }.join("\n ")} + //apm_configuration_rules: + // ${apmConfigurationRules.collect { rule -> + // """ + // - selectors: + // ${rule.selectors.collect { selector -> + // """ + // - origin: ${selector.origin} + // matches: ${selector.matches.inspect()} + // operator: ${selector.operator} + // """.stripIndent() }.join("\n ")} + // configuration: + // ${rule.configuration.collect { key, value -> "$key: $value" }.join("\n ")} + // """.stripIndent() + // }.join("\n")} + //${miscData} + //""" + // return yaml + // } + + def writeFileYaml(Path filePath, StableConfigYaml stableConfigs) { + // Yaml yaml = getStableConfigYaml(); + try (FileWriter writer = new FileWriter(filePath.toString())) { + stableConfigYamlWriter.dump(stableConfigs, writer) + } catch (IOException e) { + e.printStackTrace() + } } // Use this if you want to explicitly write/test configId - def writeFileRaw(Path filePath, String configId, String configs) { - String data = configId + "\n" + configs + def writeFileRaw(Path filePath, String configId, String data) { + data = configId + "\n" + data StandardOpenOption[] openOpts = [StandardOpenOption.WRITE] as StandardOpenOption[] Files.write(filePath, data.getBytes(), openOpts) } + // Use this for writing a string directly into a file static writeFileRaw(Path filePath, String data) { StandardOpenOption[] openOpts = [StandardOpenOption.WRITE] as StandardOpenOption[] Files.write(filePath, data.getBytes(), openOpts) From 9826f0f1644cf7117b0b763fa73dbd7426377bc1 Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Mon, 10 Mar 2025 14:07:57 -0400 Subject: [PATCH 13/98] address [some] github codequality breaches --- .../config/provider/StableConfigParser.java | 20 +++++++++++-------- .../StableConfigYaml/StableConfigYaml.java | 5 +++-- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java index ef4ca7a4fbe..1bbe767c38e 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java @@ -18,7 +18,7 @@ public static StableConfigSource.StableConfig parse(String filePath) throws IOEx StableConfigYaml data = YamlParser.parse(filePath, StableConfigYaml.class); ConfigurationMap configMap = data.getApm_configuration_default(); List rules = data.getApm_configuration_rules(); - if (rules != null) { + if (!rules.isEmpty()) { for (Rule rule : rules) { List selectors = rule.getSelectors(); boolean match = true; @@ -34,12 +34,15 @@ public static StableConfigSource.StableConfig parse(String filePath) throws IOEx } // Use the first rule that matches; return early if (match) { + // Merge apm_configuration_default and apm_configuration_rules configMap.putAll(rule.getConfiguration()); return new StableConfigSource.StableConfig( data.getConfig_id(), new HashMap<>(configMap)); } } } + // TODO: Right now, a file with config_id but no apm_configuration_default nor + // apm_configuration_rules gets discarded. Should it? // If configs were found in apm_configuration_default, use them if (!configMap.isEmpty()) { return new StableConfigSource.StableConfig(data.getConfig_id(), new HashMap<>(configMap)); @@ -96,18 +99,19 @@ public static boolean selectorMatch( return true; } } + default: + return false; } return false; case "process_arguments": // TODO: export getVMArgumentsThroughReflection to a utility class and cache its results, so // as not to re-run this query - break; + return true; + case "tags": + // TODO: Determine where tags are sourced from + return true; + default: + return false; } - // else if(origin.equals("tags")) { - // - // } else if(origin.equals("process_arguments")) { - // - // } - return true; } } diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/StableConfigYaml.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/StableConfigYaml.java index 73d58dd9560..55dd65aa716 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/StableConfigYaml.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/StableConfigYaml.java @@ -1,6 +1,7 @@ package datadog.trace.bootstrap.config.provider.StableConfigYaml; import datadog.trace.bootstrap.config.provider.ConfigurationMap; +import java.util.ArrayList; import java.util.List; public class StableConfigYaml { @@ -10,8 +11,8 @@ public class StableConfigYaml { public StableConfigYaml() { this.config_id = null; - this.apm_configuration_default = null; - this.apm_configuration_rules = null; + this.apm_configuration_default = new ConfigurationMap(); + this.apm_configuration_rules = new ArrayList<>(); } // Getters and setters From 63280ae178aed0d4274bb68fc8464aca4bf20dfa Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Tue, 11 Mar 2025 16:43:07 -0400 Subject: [PATCH 14/98] use config_id even if configs are empty/missing --- .../config/provider/StableConfigParser.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java index 1bbe767c38e..96b91db0838 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java @@ -5,6 +5,7 @@ import datadog.trace.bootstrap.config.provider.StableConfigYaml.StableConfigYaml; import datadog.yaml.YamlParser; import java.io.IOException; +import java.util.Collections; import java.util.HashMap; import java.util.List; import org.slf4j.Logger; @@ -16,6 +17,7 @@ public class StableConfigParser { public static StableConfigSource.StableConfig parse(String filePath) throws IOException { try { StableConfigYaml data = YamlParser.parse(filePath, StableConfigYaml.class); + String configId = data.getConfig_id(); ConfigurationMap configMap = data.getApm_configuration_default(); List rules = data.getApm_configuration_rules(); if (!rules.isEmpty()) { @@ -36,16 +38,17 @@ public static StableConfigSource.StableConfig parse(String filePath) throws IOEx if (match) { // Merge apm_configuration_default and apm_configuration_rules configMap.putAll(rule.getConfiguration()); - return new StableConfigSource.StableConfig( - data.getConfig_id(), new HashMap<>(configMap)); + return new StableConfigSource.StableConfig(configId, new HashMap<>(configMap)); } } } - // TODO: Right now, a file with config_id but no apm_configuration_default nor - // apm_configuration_rules gets discarded. Should it? // If configs were found in apm_configuration_default, use them if (!configMap.isEmpty()) { - return new StableConfigSource.StableConfig(data.getConfig_id(), new HashMap<>(configMap)); + return new StableConfigSource.StableConfig(configId, new HashMap<>(configMap)); + } + // There was an update but with no configs; still register this + if (configId != null) { + return new StableConfigSource.StableConfig(configId, Collections.emptyMap()); } } catch (IOException e) { // TODO: Update this log from "stable configuration" to the official name of the feature, once From 5859ec9df83a1173736dcc4f3d709ca9e5f5e13f Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Tue, 11 Mar 2025 17:04:17 -0400 Subject: [PATCH 15/98] nits: refactor StableConfigParser for clarity --- .../config/provider/StableConfigParser.java | 57 +++++++++++++------ 1 file changed, 39 insertions(+), 18 deletions(-) diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java index 96b91db0838..39522a4085a 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java @@ -14,42 +14,46 @@ public class StableConfigParser { private static final Logger log = LoggerFactory.getLogger(StableConfigParser.class); + /** + * Parses a configuration file and returns a stable configuration object. + * + *

This method reads a configuration file from the given file path, parses the YAML content, + * and identifies configurations for the process using a combination of apm_configuration_default + * and apm_configuration_rules. If a matching rule is found in apm_configuration_rules, it returns + * a {@link StableConfigSource.StableConfig} object with the merged configuration. If no matching + * rule is found, it returns the default configuration. If neither a matching rule nor a default + * configuration is found, an empty configuration is returned. + * + * @param filePath The path to the YAML configuration file to be parsed. + * @return A {@link StableConfigSource.StableConfig} object containing the stable configuration. + * @throws IOException If there is an error reading the file or parsing the YAML content. + */ public static StableConfigSource.StableConfig parse(String filePath) throws IOException { try { StableConfigYaml data = YamlParser.parse(filePath, StableConfigYaml.class); + String configId = data.getConfig_id(); ConfigurationMap configMap = data.getApm_configuration_default(); List rules = data.getApm_configuration_rules(); + if (!rules.isEmpty()) { for (Rule rule : rules) { - List selectors = rule.getSelectors(); - boolean match = true; - for (Selector selector : selectors) { - if (!selectorMatch( - selector.getOrigin(), - selector.getMatches(), - selector.getOperator(), - selector.getKey())) { - match = false; - break; - } - } - // Use the first rule that matches; return early - if (match) { - // Merge apm_configuration_default and apm_configuration_rules + if (doesRuleMatch(rule)) { configMap.putAll(rule.getConfiguration()); - return new StableConfigSource.StableConfig(configId, new HashMap<>(configMap)); + return createStableConfig(configId, configMap); } } } // If configs were found in apm_configuration_default, use them if (!configMap.isEmpty()) { - return new StableConfigSource.StableConfig(configId, new HashMap<>(configMap)); + return createStableConfig(configId, configMap); } - // There was an update but with no configs; still register this + + // If there's a configId but no configMap, return an empty map if (configId != null) { return new StableConfigSource.StableConfig(configId, Collections.emptyMap()); } + } catch (IOException e) { // TODO: Update this log from "stable configuration" to the official name of the feature, once // determined @@ -59,6 +63,23 @@ public static StableConfigSource.StableConfig parse(String filePath) throws IOEx return StableConfigSource.StableConfig.EMPTY; } + /** Checks if the rule's selectors match. All must match for a "true" return value. */ + private static boolean doesRuleMatch(Rule rule) { + for (Selector selector : rule.getSelectors()) { + if (!selectorMatch( + selector.getOrigin(), selector.getMatches(), selector.getOperator(), selector.getKey())) { + return false; // Return false immediately if any selector doesn't match + } + } + return true; // Return true if all selectors match + } + + /** Creates a StableConfig object from the provided configId and configMap. */ + private static StableConfigSource.StableConfig createStableConfig( + String configId, ConfigurationMap configMap) { + return new StableConfigSource.StableConfig(configId, new HashMap<>(configMap)); + } + // TODO: Make this private again after testing public static boolean selectorMatch( String origin, List matches, String operator, String key) { From 4e8c0fa9bc499f7019e5871414a08f25f49270a7 Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Wed, 12 Mar 2025 11:02:30 -0400 Subject: [PATCH 16/98] Clean up for first review --- .../trace/bootstrap/AgentBootstrap.java | 2 +- .../config/provider/StableConfigParser.java | 9 +++++-- .../ConfigurationMap.java | 4 ++- .../provider/StableConfigYaml/Rule.java | 4 ++- .../StableConfigYaml/StableConfigYaml.java | 1 - .../provider/StableConfigParserTest.groovy | 1 + .../provider/StableConfigSourceTest.groovy | 26 +------------------ 7 files changed, 16 insertions(+), 31 deletions(-) rename internal-api/src/main/java/datadog/trace/bootstrap/config/provider/{ => StableConfigYaml}/ConfigurationMap.java (53%) 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 7d7aa09b41c..d715c1f3277 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 @@ -421,7 +421,7 @@ private static File getAgentFileUsingClassLoaderLookup() throws URISyntaxExcepti javaagentFile = new File(new URI(thisClassUrl.getFile().split("!")[0])); return javaagentFile; } - + private static void checkJarManifestMainClassIsThis(final URL jarUrl) throws IOException { final URL manifestUrl = new URL("jar:" + jarUrl + "!/META-INF/MANIFEST.MF"); final String mainClassLine = "Main-Class: " + thisClass.getCanonicalName(); diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java index 39522a4085a..f53c5b537a0 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java @@ -1,5 +1,6 @@ package datadog.trace.bootstrap.config.provider; +import datadog.trace.bootstrap.config.provider.StableConfigYaml.ConfigurationMap; import datadog.trace.bootstrap.config.provider.StableConfigYaml.Rule; import datadog.trace.bootstrap.config.provider.StableConfigYaml.Selector; import datadog.trace.bootstrap.config.provider.StableConfigYaml.StableConfigYaml; @@ -39,6 +40,7 @@ public static StableConfigSource.StableConfig parse(String filePath) throws IOEx if (!rules.isEmpty()) { for (Rule rule : rules) { if (doesRuleMatch(rule)) { + // Merge configs found in apm_configuration_default and apm_configuration_rules configMap.putAll(rule.getConfiguration()); return createStableConfig(configId, configMap); } @@ -63,7 +65,10 @@ public static StableConfigSource.StableConfig parse(String filePath) throws IOEx return StableConfigSource.StableConfig.EMPTY; } - /** Checks if the rule's selectors match. All must match for a "true" return value. */ + /** + * Checks if the rule's selectors match the current process. All must match for a "true" return + * value. + */ private static boolean doesRuleMatch(Rule rule) { for (Selector selector : rule.getSelectors()) { if (!selectorMatch( @@ -80,7 +85,7 @@ private static StableConfigSource.StableConfig createStableConfig( return new StableConfigSource.StableConfig(configId, new HashMap<>(configMap)); } - // TODO: Make this private again after testing + // TODO: Make this private again after testing? public static boolean selectorMatch( String origin, List matches, String operator, String key) { switch (origin) { diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/ConfigurationMap.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/ConfigurationMap.java similarity index 53% rename from internal-api/src/main/java/datadog/trace/bootstrap/config/provider/ConfigurationMap.java rename to internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/ConfigurationMap.java index 315e8a306d3..527c0412332 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/ConfigurationMap.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/ConfigurationMap.java @@ -1,7 +1,9 @@ -package datadog.trace.bootstrap.config.provider; +package datadog.trace.bootstrap.config.provider.StableConfigYaml; import java.util.HashMap; +// TODO: Update this comment from "stable configuration" to whatever product decides on for the name +// ConfigurationMap represents configuration key-values found in stable configuration files public class ConfigurationMap extends HashMap {} class ConfigurationValue { diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/Rule.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/Rule.java index 52ac972c07b..4853f430a08 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/Rule.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/Rule.java @@ -1,8 +1,10 @@ package datadog.trace.bootstrap.config.provider.StableConfigYaml; -import datadog.trace.bootstrap.config.provider.ConfigurationMap; import java.util.List; +// TODO: Update this comment from "stable configuration" to whatever product decides on for the name +// Rule represents a set of selectors and their corresponding configurations found in stable +// configuration files public class Rule { private List selectors; private ConfigurationMap configuration; diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/StableConfigYaml.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/StableConfigYaml.java index 55dd65aa716..16c4c211f14 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/StableConfigYaml.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/StableConfigYaml.java @@ -1,6 +1,5 @@ package datadog.trace.bootstrap.config.provider.StableConfigYaml; -import datadog.trace.bootstrap.config.provider.ConfigurationMap; import java.util.ArrayList; import java.util.List; diff --git a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy index 17913ac49d3..e8919455f61 100644 --- a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy +++ b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy @@ -12,6 +12,7 @@ class StableConfigParserTest extends DDSpecification { if (filePath == null) { throw new AssertionError("Failed to create test file") } + // TODO: Test input with muiltiple selector-configuration sets. We always use the first matching selector String yaml = """ config_id: 12345 apm_configuration_default: diff --git a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigSourceTest.groovy b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigSourceTest.groovy index b285e47cacb..492f973882a 100644 --- a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigSourceTest.groovy +++ b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigSourceTest.groovy @@ -1,6 +1,7 @@ package datadog.trace.bootstrap.config.provider import datadog.trace.api.ConfigOrigin +import datadog.trace.bootstrap.config.provider.StableConfigYaml.ConfigurationMap import datadog.trace.bootstrap.config.provider.StableConfigYaml.StableConfigYaml import datadog.trace.test.util.DDSpecification import org.yaml.snakeyaml.DumperOptions @@ -140,31 +141,6 @@ class StableConfigSourceTest extends DDSpecification { return new Yaml(representer, options) } - // def generateYaml(configId, apmConfigurationDefault, apmConfigurationRules, miscData) { - // // Construct the YAML dynamically using GString interpolation - // def yaml = """ - //config_id: ${configId} - //apm_configuration_default: - // ${apmConfigurationDefault.collect { key, value -> "$key: $value" }.join("\n ")} - //apm_configuration_rules: - // ${apmConfigurationRules.collect { rule -> - // """ - // - selectors: - // ${rule.selectors.collect { selector -> - // """ - // - origin: ${selector.origin} - // matches: ${selector.matches.inspect()} - // operator: ${selector.operator} - // """.stripIndent() }.join("\n ")} - // configuration: - // ${rule.configuration.collect { key, value -> "$key: $value" }.join("\n ")} - // """.stripIndent() - // }.join("\n")} - //${miscData} - //""" - // return yaml - // } - def writeFileYaml(Path filePath, StableConfigYaml stableConfigs) { // Yaml yaml = getStableConfigYaml(); try (FileWriter writer = new FileWriter(filePath.toString())) { From 1bf6ccc97a2dae4512ae1f7804aea6638b5384eb Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Wed, 12 Mar 2025 14:06:36 -0400 Subject: [PATCH 17/98] Amend StableConfigParserTest valid test to include multiple selector-configuration sets --- .../provider/StableConfigParserTest.groovy | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy index e8919455f61..585ca7b1a94 100644 --- a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy +++ b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy @@ -12,13 +12,20 @@ class StableConfigParserTest extends DDSpecification { if (filePath == null) { throw new AssertionError("Failed to create test file") } - // TODO: Test input with muiltiple selector-configuration sets. We always use the first matching selector + injectEnvConfig("DD_SERVICE", "mysvc") + // From the below yaml, only apm_configuration_default and the second selector should be applied String yaml = """ config_id: 12345 apm_configuration_default: KEY_ONE: "default" KEY_TWO: true apm_configuration_rules: + - selectors: + - origin: language + matches: ["golang"] + operator: equals + configuration: + KEY_ONE: "ignored" - selectors: - origin: language matches: ["Java"] @@ -26,6 +33,13 @@ apm_configuration_rules: configuration: KEY_ONE: "rules" KEY_THREE: 1 + - selectors: + - origin: environment_variables + key: "DD_SERVICE" + operator: equals + matches: ["mysvc"] + configuration: + KEY_FOUR: "ignored" """ try { StableConfigSourceTest.writeFileRaw(filePath, yaml) From 57762b1750fa63deb275186fd02553924bc51031 Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Thu, 13 Mar 2025 14:21:32 -0400 Subject: [PATCH 18/98] nits/ cleanup --- .../config/provider/StableConfigParser.java | 8 ++-- .../config/provider/StableConfigSource.java | 11 +++++- .../ConfigurationMap.java | 13 ++++++- .../Rule.java | 13 ++++++- .../Selector.java | 17 +++++++- .../StableConfigYaml.java | 2 +- .../provider/StableConfigSourceTest.groovy | 39 +++++++++++++++---- 7 files changed, 84 insertions(+), 19 deletions(-) rename internal-api/src/main/java/datadog/trace/bootstrap/config/provider/{StableConfigYaml => stableconfigyaml}/ConfigurationMap.java (67%) rename internal-api/src/main/java/datadog/trace/bootstrap/config/provider/{StableConfigYaml => stableconfigyaml}/Rule.java (66%) rename internal-api/src/main/java/datadog/trace/bootstrap/config/provider/{StableConfigYaml => stableconfigyaml}/Selector.java (62%) rename internal-api/src/main/java/datadog/trace/bootstrap/config/provider/{StableConfigYaml => stableconfigyaml}/StableConfigYaml.java (94%) diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java index f53c5b537a0..ed50ed96e72 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java @@ -1,9 +1,9 @@ package datadog.trace.bootstrap.config.provider; -import datadog.trace.bootstrap.config.provider.StableConfigYaml.ConfigurationMap; -import datadog.trace.bootstrap.config.provider.StableConfigYaml.Rule; -import datadog.trace.bootstrap.config.provider.StableConfigYaml.Selector; -import datadog.trace.bootstrap.config.provider.StableConfigYaml.StableConfigYaml; +import datadog.trace.bootstrap.config.provider.stableconfigyaml.ConfigurationMap; +import datadog.trace.bootstrap.config.provider.stableconfigyaml.Rule; +import datadog.trace.bootstrap.config.provider.stableconfigyaml.Selector; +import datadog.trace.bootstrap.config.provider.stableconfigyaml.StableConfigYaml; import datadog.yaml.YamlParser; import java.io.IOException; import java.util.Collections; diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java index ff30321c5ae..5054620bac9 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java @@ -3,6 +3,7 @@ import static datadog.trace.util.Strings.propertyNameToEnvironmentVariableName; import datadog.trace.api.ConfigOrigin; +import java.io.File; import java.util.Collections; import java.util.Map; import java.util.Set; @@ -26,11 +27,17 @@ public final class StableConfigSource extends ConfigProvider.Source { private final StableConfig config; - StableConfigSource(String file, ConfigOrigin origin) { + StableConfigSource(String filePath, ConfigOrigin origin) { this.fileOrigin = origin; + File file = new File(filePath); + if (!file.exists()) { + log.debug("Stable configuration file not available at specified path: {}", file); + this.config = StableConfig.EMPTY; + return; + } StableConfig cfg; try { - cfg = StableConfigParser.parse(file); + cfg = StableConfigParser.parse(filePath); } catch (Throwable e) { log.debug("Stable configuration file not readable at specified path: {}", file); cfg = StableConfig.EMPTY; diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/ConfigurationMap.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/ConfigurationMap.java similarity index 67% rename from internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/ConfigurationMap.java rename to internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/ConfigurationMap.java index 527c0412332..d6b6911a1fe 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/ConfigurationMap.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/ConfigurationMap.java @@ -1,10 +1,19 @@ -package datadog.trace.bootstrap.config.provider.StableConfigYaml; +package datadog.trace.bootstrap.config.provider.stableconfigyaml; import java.util.HashMap; +import java.util.Map; // TODO: Update this comment from "stable configuration" to whatever product decides on for the name // ConfigurationMap represents configuration key-values found in stable configuration files -public class ConfigurationMap extends HashMap {} +public class ConfigurationMap extends HashMap { + public ConfigurationMap() { + return; + } + + public ConfigurationMap(Map map) { + super(map); + } +} class ConfigurationValue { private final String value; diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/Rule.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/Rule.java similarity index 66% rename from internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/Rule.java rename to internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/Rule.java index 4853f430a08..105e9919c97 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/Rule.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/Rule.java @@ -1,5 +1,6 @@ -package datadog.trace.bootstrap.config.provider.StableConfigYaml; +package datadog.trace.bootstrap.config.provider.stableconfigyaml; +import java.util.ArrayList; import java.util.List; // TODO: Update this comment from "stable configuration" to whatever product decides on for the name @@ -9,6 +10,16 @@ public class Rule { private List selectors; private ConfigurationMap configuration; + public Rule() { + this.selectors = new ArrayList<>(); + this.configuration = new ConfigurationMap(); + } + + public Rule(List selectors, ConfigurationMap configuration) { + this.selectors = selectors; + this.configuration = configuration; + } + // Getters and setters public List getSelectors() { return selectors; diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/Selector.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/Selector.java similarity index 62% rename from internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/Selector.java rename to internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/Selector.java index 634af44ae68..05ce5cb9c6b 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/Selector.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/Selector.java @@ -1,5 +1,6 @@ -package datadog.trace.bootstrap.config.provider.StableConfigYaml; +package datadog.trace.bootstrap.config.provider.stableconfigyaml; +import java.util.ArrayList; import java.util.List; public class Selector { @@ -8,6 +9,20 @@ public class Selector { private List matches; private String operator; + public Selector() { + this.origin = null; + this.key = null; + this.matches = new ArrayList<>(); + this.operator = null; + } + + public Selector(String origin, String key, List matches, String operator) { + this.origin = origin; + this.key = key; + this.matches = matches; + this.operator = operator; + } + // Getters and setters public String getOrigin() { return origin; diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/StableConfigYaml.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/StableConfigYaml.java similarity index 94% rename from internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/StableConfigYaml.java rename to internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/StableConfigYaml.java index 16c4c211f14..ec1a2816ed1 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigYaml/StableConfigYaml.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/StableConfigYaml.java @@ -1,4 +1,4 @@ -package datadog.trace.bootstrap.config.provider.StableConfigYaml; +package datadog.trace.bootstrap.config.provider.stableconfigyaml; import java.util.ArrayList; import java.util.List; diff --git a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigSourceTest.groovy b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigSourceTest.groovy index 492f973882a..80e5bd34a1b 100644 --- a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigSourceTest.groovy +++ b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigSourceTest.groovy @@ -1,8 +1,11 @@ package datadog.trace.bootstrap.config.provider import datadog.trace.api.ConfigOrigin -import datadog.trace.bootstrap.config.provider.StableConfigYaml.ConfigurationMap -import datadog.trace.bootstrap.config.provider.StableConfigYaml.StableConfigYaml +import datadog.trace.bootstrap.config.provider.stableconfigyaml.ConfigurationMap +import datadog.trace.bootstrap.config.provider.stableconfigyaml.ConfigurationValue +import datadog.trace.bootstrap.config.provider.stableconfigyaml.Rule +import datadog.trace.bootstrap.config.provider.stableconfigyaml.Selector +import datadog.trace.bootstrap.config.provider.stableconfigyaml.StableConfigYaml import datadog.trace.test.util.DDSpecification import org.yaml.snakeyaml.DumperOptions import org.yaml.snakeyaml.Yaml @@ -91,24 +94,44 @@ class StableConfigSourceTest extends DDSpecification { keyString = keyString.substring(4) // Cut `DD_` stableCfg.get(keyString) == defaultConfigs.get(key) } + // All configs from MatchingRule should be applied + if (ruleConfigs.contains(sampleMatchingRule)) { + for (key in sampleMatchingRule.getConfiguration().keySet()) { + String keyString = (String) key + keyString = keyString.substring(4) // Cut `DD_` + stableCfg.get(keyString) == defaultConfigs.get(key) + } + } + // None of the configs from NonMatchingRule should be applied + if (ruleConfigs.contains(sampleNonMatchingRule)) { + Set cfgKeys = stableCfg.getKeys() + for (key in sampleMatchingRule.getConfiguration().keySet()) { + String keyString = (String) key + keyString = keyString.substring(4) // Cut `DD_` + !cfgKeys.contains(keyString) + } + } Files.delete(filePath) where: - // TODO: Add ruleConfigs - configId | defaultConfigs - "" | new HashMap<>() - "12345" | new HashMap<>() << ["DD_KEY_ONE": "one", "DD_KEY_TWO": "two"] + configId | defaultConfigs | ruleConfigs + "" | new HashMap<>() | Arrays.asList(new Rule()) + "12345" | new HashMap<>() << ["DD_KEY_ONE": "one", "DD_KEY_TWO": "two"] | Arrays.asList(sampleMatchingRule, sampleNonMatchingRule) } // Corrupt YAML string variable used for testing, defined outside the 'where' block for readability - @Shared - def corruptYaml = ''' + def static corruptYaml = ''' abc: 123 def: ghi: "jkl" lmn: 456 ''' + // Matching and non-matching Rules used for testing, defined outside the 'where' block for readability + def static sampleMatchingRule = new Rule(Arrays.asList(new Selector("origin", "language", Arrays.asList("Java"), null)), new ConfigurationMap((Map)Map.of("DD_KEY_THREE", new ConfigurationValue("three")))) + def static sampleNonMatchingRule = new Rule(Arrays.asList(new Selector("origin", "language", Arrays.asList("Golang"), null)), new ConfigurationMap((Map)Map.of("DD_KEY_FOUR", new ConfigurationValue("four")))) + + // Helper functions static Path tempFile() { try { return Files.createTempFile("testFile_", ".yaml") From fe843e12dd3de0b31050219f97b3e8ef2925d8bb Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Thu, 13 Mar 2025 14:28:35 -0400 Subject: [PATCH 19/98] nits/ cleanup --- .../trace/bootstrap/config/provider/StableConfigSource.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java index 5054620bac9..ce5e61d09e5 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java @@ -79,7 +79,7 @@ public StableConfig(String configId, Map configMap) { public String get(String key) { Object value = this.apmConfiguration.get(key); // TODO: Handle this more safely, e.g. for an array - return (value != null) ? value.toString() : null; + return (value == null) ? null : value.toString(); } public Set getKeys() { From 55a798b56a8071d45ad25b3b3e4404479b653c1f Mon Sep 17 00:00:00 2001 From: Nikita Tkachenko <121111529+nikita-tkachenko-datadog@users.noreply.github.com> Date: Tue, 11 Mar 2025 10:30:53 +0100 Subject: [PATCH 20/98] Fix Test Optimization init when repo root cannot be determined (#8533) --- .../CiVisibilityRepoServices.java | 13 ++--- .../config/ExecutionSettingsFactoryImpl.java | 12 ++--- .../percentage/JacocoCoverageCalculator.java | 47 ++++++++++++++----- .../events/NoOpTestEventsHandler.java | 3 +- .../civisibility/git/tree/GitClient.java | 2 +- .../civisibility/git/tree/NoOpGitClient.java | 10 ++-- .../civisibility/git/tree/ShellGitClient.java | 13 +++-- .../index/CachingRepoIndexBuilderFactory.java | 3 +- .../source/index/RepoIndexBuilder.java | 3 +- .../source/index/RepoIndexProvider.java | 4 +- 10 files changed, 71 insertions(+), 39 deletions(-) diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/CiVisibilityRepoServices.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/CiVisibilityRepoServices.java index 6a269fa1964..6078e61880e 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/CiVisibilityRepoServices.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/CiVisibilityRepoServices.java @@ -39,6 +39,7 @@ import java.nio.file.Paths; import java.util.Map; import java.util.concurrent.CompletableFuture; +import javax.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -47,7 +48,7 @@ public class CiVisibilityRepoServices { private static final Logger LOGGER = LoggerFactory.getLogger(CiVisibilityRepoServices.class); - final String repoRoot; + @Nullable final String repoRoot; final String moduleName; final Provider ciProvider; final Map ciTags; @@ -135,7 +136,7 @@ private static String appendSlashIfNeeded(String repoRoot) { } } - static String getModuleName(Config config, String repoRoot, Path path) { + static String getModuleName(Config config, @Nullable String repoRoot, Path path) { // if parent process is instrumented, it will provide build system's module name String parentModuleName = config.getCiVisibilityModuleName(); if (parentModuleName != null) { @@ -175,7 +176,7 @@ private static ExecutionSettingsFactory buildExecutionSettingsFactory( GitRepoUnshallow gitRepoUnshallow, GitDataUploader gitDataUploader, PullRequestInfo pullRequestInfo, - String repoRoot) { + @Nullable String repoRoot) { ConfigurationApi configurationApi; if (backendApi == null) { LOGGER.warn( @@ -208,7 +209,7 @@ private static GitDataUploader buildGitDataUploader( GitClient gitClient, GitRepoUnshallow gitRepoUnshallow, BackendApi backendApi, - String repoRoot) { + @Nullable String repoRoot) { if (!config.isCiVisibilityGitUploadEnabled()) { return () -> CompletableFuture.completedFuture(null); } @@ -239,7 +240,7 @@ private static GitDataUploader buildGitDataUploader( } private static SourcePathResolver buildSourcePathResolver( - String repoRoot, RepoIndexProvider indexProvider) { + @Nullable String repoRoot, RepoIndexProvider indexProvider) { SourcePathResolver compilerAidedResolver = repoRoot != null ? new CompilerAidedSourcePathResolver(repoRoot) @@ -248,7 +249,7 @@ private static SourcePathResolver buildSourcePathResolver( return new BestEffortSourcePathResolver(compilerAidedResolver, indexResolver); } - private static Codeowners buildCodeowners(String repoRoot) { + private static Codeowners buildCodeowners(@Nullable String repoRoot) { if (repoRoot != null) { return new CodeownersProvider().build(repoRoot); } else { diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/config/ExecutionSettingsFactoryImpl.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/config/ExecutionSettingsFactoryImpl.java index cab997654b1..c0beee97019 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/config/ExecutionSettingsFactoryImpl.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/config/ExecutionSettingsFactoryImpl.java @@ -54,7 +54,7 @@ public class ExecutionSettingsFactoryImpl implements ExecutionSettingsFactory { private final GitRepoUnshallow gitRepoUnshallow; private final GitDataUploader gitDataUploader; private final PullRequestInfo pullRequestInfo; - private final String repositoryRoot; + @Nullable private final String repositoryRoot; public ExecutionSettingsFactoryImpl( Config config, @@ -63,7 +63,7 @@ public ExecutionSettingsFactoryImpl( GitRepoUnshallow gitRepoUnshallow, GitDataUploader gitDataUploader, PullRequestInfo pullRequestInfo, - String repositoryRoot) { + @Nullable String repositoryRoot) { this.config = config; this.configurationApi = configurationApi; this.gitClient = gitClient; @@ -75,21 +75,19 @@ public ExecutionSettingsFactoryImpl( /** @return Executions settings by module name */ public Map create(@Nonnull JvmInfo jvmInfo) { - TracerEnvironment tracerEnvironment = buildTracerEnvironment(repositoryRoot, jvmInfo, null); + TracerEnvironment tracerEnvironment = buildTracerEnvironment(jvmInfo, null); return create(tracerEnvironment); } @Override public ExecutionSettings create(@Nonnull JvmInfo jvmInfo, @Nullable String moduleName) { - TracerEnvironment tracerEnvironment = - buildTracerEnvironment(repositoryRoot, jvmInfo, moduleName); + TracerEnvironment tracerEnvironment = buildTracerEnvironment(jvmInfo, moduleName); Map settingsByModule = create(tracerEnvironment); ExecutionSettings settings = settingsByModule.get(moduleName); return settings != null ? settings : settingsByModule.get(DEFAULT_SETTINGS); } - private TracerEnvironment buildTracerEnvironment( - String repositoryRoot, JvmInfo jvmInfo, @Nullable String moduleName) { + private TracerEnvironment buildTracerEnvironment(JvmInfo jvmInfo, @Nullable String moduleName) { GitInfo gitInfo = GitInfoProvider.INSTANCE.getGitInfo(repositoryRoot); TracerEnvironment.Builder builder = TracerEnvironment.builder(); diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/coverage/percentage/JacocoCoverageCalculator.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/coverage/percentage/JacocoCoverageCalculator.java index b957575718e..c275d18a7eb 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/coverage/percentage/JacocoCoverageCalculator.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/coverage/percentage/JacocoCoverageCalculator.java @@ -19,6 +19,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.Reader; import java.nio.file.Files; import java.nio.file.Paths; import java.util.BitSet; @@ -42,6 +43,7 @@ import org.jacoco.core.data.SessionInfoStore; import org.jacoco.report.FileMultiReportOutput; import org.jacoco.report.IReportVisitor; +import org.jacoco.report.ISourceFileLocator; import org.jacoco.report.InputStreamSourceFileLocator; import org.jacoco.report.html.HTMLFormatter; import org.jacoco.report.xml.XMLFormatter; @@ -55,13 +57,13 @@ public static final class Factory implements CoverageCalculator.Factory { private final Config config; private final RepoIndexProvider repoIndexProvider; - private final String repoRoot; + @Nullable private final String repoRoot; private final ModuleSignalRouter moduleSignalRouter; public Factory( Config config, RepoIndexProvider repoIndexProvider, - String repoRoot, + @Nullable String repoRoot, ModuleSignalRouter moduleSignalRouter) { this.config = config; this.repoIndexProvider = repoIndexProvider; @@ -100,7 +102,7 @@ public JacocoCoverageCalculator moduleCoverage( private final RepoIndexProvider repoIndexProvider; - private final String repoRoot; + @Nullable private final String repoRoot; private final long eventId; @@ -116,7 +118,10 @@ public JacocoCoverageCalculator moduleCoverage( private final Collection outputClassesDirs = new HashSet<>(); private JacocoCoverageCalculator( - Config config, RepoIndexProvider repoIndexProvider, String repoRoot, long sessionId) { + Config config, + RepoIndexProvider repoIndexProvider, + @Nullable String repoRoot, + long sessionId) { this.parent = null; this.config = config; this.repoIndexProvider = repoIndexProvider; @@ -128,7 +133,7 @@ private JacocoCoverageCalculator( Config config, RepoIndexProvider repoIndexProvider, ExecutionSettings executionSettings, - String repoRoot, + @Nullable String repoRoot, long moduleId, @Nullable BuildModuleLayout moduleLayout, ModuleSignalRouter moduleSignalRouter, @@ -297,8 +302,7 @@ private void dumpCoverageReport(IBundleCoverage coverageBundle, File reportFolde final IReportVisitor htmlVisitor = htmlFormatter.createVisitor(new FileMultiReportOutput(reportFolder)); htmlVisitor.visitInfo(Collections.emptyList(), Collections.emptyList()); - htmlVisitor.visitBundle( - coverageBundle, new RepoIndexFileLocator(repoIndexProvider.getIndex(), repoRoot)); + htmlVisitor.visitBundle(coverageBundle, createSourceFileLocator()); htmlVisitor.visitEnd(); File xmlReport = new File(reportFolder, "jacoco.xml"); @@ -306,8 +310,7 @@ private void dumpCoverageReport(IBundleCoverage coverageBundle, File reportFolde XMLFormatter xmlFormatter = new XMLFormatter(); IReportVisitor xmlVisitor = xmlFormatter.createVisitor(xmlReportStream); xmlVisitor.visitInfo(Collections.emptyList(), Collections.emptyList()); - xmlVisitor.visitBundle( - coverageBundle, new RepoIndexFileLocator(repoIndexProvider.getIndex(), repoRoot)); + xmlVisitor.visitBundle(coverageBundle, createSourceFileLocator()); xmlVisitor.visitEnd(); } } catch (Exception e) { @@ -315,11 +318,17 @@ private void dumpCoverageReport(IBundleCoverage coverageBundle, File reportFolde } } + private ISourceFileLocator createSourceFileLocator() { + return repoRoot != null + ? new RepoIndexFileLocator(repoIndexProvider.getIndex(), repoRoot) + : NoOpFileLocator.INSTANCE; + } + private static final class RepoIndexFileLocator extends InputStreamSourceFileLocator { private final RepoIndex repoIndex; - private final String repoRoot; + @Nonnull private final String repoRoot; - private RepoIndexFileLocator(RepoIndex repoIndex, String repoRoot) { + private RepoIndexFileLocator(RepoIndex repoIndex, @Nonnull String repoRoot) { super("utf-8", 4); this.repoIndex = repoIndex; this.repoRoot = repoRoot; @@ -343,6 +352,22 @@ protected InputStream getSourceStream(String path) throws IOException { } } + private static final class NoOpFileLocator implements ISourceFileLocator { + private static final NoOpFileLocator INSTANCE = new NoOpFileLocator(); + + private NoOpFileLocator() {} + + @Override + public Reader getSourceFile(String s, String s1) { + return null; + } + + @Override + public int getTabWidth() { + return 0; + } + } + private long getCoveragePercentage(IBundleCoverage coverageBundle) { if (backendCoverageData.isEmpty()) { return getLocalCoveragePercentage(coverageBundle); diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/events/NoOpTestEventsHandler.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/events/NoOpTestEventsHandler.java index cd7d292aab6..99ac9994829 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/events/NoOpTestEventsHandler.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/events/NoOpTestEventsHandler.java @@ -15,7 +15,6 @@ import java.util.Collection; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import org.jetbrains.annotations.NotNull; public class NoOpTestEventsHandler implements TestEventsHandler { @@ -99,7 +98,7 @@ public SkipReason skipReason(TestIdentifier test) { return null; } - @NotNull + @Nonnull @Override public TestExecutionPolicy executionPolicy( TestIdentifier test, TestSourceData source, Collection testTags) { diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/GitClient.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/GitClient.java index a6bffa37771..41e9cc9ee10 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/GitClient.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/GitClient.java @@ -77,6 +77,6 @@ LineDiff getGitDiff(String baseCommit, String targetCommit) throws IOException, TimeoutException, InterruptedException; interface Factory { - GitClient create(String repoRoot); + GitClient create(@Nullable String repoRoot); } } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/NoOpGitClient.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/NoOpGitClient.java index 2e09358c40b..c030fc7442f 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/NoOpGitClient.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/NoOpGitClient.java @@ -5,8 +5,8 @@ import java.util.Collection; import java.util.Collections; import java.util.List; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; public class NoOpGitClient implements GitClient { @@ -54,7 +54,7 @@ public String getCurrentBranch() { return null; } - @NotNull + @Nonnull @Override public List getTags(String commit) { return Collections.emptyList(); @@ -108,13 +108,13 @@ public String getCommitterDate(String commit) { return null; } - @NotNull + @Nonnull @Override public List getLatestCommits() { return Collections.emptyList(); } - @NotNull + @Nonnull @Override public List getObjects( Collection commitsToSkip, Collection commitsToInclude) { diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/ShellGitClient.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/ShellGitClient.java index 56c3cb4949d..4d78112a646 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/ShellGitClient.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/git/tree/ShellGitClient.java @@ -51,7 +51,7 @@ public class ShellGitClient implements GitClient { */ ShellGitClient( CiVisibilityMetricCollector metricCollector, - String repoRoot, + @Nonnull String repoRoot, String latestCommitsSince, int latestCommitsLimit, long timeoutMillis) { @@ -651,10 +651,15 @@ public Factory(Config config, CiVisibilityMetricCollector metricCollector) { } @Override - public GitClient create(String repoRoot) { + public GitClient create(@Nullable String repoRoot) { long commandTimeoutMillis = config.getCiVisibilityGitCommandTimeoutMillis(); - return new ShellGitClient( - metricCollector, repoRoot, "1 month ago", 1000, commandTimeoutMillis); + if (repoRoot != null) { + return new ShellGitClient( + metricCollector, repoRoot, "1 month ago", 1000, commandTimeoutMillis); + } else { + LOGGER.debug("Could not determine repository root, using no-op git client"); + return NoOpGitClient.INSTANCE; + } } } } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/source/index/CachingRepoIndexBuilderFactory.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/source/index/CachingRepoIndexBuilderFactory.java index d3b34ebbba2..152422f6efe 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/source/index/CachingRepoIndexBuilderFactory.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/source/index/CachingRepoIndexBuilderFactory.java @@ -4,6 +4,7 @@ import datadog.trace.api.cache.DDCache; import datadog.trace.api.cache.DDCaches; import java.nio.file.FileSystem; +import javax.annotation.Nullable; public class CachingRepoIndexBuilderFactory implements RepoIndexProvider.Factory { @@ -25,7 +26,7 @@ public CachingRepoIndexBuilderFactory( } @Override - public RepoIndexProvider create(String repoRoot) { + public RepoIndexProvider create(@Nullable String repoRoot) { if (repoRoot == null) { return () -> RepoIndex.EMPTY; } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/source/index/RepoIndexBuilder.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/source/index/RepoIndexBuilder.java index b5253ae0738..805cb4e56c1 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/source/index/RepoIndexBuilder.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/source/index/RepoIndexBuilder.java @@ -19,6 +19,7 @@ import java.util.HashSet; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; +import javax.annotation.Nonnull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,7 +38,7 @@ public class RepoIndexBuilder implements RepoIndexProvider { public RepoIndexBuilder( Config config, - String repoRoot, + @Nonnull String repoRoot, PackageResolver packageResolver, ResourceResolver resourceResolver, FileSystem fileSystem) { diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/source/index/RepoIndexProvider.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/source/index/RepoIndexProvider.java index 0a012c9516b..0244526b105 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/source/index/RepoIndexProvider.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/source/index/RepoIndexProvider.java @@ -1,9 +1,11 @@ package datadog.trace.civisibility.source.index; +import javax.annotation.Nullable; + public interface RepoIndexProvider { RepoIndex getIndex(); interface Factory { - RepoIndexProvider create(String repoRoot); + RepoIndexProvider create(@Nullable String repoRoot); } } From cdd201021a821e75de7e5599c3b1fe69f42c4445 Mon Sep 17 00:00:00 2001 From: Bruce Bujon Date: Tue, 11 Mar 2025 16:36:04 +0100 Subject: [PATCH 21/98] Improve Baggage API (#8523) * feat(internal-api): Improve Baggage API * feat(internal-api): Add Baggage unit tests --- .../trace/core/baggage/BaggagePropagator.java | 98 +++++++------- .../datadog/trace/core/util/EscapedData.java | 36 ------ .../trace/core/util/PercentEscaper.java | 42 +++--- .../core/baggage/BaggagePropagatorTest.groovy | 25 ++-- internal-api/build.gradle | 2 - .../instrumentation/api/Baggage.java | 122 ++++++++++++++++++ .../instrumentation/api/BaggageContext.java | 74 ----------- .../instrumentation/api/BaggageTest.groovy | 88 +++++++++++++ 8 files changed, 295 insertions(+), 192 deletions(-) delete mode 100644 dd-trace-core/src/main/java/datadog/trace/core/util/EscapedData.java create mode 100644 internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/Baggage.java delete mode 100644 internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/BaggageContext.java create mode 100644 internal-api/src/test/groovy/datadog/trace/bootstrap/instrumentation/api/BaggageTest.groovy diff --git a/dd-trace-core/src/main/java/datadog/trace/core/baggage/BaggagePropagator.java b/dd-trace-core/src/main/java/datadog/trace/core/baggage/BaggagePropagator.java index 67f8702291e..e203a1722db 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/baggage/BaggagePropagator.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/baggage/BaggagePropagator.java @@ -1,16 +1,17 @@ package datadog.trace.core.baggage; +import static java.util.Collections.emptyMap; + import datadog.context.Context; import datadog.context.propagation.CarrierSetter; import datadog.context.propagation.CarrierVisitor; import datadog.context.propagation.Propagator; import datadog.trace.api.Config; -import datadog.trace.bootstrap.instrumentation.api.BaggageContext; -import datadog.trace.core.util.EscapedData; +import datadog.trace.bootstrap.instrumentation.api.Baggage; import datadog.trace.core.util.PercentEscaper; +import datadog.trace.core.util.PercentEscaper.Escaped; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; -import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.function.BiConsumer; @@ -20,7 +21,7 @@ @ParametersAreNonnullByDefault public class BaggagePropagator implements Propagator { - private static final Logger log = LoggerFactory.getLogger(BaggagePropagator.class); + private static final Logger LOG = LoggerFactory.getLogger(BaggagePropagator.class); private static final PercentEscaper UTF_ESCAPER = PercentEscaper.create(); static final String BAGGAGE_KEY = "baggage"; private final Config config; @@ -37,13 +38,13 @@ public BaggagePropagator(Config config) { public BaggagePropagator(boolean injectBaggage, boolean extractBaggage) { this.injectBaggage = injectBaggage; this.extractBaggage = extractBaggage; - config = Config.get(); + this.config = Config.get(); } @Override public void inject(Context context, C carrier, CarrierSetter setter) { - int maxItems = config.getTraceBaggageMaxItems(); - int maxBytes = config.getTraceBaggageMaxBytes(); + int maxItems = this.config.getTraceBaggageMaxItems(); + int maxBytes = this.config.getTraceBaggageMaxBytes(); //noinspection ConstantValue if (!this.injectBaggage || maxItems == 0 @@ -54,52 +55,52 @@ public void inject(Context context, C carrier, CarrierSetter setter) { return; } - BaggageContext baggageContext = BaggageContext.fromContext(context); - if (baggageContext == null) { - log.debug("BaggageContext instance is missing from the following context {}", context); + Baggage baggage = Baggage.fromContext(context); + if (baggage == null) { + LOG.debug("Baggage instance is missing from the following context {}", context); return; } - String baggageHeader = baggageContext.getW3cBaggageHeader(); - if (baggageHeader != null) { - setter.set(carrier, BAGGAGE_KEY, baggageHeader); + String headerValue = baggage.getW3cHeader(); + if (headerValue != null) { + setter.set(carrier, BAGGAGE_KEY, headerValue); return; } - int processedBaggage = 0; + int processedItems = 0; int currentBytes = 0; StringBuilder baggageText = new StringBuilder(); - for (final Map.Entry entry : baggageContext.asMap().entrySet()) { + for (final Map.Entry entry : baggage.asMap().entrySet()) { // if there are already baggage items processed, add and allocate bytes for a comma int extraBytes = 1; - if (processedBaggage != 0) { + if (processedItems != 0) { baggageText.append(','); extraBytes++; } - EscapedData escapedKey = UTF_ESCAPER.escapeKey(entry.getKey()); - EscapedData escapedVal = UTF_ESCAPER.escapeValue(entry.getValue()); + Escaped escapedKey = UTF_ESCAPER.escapeKey(entry.getKey()); + Escaped escapedVal = UTF_ESCAPER.escapeValue(entry.getValue()); - baggageText.append(escapedKey.getData()); + baggageText.append(escapedKey.data); baggageText.append('='); - baggageText.append(escapedVal.getData()); + baggageText.append(escapedVal.data); - processedBaggage++; + processedItems++; // reached the max number of baggage items allowed - if (processedBaggage == maxItems) { + if (processedItems == maxItems) { break; } // Drop newest k/v pair if adding it leads to exceeding the limit - if (currentBytes + escapedKey.getSize() + escapedVal.getSize() + extraBytes > maxBytes) { + if (currentBytes + escapedKey.size + escapedVal.size + extraBytes > maxBytes) { baggageText.setLength(currentBytes); break; } - currentBytes += escapedKey.getSize() + escapedVal.getSize() + extraBytes; + currentBytes += escapedKey.size + escapedVal.size + extraBytes; } - String baggageString = baggageText.toString(); - baggageContext.setW3cBaggageHeader(baggageString); - setter.set(carrier, BAGGAGE_KEY, baggageString); + headerValue = baggageText.toString(); + baggage.setW3cHeader(headerValue); + setter.set(carrier, BAGGAGE_KEY, headerValue); } @Override @@ -108,19 +109,17 @@ public Context extract(Context context, C carrier, CarrierVisitor visitor if (!this.extractBaggage || context == null || carrier == null || visitor == null) { return context; } - BaggageContextExtractor baggageContextExtractor = new BaggageContextExtractor(); - visitor.forEachKeyValue(carrier, baggageContextExtractor); - BaggageContext extractedContext = baggageContextExtractor.extractedContext; - if (extractedContext == null) { - return context; - } - return extractedContext.storeInto(context); + BaggageExtractor baggageExtractor = new BaggageExtractor(); + visitor.forEachKeyValue(carrier, baggageExtractor); + return baggageExtractor.extracted == null ? context : context.with(baggageExtractor.extracted); } - public static class BaggageContextExtractor implements BiConsumer { - private BaggageContext extractedContext; + private static class BaggageExtractor implements BiConsumer { + private static final char KEY_VALUE_SEPARATOR = '='; + private static final char PAIR_SEPARATOR = ','; + private Baggage extracted; - BaggageContextExtractor() {} + private BaggageExtractor() {} /** URL decode value */ private String decode(final String value) { @@ -128,37 +127,34 @@ private String decode(final String value) { try { decoded = URLDecoder.decode(value, "UTF-8"); } catch (final UnsupportedEncodingException | IllegalArgumentException e) { - log.debug("Failed to decode {}", value); + LOG.debug("Failed to decode {}", value); } return decoded; } private Map parseBaggageHeaders(String input) { Map baggage = new HashMap<>(); - char keyValueSeparator = '='; - char pairSeparator = ','; int start = 0; - - int pairSeparatorInd = input.indexOf(pairSeparator); + int pairSeparatorInd = input.indexOf(PAIR_SEPARATOR); pairSeparatorInd = pairSeparatorInd == -1 ? input.length() : pairSeparatorInd; - int kvSeparatorInd = input.indexOf(keyValueSeparator); + int kvSeparatorInd = input.indexOf(KEY_VALUE_SEPARATOR); while (kvSeparatorInd != -1) { int end = pairSeparatorInd; if (kvSeparatorInd > end) { - log.debug( + LOG.debug( "Dropping baggage headers due to key with no value {}", input.substring(start, end)); - return Collections.emptyMap(); + return emptyMap(); } String key = decode(input.substring(start, kvSeparatorInd).trim()); String value = decode(input.substring(kvSeparatorInd + 1, end).trim()); if (key.isEmpty() || value.isEmpty()) { - log.debug("Dropping baggage headers due to empty k/v {}:{}", key, value); - return Collections.emptyMap(); + LOG.debug("Dropping baggage headers due to empty k/v {}:{}", key, value); + return emptyMap(); } baggage.put(key, value); - kvSeparatorInd = input.indexOf(keyValueSeparator, pairSeparatorInd + 1); - pairSeparatorInd = input.indexOf(pairSeparator, pairSeparatorInd + 1); + kvSeparatorInd = input.indexOf(KEY_VALUE_SEPARATOR, pairSeparatorInd + 1); + pairSeparatorInd = input.indexOf(PAIR_SEPARATOR, pairSeparatorInd + 1); pairSeparatorInd = pairSeparatorInd == -1 ? input.length() : pairSeparatorInd; start = end + 1; } @@ -168,10 +164,10 @@ private Map parseBaggageHeaders(String input) { @Override public void accept(String key, String value) { // Only process tags that are relevant to baggage - if (key != null && key.equalsIgnoreCase(BAGGAGE_KEY)) { + if (BAGGAGE_KEY.equalsIgnoreCase(key)) { Map baggage = parseBaggageHeaders(value); if (!baggage.isEmpty()) { - extractedContext = BaggageContext.create(baggage, value); + this.extracted = Baggage.create(baggage, value); } } } diff --git a/dd-trace-core/src/main/java/datadog/trace/core/util/EscapedData.java b/dd-trace-core/src/main/java/datadog/trace/core/util/EscapedData.java deleted file mode 100644 index 0ff428d2f60..00000000000 --- a/dd-trace-core/src/main/java/datadog/trace/core/util/EscapedData.java +++ /dev/null @@ -1,36 +0,0 @@ -package datadog.trace.core.util; - -public class EscapedData { - private String data; - private int size; - - public EscapedData(String data, int size) { - this.data = data; - this.size = size; - } - - public EscapedData() { - this.data = ""; - this.size = 0; - } - - public String getData() { - return data; - } - - public int getSize() { - return size; - } - - public void setData(String data) { - this.data = data; - } - - public void incrementSize() { - size++; - } - - public void addSize(int delta) { - size += delta; - } -} diff --git a/dd-trace-core/src/main/java/datadog/trace/core/util/PercentEscaper.java b/dd-trace-core/src/main/java/datadog/trace/core/util/PercentEscaper.java index 8bd6a7b21d5..c32036713ad 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/util/PercentEscaper.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/util/PercentEscaper.java @@ -107,17 +107,16 @@ private static boolean[] createUnsafeOctets(String safeChars) { return octets; } - public EscapedData escapeKey(String s) { + public Escaped escapeKey(String s) { return escape(s, unsafeKeyOctets); } - public EscapedData escapeValue(String s) { + public Escaped escapeValue(String s) { return escape(s, unsafeValOctets); } /** Escape the provided String, using percent-style URL Encoding. */ - public EscapedData escape(String s, boolean[] unsafeOctets) { - int size = 0; + public Escaped escape(String s, boolean[] unsafeOctets) { int slen = s.length(); for (int index = 0; index < slen; index++) { char c = s.charAt(index); @@ -125,7 +124,7 @@ public EscapedData escape(String s, boolean[] unsafeOctets) { return escapeSlow(s, index, unsafeOctets); } } - return new EscapedData(s, slen); + return new Escaped(s, slen); } /* @@ -147,14 +146,14 @@ public EscapedData escape(String s, boolean[] unsafeOctets) { * @throws NullPointerException if {@code string} is null * @throws IllegalArgumentException if invalid surrogate characters are encountered */ - private static EscapedData escapeSlow(String s, int index, boolean[] unsafeOctets) { + private static Escaped escapeSlow(String s, int index, boolean[] unsafeOctets) { int end = s.length(); // Get a destination buffer and setup some loop variables. char[] dest = new char[1024]; // 1024 from the original guava source int destIndex = 0; int unescapedChunkStart = 0; - EscapedData data = new EscapedData("", index); + Escaped result = new Escaped("", index); while (index < end) { int cp = codePointAt(s, index, end); @@ -164,7 +163,7 @@ private static EscapedData escapeSlow(String s, int index, boolean[] unsafeOctet // It is possible for this to return null because nextEscapeIndex() may // (for performance reasons) yield some false positives but it must never // give false negatives. - char[] escaped = escape(cp, data, unsafeOctets); + char[] escaped = escape(cp, result, unsafeOctets); int nextIndex = index + (Character.isSupplementaryCodePoint(cp) ? 2 : 1); if (escaped != null) { int charsSkipped = index - unescapedChunkStart; @@ -202,10 +201,11 @@ private static EscapedData escapeSlow(String s, int index, boolean[] unsafeOctet s.getChars(unescapedChunkStart, end, dest, destIndex); destIndex = endIndex; } - data.addSize(charsSkipped); // Adding characters in-between characters that want to be encoded + // Adding characters in-between characters that want to be encoded + result.size += charsSkipped; - data.setData(new String(dest, 0, destIndex)); - return data; + result.data = new String(dest, 0, destIndex); + return result; } private static int nextEscapeIndex(CharSequence csq, int index, int end, boolean[] unsafeOctets) { @@ -221,7 +221,7 @@ private static int nextEscapeIndex(CharSequence csq, int index, int end, boolean /** Escapes the given Unicode code point in UTF-8. */ @CheckForNull @SuppressWarnings("UngroupedOverloads") - private static char[] escape(int cp, EscapedData data, boolean[] unsafeOctets) { + private static char[] escape(int cp, Escaped escaped, boolean[] unsafeOctets) { // We should never get negative values here but if we do it will throw an // IndexOutOfBoundsException, so at least it will get spotted. if (cp < unsafeOctets.length && !unsafeOctets[cp]) { @@ -233,7 +233,7 @@ private static char[] escape(int cp, EscapedData data, boolean[] unsafeOctets) { dest[0] = '%'; dest[2] = UPPER_HEX_DIGITS[cp & 0xF]; dest[1] = UPPER_HEX_DIGITS[cp >>> 4]; - data.incrementSize(); + escaped.size++; return dest; } else if (cp <= 0x7ff) { // Two byte UTF-8 characters [cp >= 0x80 && cp <= 0x7ff] @@ -248,7 +248,7 @@ private static char[] escape(int cp, EscapedData data, boolean[] unsafeOctets) { dest[2] = UPPER_HEX_DIGITS[cp & 0xF]; cp >>>= 4; dest[1] = UPPER_HEX_DIGITS[0xC | cp]; - data.addSize(2); + escaped.size += 2; return dest; } else if (cp <= 0xffff) { // Three byte UTF-8 characters [cp >= 0x800 && cp <= 0xffff] @@ -267,7 +267,7 @@ private static char[] escape(int cp, EscapedData data, boolean[] unsafeOctets) { dest[4] = UPPER_HEX_DIGITS[0x8 | (cp & 0x3)]; cp >>>= 2; dest[2] = UPPER_HEX_DIGITS[cp]; - data.addSize(3); + escaped.size += 3; return dest; } else if (cp <= 0x10ffff) { char[] dest = new char[12]; @@ -291,7 +291,7 @@ private static char[] escape(int cp, EscapedData data, boolean[] unsafeOctets) { dest[4] = UPPER_HEX_DIGITS[0x8 | (cp & 0x3)]; cp >>>= 2; dest[2] = UPPER_HEX_DIGITS[cp & 0x7]; - data.addSize(4); + escaped.size += 4; return dest; } else { // If this ever happens it is due to bug in UnicodeEscaper, not bad input. @@ -386,4 +386,14 @@ private static char[] growBuffer(char[] dest, int index, int size) { } return copy; } + + public static class Escaped { + public String data; + public int size; + + public Escaped(String data, int size) { + this.data = data; + this.size = size; + } + } } diff --git a/dd-trace-core/src/test/groovy/datadog/trace/core/baggage/BaggagePropagatorTest.groovy b/dd-trace-core/src/test/groovy/datadog/trace/core/baggage/BaggagePropagatorTest.groovy index 56a16cc376f..4910898c047 100644 --- a/dd-trace-core/src/test/groovy/datadog/trace/core/baggage/BaggagePropagatorTest.groovy +++ b/dd-trace-core/src/test/groovy/datadog/trace/core/baggage/BaggagePropagatorTest.groovy @@ -3,21 +3,20 @@ package datadog.trace.core.baggage import datadog.context.Context import datadog.context.propagation.CarrierSetter import datadog.context.propagation.CarrierVisitor -import datadog.trace.bootstrap.instrumentation.api.BaggageContext +import datadog.trace.bootstrap.instrumentation.api.Baggage import datadog.trace.bootstrap.instrumentation.api.ContextVisitors -import datadog.trace.core.test.DDCoreSpecification +import datadog.trace.test.util.DDSpecification import java.util.function.BiConsumer import static datadog.trace.core.baggage.BaggagePropagator.BAGGAGE_KEY -class BaggagePropagatorTest extends DDCoreSpecification { +class BaggagePropagatorTest extends DDSpecification { BaggagePropagator propagator CarrierSetter setter Map carrier Context context - static class MapCarrierAccessor implements CarrierSetter>, CarrierVisitor> { @Override @@ -35,14 +34,14 @@ class BaggagePropagatorTest extends DDCoreSpecification { def setup() { this.propagator = new BaggagePropagator(true, true) - setter = new MapCarrierAccessor() - carrier = [:] - context = Context.root() + this.setter = new MapCarrierAccessor() + this.carrier = [:] + this.context = Context.root() } def 'test baggage propagator context injection'() { setup: - context = BaggageContext.create(baggageMap).storeInto(context) + this.context = Baggage.create(baggageMap).storeInto(this.context) when: this.propagator.inject(context, carrier, setter) @@ -66,7 +65,7 @@ class BaggagePropagatorTest extends DDCoreSpecification { setup: injectSysConfig("trace.baggage.max.items", '2') propagator = new BaggagePropagator(true, true) //creating a new instance after injecting config - context = BaggageContext.create(baggage).storeInto(context) + context = Baggage.create(baggage).storeInto(context) when: this.propagator.inject(context, carrier, setter) @@ -84,7 +83,7 @@ class BaggagePropagatorTest extends DDCoreSpecification { setup: injectSysConfig("trace.baggage.max.bytes", '20') propagator = new BaggagePropagator(true, true) //creating a new instance after injecting config - context = BaggageContext.create(baggage).storeInto(context) + context = Baggage.create(baggage).storeInto(context) when: this.propagator.inject(context, carrier, setter) @@ -109,7 +108,7 @@ class BaggagePropagatorTest extends DDCoreSpecification { context = this.propagator.extract(context, headers, ContextVisitors.stringValuesMap()) then: - BaggageContext.fromContext(context).asMap() == baggageMap + Baggage.fromContext(context).asMap() == baggageMap where: baggageHeader | baggageMap @@ -127,7 +126,7 @@ class BaggagePropagatorTest extends DDCoreSpecification { context = this.propagator.extract(context, headers, ContextVisitors.stringValuesMap()) then: - BaggageContext.fromContext(context) == null + Baggage.fromContext(context) == null where: baggageHeader | _ @@ -150,7 +149,7 @@ class BaggagePropagatorTest extends DDCoreSpecification { context = this.propagator.extract(context, headers, ContextVisitors.stringValuesMap()) then: - BaggageContext baggageContext = BaggageContext.fromContext(context) + Baggage baggageContext = Baggage.fromContext(context) baggageContext.asMap() == baggageMap when: diff --git a/internal-api/build.gradle b/internal-api/build.gradle index e9fff4e2686..cb72af95b17 100644 --- a/internal-api/build.gradle +++ b/internal-api/build.gradle @@ -189,8 +189,6 @@ excludedClassesCoverage += [ "datadog.trace.api.iast.Taintable", "datadog.trace.api.Stateful", "datadog.trace.api.Stateful.1", - // BaggageContext class tested in BaggagePropagatorTest in dd-trace-core - 'datadog.trace.bootstrap.instrumentation.api.BaggageContext', // a stub "datadog.trace.bootstrap.instrumentation.api.ProfilingContextIntegration", "datadog.trace.bootstrap.instrumentation.api.ProfilingContextIntegration.NoOp", diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/Baggage.java b/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/Baggage.java new file mode 100644 index 00000000000..e6ce2f73751 --- /dev/null +++ b/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/Baggage.java @@ -0,0 +1,122 @@ +package datadog.trace.bootstrap.instrumentation.api; + +import static datadog.context.ContextKey.named; +import static java.util.Collections.unmodifiableMap; + +import datadog.context.Context; +import datadog.context.ContextKey; +import datadog.context.ImplicitContextKeyed; +import java.util.HashMap; +import java.util.Map; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** Baggage are key/value store which propagate alongside {@link Context}. */ +public class Baggage implements ImplicitContextKeyed { + private static final ContextKey CONTEXT_KEY = named("baggage-key"); + private final Map items; + /** + * The W3C Baggage header representation of the + * baggage instance, {@code null} if not in sync with the current baggage items. + */ + private String w3cHeader; + + /** + * Gets baggage from context. + * + * @param context The context to get baggage from. + * @return The baggage from the given context if any, {@code null} if none. + */ + public static @Nullable Baggage fromContext(Context context) { + return context.get(CONTEXT_KEY); + } + + /** + * Create empty baggage. + * + * @return Empty baggage. + */ + public static Baggage empty() { + return create(new HashMap<>(), ""); + } + + /** + * Create baggage from items. + * + * @param items The original baggage items. + * @return Baggage with the given items. + */ + public static Baggage create(Map items) { + return new Baggage(items, null); + } + + /** + * Create baggage from items. + * + * @param items The original baggage items. + * @param w3cHeader The W3C Baggage header representation. + * @return Baggage with the given items and its W3C header cached. + */ + public static Baggage create(Map items, String w3cHeader) { + return new Baggage(items, w3cHeader); + } + + private Baggage(Map items, String w3cHeader) { + this.items = items; + this.w3cHeader = w3cHeader; + } + + /** + * Adds a baggage item. + * + * @param key The item key. + * @param value The item value. + */ + public void addItem(String key, String value) { + this.items.put(key, value); + this.w3cHeader = null; + } + + /** + * Removes a baggage item. + * + * @param key The item key to remove. + */ + public void removeItem(String key) { + if (this.items.remove(key) != null) { + this.w3cHeader = null; + } + } + + /** + * Gets the W3C Baggage header representation. + * + * @return The header value, {@code null} if not in sync with the current baggage items. + */ + public @Nullable String getW3cHeader() { + return this.w3cHeader; + } + + /** + * Updates the W3C Baggage header representation. + * + * @param w3cHeader The header value. + */ + public void setW3cHeader(String w3cHeader) { + this.w3cHeader = w3cHeader; + } + + /** + * Gets a view of the baggage items. + * + * @return The read-only view of the baggage items. + */ + public Map asMap() { + return unmodifiableMap(this.items); + } + + @Override + public Context storeInto(@Nonnull Context context) { + return context.with(CONTEXT_KEY, this); + } +} diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/BaggageContext.java b/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/BaggageContext.java deleted file mode 100644 index 99048f7a107..00000000000 --- a/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/BaggageContext.java +++ /dev/null @@ -1,74 +0,0 @@ -package datadog.trace.bootstrap.instrumentation.api; - -import datadog.context.Context; -import datadog.context.ContextKey; -import datadog.context.ImplicitContextKeyed; -import java.util.HashMap; -import java.util.Map; - -public class BaggageContext implements ImplicitContextKeyed { - private static final ContextKey CONTEXT_KEY = ContextKey.named("baggage-key"); - - private final Map baggage; - private String baggageString; - private boolean updatedCache; - - public BaggageContext empty() { - return create(new HashMap<>(), ""); - } - - public static BaggageContext create(Map baggage) { - return new BaggageContext(baggage); - } - - private BaggageContext(Map baggage) { - this.baggage = baggage; - this.baggageString = ""; - updatedCache = false; - } - - public static BaggageContext create(Map baggage, String w3cHeader) { - return new BaggageContext(baggage, w3cHeader); - } - - private BaggageContext(Map baggage, String baggageString) { - this.baggage = baggage; - this.baggageString = baggageString; - updatedCache = true; - } - - public void addW3CBaggage(String key, String value) { - baggage.put(key, value); - updatedCache = false; - } - - public void removeW3CBaggage(String key) { - baggage.remove(key); - updatedCache = false; - } - - public void setW3cBaggageHeader(String w3cHeader) { - this.baggageString = w3cHeader; - updatedCache = true; - } - - public String getW3cBaggageHeader() { - if (updatedCache) { - return baggageString; - } - return null; - } - - public Map asMap() { - return new HashMap<>(baggage); - } - - public static BaggageContext fromContext(Context context) { - return context.get(CONTEXT_KEY); - } - - @Override - public Context storeInto(Context context) { - return context.with(CONTEXT_KEY, this); - } -} diff --git a/internal-api/src/test/groovy/datadog/trace/bootstrap/instrumentation/api/BaggageTest.groovy b/internal-api/src/test/groovy/datadog/trace/bootstrap/instrumentation/api/BaggageTest.groovy new file mode 100644 index 00000000000..7611a87b407 --- /dev/null +++ b/internal-api/src/test/groovy/datadog/trace/bootstrap/instrumentation/api/BaggageTest.groovy @@ -0,0 +1,88 @@ +package datadog.trace.bootstrap.instrumentation.api + +import datadog.context.Context +import spock.lang.Specification + +class BaggageTest extends Specification { + def 'test empty baggage'() { + when: + def baggage = Baggage.empty() + + then: + baggage.asMap().isEmpty() + baggage.w3cHeader != null + baggage.w3cHeader.isEmpty() + + when: + baggage.addItem('key', 'value') + + then: + baggage.w3cHeader == null + } + + def 'test baggage creation'() { + setup: + def items = ['key1': 'value1', 'key2': 'value2'] + def header = 'key1=value1,key2=value2' + + when: + def baggage = Baggage.create(items) + + then: + baggage.asMap() == items + baggage.w3cHeader == null + + when: + baggage = Baggage.create(items, header) + + then: + baggage.asMap() == items + baggage.w3cHeader == header + } + + def 'test baggage header'() { + setup: + def items = ['key1': 'value1', 'key2': 'value2'] + def header = 'key1=value1,key2=value2' + def baggage = Baggage.create(items, header) + + when: + baggage.removeItem('missingKey') + + then: 'header is preserved' + baggage.w3cHeader == header + + when: + baggage.removeItem('key2') + + then: 'header is out of sync' + baggage.w3cHeader == null + + when: + baggage.w3cHeader = 'key1=value1' + + then: 'header is forced' + baggage.w3cHeader == 'key1=value1' + + when: + baggage.addItem('key3', 'value3') + + then: 'header is out of sync' + baggage.w3cHeader == null + } + + def 'test context storage'() { + given: + def baggage = Baggage.empty() + def context = Context.root() + + expect: + Baggage.fromContext(context) == null + + when: + context = context.with(baggage) + + then: + Baggage.fromContext(context) == baggage + } +} From 9a4458a48e6687ee7e02738302264a7d6d78035c Mon Sep 17 00:00:00 2001 From: mhlidd Date: Tue, 11 Mar 2025 15:07:26 -0400 Subject: [PATCH 22/98] Update system-tests to 5aee0ed598fd984344cf0da0048b27bdb2eb4da1 (#8537) --- .circleci/config.continue.yml.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.continue.yml.j2 b/.circleci/config.continue.yml.j2 index f0eecdc4850..8029d84fb12 100644 --- a/.circleci/config.continue.yml.j2 +++ b/.circleci/config.continue.yml.j2 @@ -36,7 +36,7 @@ instrumentation_modules: &instrumentation_modules "dd-java-agent/instrumentation debugger_modules: &debugger_modules "dd-java-agent/agent-debugger|dd-java-agent/agent-bootstrap|dd-java-agent/agent-builder|internal-api|communication|dd-trace-core" profiling_modules: &profiling_modules "dd-java-agent/agent-profiling" -default_system_tests_commit: &default_system_tests_commit 590162e1f5223cbbcd2876fdb820837cb13a85e1 +default_system_tests_commit: &default_system_tests_commit 5aee0ed598fd984344cf0da0048b27bdb2eb4da1 parameters: nightly: From 89286d7f94bd4713635519ac9b964536770700c4 Mon Sep 17 00:00:00 2001 From: mhlidd Date: Tue, 11 Mar 2025 16:01:31 -0400 Subject: [PATCH 23/98] Introducing `DD_TRACE_EXPERIMENTAL_FEATURES_ENABLED` Config (#8536) * introducing config * undo spotless --- .../main/java/datadog/trace/api/ConfigDefaults.java | 2 ++ .../java/datadog/trace/api/config/TracerConfig.java | 3 +++ .../src/main/java/datadog/trace/api/Config.java | 11 +++++++++++ .../test/groovy/datadog/trace/api/ConfigTest.groovy | 9 +++++++++ 4 files changed, 25 insertions(+) diff --git a/dd-trace-api/src/main/java/datadog/trace/api/ConfigDefaults.java b/dd-trace-api/src/main/java/datadog/trace/api/ConfigDefaults.java index 6a4158cdf6a..6fd8cec6d6e 100644 --- a/dd-trace-api/src/main/java/datadog/trace/api/ConfigDefaults.java +++ b/dd-trace-api/src/main/java/datadog/trace/api/ConfigDefaults.java @@ -232,6 +232,8 @@ public final class ConfigDefaults { static final boolean DEFAULT_TELEMETRY_LOG_COLLECTION_ENABLED = true; static final int DEFAULT_TELEMETRY_DEPENDENCY_RESOLUTION_QUEUE_SIZE = 100000; + static final Set DEFAULT_TRACE_EXPERIMENTAL_FEATURES_ENABLED = new HashSet<>(); + static final boolean DEFAULT_TRACE_128_BIT_TRACEID_GENERATION_ENABLED = true; static final boolean DEFAULT_TRACE_128_BIT_TRACEID_LOGGING_ENABLED = false; static final boolean DEFAULT_SECURE_RANDOM = false; diff --git a/dd-trace-api/src/main/java/datadog/trace/api/config/TracerConfig.java b/dd-trace-api/src/main/java/datadog/trace/api/config/TracerConfig.java index e4cebef3308..85155b7ada2 100644 --- a/dd-trace-api/src/main/java/datadog/trace/api/config/TracerConfig.java +++ b/dd-trace-api/src/main/java/datadog/trace/api/config/TracerConfig.java @@ -34,6 +34,9 @@ public final class TracerConfig { @Deprecated public static final String TRACE_RESOLVER_ENABLED = "trace.resolver.enabled"; public static final String SERVICE_MAPPING = "service.mapping"; + public static final String TRACE_EXPERIMENTAL_FEATURES_ENABLED = + "trace.experimental.features.enabled"; + public static final String SPAN_TAGS = "trace.span.tags"; public static final String TRACE_ANALYTICS_ENABLED = "trace.analytics.enabled"; diff --git a/internal-api/src/main/java/datadog/trace/api/Config.java b/internal-api/src/main/java/datadog/trace/api/Config.java index 17e776f7980..240c3b41790 100644 --- a/internal-api/src/main/java/datadog/trace/api/Config.java +++ b/internal-api/src/main/java/datadog/trace/api/Config.java @@ -561,6 +561,7 @@ public static String getHostName() { private final long dependecyResolutionPeriodMillis; private final boolean apmTracingEnabled; + private final Set experimentalFeaturesEnabled; // Read order: System Properties -> Env Variables, [-> properties file], [-> default value] private Config() { @@ -626,6 +627,10 @@ private Config(final ConfigProvider configProvider, final InstrumenterConfig ins configProvider.getString( SERVLET_ROOT_CONTEXT_SERVICE_NAME, DEFAULT_SERVLET_ROOT_CONTEXT_SERVICE_NAME); + experimentalFeaturesEnabled = + configProvider.getSet( + TRACE_EXPERIMENTAL_FEATURES_ENABLED, DEFAULT_TRACE_EXPERIMENTAL_FEATURES_ENABLED); + integrationSynapseLegacyOperationName = configProvider.getBoolean(INTEGRATION_SYNAPSE_LEGACY_OPERATION_NAME, false); writerType = configProvider.getString(WRITER_TYPE, DEFAULT_AGENT_WRITER_TYPE); @@ -2013,6 +2018,10 @@ public String getRootContextServiceName() { return rootContextServiceName; } + public Set getExperimentalFeaturesEnabled() { + return experimentalFeaturesEnabled; + } + public boolean isTraceEnabled() { return instrumenterConfig.isTraceEnabled(); } @@ -4367,6 +4376,8 @@ public String toString() { + serviceNameSetByUser + ", rootContextServiceName=" + rootContextServiceName + + ", experimentalFeaturesEnabled=" + + experimentalFeaturesEnabled + ", integrationSynapseLegacyOperationName=" + integrationSynapseLegacyOperationName + ", writerType='" diff --git a/internal-api/src/test/groovy/datadog/trace/api/ConfigTest.groovy b/internal-api/src/test/groovy/datadog/trace/api/ConfigTest.groovy index df5509b13ef..1e661867875 100644 --- a/internal-api/src/test/groovy/datadog/trace/api/ConfigTest.groovy +++ b/internal-api/src/test/groovy/datadog/trace/api/ConfigTest.groovy @@ -107,6 +107,7 @@ import static datadog.trace.api.config.TracerConfig.HTTP_CLIENT_ERROR_STATUSES import static datadog.trace.api.config.TracerConfig.HTTP_SERVER_ERROR_STATUSES import static datadog.trace.api.config.TracerConfig.ID_GENERATION_STRATEGY import static datadog.trace.api.config.TracerConfig.PARTIAL_FLUSH_ENABLED +import static datadog.trace.api.config.TracerConfig.TRACE_EXPERIMENTAL_FEATURES_ENABLED import static datadog.trace.api.config.TracerConfig.TRACE_LONG_RUNNING_ENABLED import static datadog.trace.api.config.TracerConfig.TRACE_LONG_RUNNING_FLUSH_INTERVAL import static datadog.trace.api.config.TracerConfig.TRACE_LONG_RUNNING_INITIAL_FLUSH_INTERVAL @@ -221,6 +222,8 @@ class ConfigTest extends DDSpecification { prop.setProperty(TRACE_LONG_RUNNING_ENABLED, "true") prop.setProperty(TRACE_LONG_RUNNING_FLUSH_INTERVAL, "250") + prop.setProperty(TRACE_EXPERIMENTAL_FEATURES_ENABLED, "DD_TAGS, DD_TRACE_HTTP_CLIENT_TAG_QUERY_STRING") + prop.setProperty(PROFILING_ENABLED, "true") prop.setProperty(PROFILING_URL, "new url") prop.setProperty(PROFILING_TAGS, "f:6,host:test-host") @@ -312,6 +315,8 @@ class ConfigTest extends DDSpecification { config.isLongRunningTraceEnabled() config.getLongRunningTraceFlushInterval() == 250 + config.experimentalFeaturesEnabled == ["DD_TAGS", "DD_TRACE_HTTP_CLIENT_TAG_QUERY_STRING"].toSet() + config.profilingEnabled == true config.profilingUrl == "new url" config.mergedProfilingTags == [b: "2", f: "6", (HOST_TAG): "test-host", (RUNTIME_ID_TAG): config.getRuntimeId(), (RUNTIME_VERSION_TAG): config.getRuntimeVersion(), (SERVICE_TAG): config.serviceName, (LANGUAGE_TAG_KEY): LANGUAGE_TAG_VALUE] @@ -402,6 +407,8 @@ class ConfigTest extends DDSpecification { System.setProperty(PREFIX + TRACE_LONG_RUNNING_ENABLED, "true") System.setProperty(PREFIX + TRACE_LONG_RUNNING_FLUSH_INTERVAL, "333") + System.setProperty(PREFIX + TRACE_EXPERIMENTAL_FEATURES_ENABLED, "DD_TAGS, DD_TRACE_HTTP_CLIENT_TAG_QUERY_STRING") + System.setProperty(PREFIX + PROFILING_ENABLED, "true") System.setProperty(PREFIX + PROFILING_URL, "new url") System.setProperty(PREFIX + PROFILING_TAGS, "f:6,host:test-host") @@ -493,6 +500,8 @@ class ConfigTest extends DDSpecification { config.getLongRunningTraceFlushInterval() == 333 config.traceRateLimit == 200 + config.experimentalFeaturesEnabled == ["DD_TAGS", "DD_TRACE_HTTP_CLIENT_TAG_QUERY_STRING"].toSet() + config.profilingEnabled == true config.profilingUrl == "new url" config.mergedProfilingTags == [b: "2", f: "6", (HOST_TAG): "test-host", (RUNTIME_ID_TAG): config.getRuntimeId(), (RUNTIME_VERSION_TAG): config.getRuntimeVersion(), (SERVICE_TAG): config.serviceName, (LANGUAGE_TAG_KEY): LANGUAGE_TAG_VALUE] From 4c2a2f5824ae2aa940bac4319610ad74b6e153c9 Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Wed, 12 Mar 2025 12:24:59 +0000 Subject: [PATCH 24/98] Remove AgentScope.source() from instrumentation API (#8539) --- .../opentracing31/OTScopeManager.java | 5 ----- .../opentracing32/OTScopeManager.java | 5 ----- .../java/datadog/trace/core/CoreTracer.java | 15 +++---------- .../core/scopemanager/ContinuableScope.java | 1 - .../scopemanager/ContinuableScopeManager.java | 22 +++++++++++++++++++ .../datadog/opentracing/OTScopeManager.java | 5 ----- .../instrumentation/api/AgentScope.java | 2 -- .../instrumentation/api/NoopScope.java | 5 ----- 8 files changed, 25 insertions(+), 35 deletions(-) diff --git a/dd-java-agent/instrumentation/opentracing/api-0.31/src/main/java/datadog/trace/instrumentation/opentracing31/OTScopeManager.java b/dd-java-agent/instrumentation/opentracing/api-0.31/src/main/java/datadog/trace/instrumentation/opentracing31/OTScopeManager.java index e0c18fb9c2c..e7f1987163a 100644 --- a/dd-java-agent/instrumentation/opentracing/api-0.31/src/main/java/datadog/trace/instrumentation/opentracing31/OTScopeManager.java +++ b/dd-java-agent/instrumentation/opentracing/api-0.31/src/main/java/datadog/trace/instrumentation/opentracing31/OTScopeManager.java @@ -89,11 +89,6 @@ public AgentSpan span() { return agentSpan; } - @Override - public byte source() { - return ScopeSource.MANUAL.id(); - } - @Override public void close() { if (agentSpan == tracer.activeSpan()) { diff --git a/dd-java-agent/instrumentation/opentracing/api-0.32/src/main/java/datadog/trace/instrumentation/opentracing32/OTScopeManager.java b/dd-java-agent/instrumentation/opentracing/api-0.32/src/main/java/datadog/trace/instrumentation/opentracing32/OTScopeManager.java index 1978ea1b83b..bb9da45e1ec 100644 --- a/dd-java-agent/instrumentation/opentracing/api-0.32/src/main/java/datadog/trace/instrumentation/opentracing32/OTScopeManager.java +++ b/dd-java-agent/instrumentation/opentracing/api-0.32/src/main/java/datadog/trace/instrumentation/opentracing32/OTScopeManager.java @@ -99,11 +99,6 @@ public AgentSpan span() { return agentSpan; } - @Override - public byte source() { - return ScopeSource.MANUAL.id(); - } - @Override public void close() { if (agentSpan == tracer.activeSpan()) { diff --git a/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java b/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java index cd7036edb66..2a9198d736b 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java @@ -922,12 +922,7 @@ public AgentScope activateSpan(AgentSpan span, ScopeSource source, boolean isAsy @Override public AgentScope.Continuation captureActiveSpan() { - AgentScope activeScope = this.scopeManager.active(); - if (null != activeScope && activeScope.isAsyncPropagating()) { - return scopeManager.captureSpan(activeScope.span(), activeScope.source()); - } else { - return AgentTracer.noopContinuation(); - } + return scopeManager.captureActiveSpan(); } @Override @@ -937,16 +932,12 @@ public AgentScope.Continuation captureSpan(final AgentSpan span) { @Override public boolean isAsyncPropagationEnabled() { - AgentScope activeScope = this.scopeManager.active(); - return activeScope != null && activeScope.isAsyncPropagating(); + return scopeManager.isAsyncPropagationEnabled(); } @Override public void setAsyncPropagationEnabled(boolean asyncPropagationEnabled) { - AgentScope activeScope = this.scopeManager.active(); - if (activeScope != null) { - activeScope.setAsyncPropagation(asyncPropagationEnabled); - } + scopeManager.setAsyncPropagationEnabled(asyncPropagationEnabled); } @Override diff --git a/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScope.java b/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScope.java index f8bea7cc160..a07333b11c8 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScope.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScope.java @@ -184,7 +184,6 @@ public final void afterActivated() { } } - @Override public byte source() { return (byte) (source & 0x7F); } diff --git a/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScopeManager.java b/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScopeManager.java index 5fcf4c6d6b3..83589add514 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScopeManager.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScopeManager.java @@ -13,6 +13,7 @@ import datadog.trace.api.scopemanager.ScopeListener; import datadog.trace.bootstrap.instrumentation.api.AgentScope; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import datadog.trace.bootstrap.instrumentation.api.AgentTracer; import datadog.trace.bootstrap.instrumentation.api.ProfilerContext; import datadog.trace.bootstrap.instrumentation.api.ProfilingContextIntegration; import datadog.trace.bootstrap.instrumentation.api.ScopeSource; @@ -90,6 +91,15 @@ public AgentScope activate( return activate(span, source.id(), true, isAsyncPropagating); } + public AgentScope.Continuation captureActiveSpan() { + ContinuableScope activeScope = scopeStack().active(); + if (null != activeScope && activeScope.isAsyncPropagating()) { + return captureSpan(activeScope.span(), activeScope.source()); + } else { + return AgentTracer.noopContinuation(); + } + } + public AgentScope.Continuation captureSpan(final AgentSpan span, byte source) { ScopeContinuation continuation = new ScopeContinuation(this, span, source); continuation.register(); @@ -166,6 +176,18 @@ ContinuableScope continueSpan( return scope; } + public boolean isAsyncPropagationEnabled() { + ContinuableScope activeScope = scopeStack().active(); + return activeScope != null && activeScope.isAsyncPropagating(); + } + + public void setAsyncPropagationEnabled(boolean asyncPropagationEnabled) { + ContinuableScope activeScope = scopeStack().active(); + if (activeScope != null) { + activeScope.setAsyncPropagation(asyncPropagationEnabled); + } + } + public void closePrevious(final boolean finishSpan) { ScopeStack scopeStack = scopeStack(); diff --git a/dd-trace-ot/src/main/java/datadog/opentracing/OTScopeManager.java b/dd-trace-ot/src/main/java/datadog/opentracing/OTScopeManager.java index b2297abfd19..0ca67a260a1 100644 --- a/dd-trace-ot/src/main/java/datadog/opentracing/OTScopeManager.java +++ b/dd-trace-ot/src/main/java/datadog/opentracing/OTScopeManager.java @@ -117,11 +117,6 @@ public AgentSpan span() { return agentSpan; } - @Override - public byte source() { - return ScopeSource.MANUAL.id(); - } - @Override public void close() { if (agentSpan == tracer.activeSpan()) { diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentScope.java b/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentScope.java index 0c9f4825cd3..ae9d619a142 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentScope.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentScope.java @@ -6,8 +6,6 @@ public interface AgentScope extends TraceScope, Closeable { AgentSpan span(); - byte source(); - @Override void close(); diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/NoopScope.java b/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/NoopScope.java index 5916841b796..bf879960df5 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/NoopScope.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/NoopScope.java @@ -10,11 +10,6 @@ public AgentSpan span() { return NoopSpan.INSTANCE; } - @Override - public byte source() { - return 0; - } - @Override public Continuation capture() { return NoopContinuation.INSTANCE; From fd8a07679b08a43aa865f73e73fe6470f29d6c38 Mon Sep 17 00:00:00 2001 From: Sarah Chen Date: Wed, 12 Mar 2025 10:23:03 -0400 Subject: [PATCH 25/98] Add smoke tests for java's concurrent API (#8438) * Create initial app and ExecutorService demo. * Add ForkJoin demo. * Start writing tests. * Add simple OTel spans for now. * Add FibonacciCalculator interface and adjust tests and demos accordingly. * Change trace expectations to reality. * Extract calculations to helper function and update tests. * Check that span name is as expected. * Clean PR. * Update settings.gradle Co-authored-by: Bruce Bujon * Update dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/demoExecutorService.java Co-authored-by: Bruce Bujon * Update dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/demoForkJoin.java Co-authored-by: Bruce Bujon * Update names. * Clean build.gradle. * Format tests. * Implement close method. * Organize methods in demo classes and add child span tests (but no child spans right now??). * Edit tests. * feat: Update executor app and checks * Propagate changes. * Refactor tests. * Fix variable name. * Adjust tests again. --------- Co-authored-by: Bruce Bujon Co-authored-by: Bruce Bujon --- dd-smoke-tests/concurrent/build.gradle | 32 +++++++++ .../smoketest/concurrent/ConcurrentApp.java | 27 ++++++++ .../concurrent/DemoExecutorService.java | 53 +++++++++++++++ .../smoketest/concurrent/DemoForkJoin.java | 43 ++++++++++++ .../concurrent/FibonacciCalculator.java | 10 +++ .../datadog/smoketest/AbstractDemoTest.groovy | 66 +++++++++++++++++++ .../smoketest/DemoExecutorServiceTest.groovy | 12 ++++ .../datadog/smoketest/DemoForkJoinTest.groovy | 12 ++++ .../DemoMultipleConcurrenciesTest.groovy | 12 ++++ .../smoketest/AbstractSmokeTest.groovy | 12 ++-- settings.gradle | 2 +- 11 files changed, 274 insertions(+), 7 deletions(-) create mode 100644 dd-smoke-tests/concurrent/build.gradle create mode 100644 dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/ConcurrentApp.java create mode 100644 dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/DemoExecutorService.java create mode 100644 dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/DemoForkJoin.java create mode 100644 dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/FibonacciCalculator.java create mode 100644 dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/AbstractDemoTest.groovy create mode 100644 dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/DemoExecutorServiceTest.groovy create mode 100644 dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/DemoForkJoinTest.groovy create mode 100644 dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/DemoMultipleConcurrenciesTest.groovy diff --git a/dd-smoke-tests/concurrent/build.gradle b/dd-smoke-tests/concurrent/build.gradle new file mode 100644 index 00000000000..b95668127e6 --- /dev/null +++ b/dd-smoke-tests/concurrent/build.gradle @@ -0,0 +1,32 @@ +plugins { + id 'java' + id 'application' + id 'com.github.johnrengelman.shadow' +} + +apply from: "$rootDir/gradle/java.gradle" + +description = 'Concurrent Integration Tests.' + +application { + mainClassName = 'datadog.smoketest.concurrent.ConcurrentApp' +} + +dependencies { + implementation('io.opentelemetry.instrumentation:opentelemetry-instrumentation-annotations:2.13.1') + implementation project(':dd-trace-api') + testImplementation project(':dd-smoke-tests') + + testImplementation platform('org.junit:junit-bom:5.10.0') + testImplementation 'org.junit.jupiter:junit-jupiter' +} + +test { + useJUnitPlatform() +} + +tasks.withType(Test).configureEach { + dependsOn "shadowJar" + + jvmArgs "-Ddatadog.smoketest.shadowJar.path=${tasks.shadowJar.archiveFile.get()}" +} diff --git a/dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/ConcurrentApp.java b/dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/ConcurrentApp.java new file mode 100644 index 00000000000..c17d84a8887 --- /dev/null +++ b/dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/ConcurrentApp.java @@ -0,0 +1,27 @@ +package datadog.smoketest.concurrent; + +import io.opentelemetry.instrumentation.annotations.WithSpan; +import java.util.concurrent.ExecutionException; + +public class ConcurrentApp { + @WithSpan("main") + public static void main(String[] args) { + // Calculate fibonacci using concurrent strategies + for (String arg : args) { + try (FibonacciCalculator calc = getCalculator(arg)) { + calc.computeFibonacci(10); + } catch (ExecutionException | InterruptedException e) { + throw new RuntimeException("Failed to compute fibonacci number.", e); + } + } + } + + private static FibonacciCalculator getCalculator(String name) { + if (name.equalsIgnoreCase("executorService")) { + return new DemoExecutorService(); + } else if (name.equalsIgnoreCase("forkJoin")) { + return new DemoForkJoin(); + } + throw new IllegalArgumentException("Unknown calculator: " + name); + } +} diff --git a/dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/DemoExecutorService.java b/dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/DemoExecutorService.java new file mode 100644 index 00000000000..2de2b76ccf3 --- /dev/null +++ b/dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/DemoExecutorService.java @@ -0,0 +1,53 @@ +package datadog.smoketest.concurrent; + +import static java.util.concurrent.TimeUnit.SECONDS; + +import io.opentelemetry.instrumentation.annotations.WithSpan; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +public class DemoExecutorService implements FibonacciCalculator { + private final ExecutorService executorService; + + public DemoExecutorService() { + executorService = Executors.newFixedThreadPool(10); + } + + @WithSpan("compute") + @Override + public long computeFibonacci(int n) throws ExecutionException, InterruptedException { + Future future = executorService.submit(new FibonacciTask(n)); + return future.get(); + } + + private class FibonacciTask implements Callable { + private final int n; + + public FibonacciTask(int n) { + this.n = n; + } + + @Override + public Long call() throws ExecutionException, InterruptedException { + if (n <= 1) { + return (long) n; + } + return computeFibonacci(n - 1) + computeFibonacci(n - 2); + } + } + + @Override + public void close() { + executorService.shutdown(); + try { + if (!executorService.awaitTermination(10, SECONDS)) { + executorService.shutdownNow(); + } + } catch (InterruptedException e) { + executorService.shutdownNow(); + } + } +} diff --git a/dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/DemoForkJoin.java b/dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/DemoForkJoin.java new file mode 100644 index 00000000000..dd77f86f324 --- /dev/null +++ b/dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/DemoForkJoin.java @@ -0,0 +1,43 @@ +package datadog.smoketest.concurrent; + +import io.opentelemetry.instrumentation.annotations.WithSpan; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.RecursiveTask; + +public class DemoForkJoin implements FibonacciCalculator { + private final ForkJoinPool forkJoinPool; + + public DemoForkJoin() { + forkJoinPool = new ForkJoinPool(); + } + + @Override + public long computeFibonacci(int n) { + return forkJoinPool.invoke(new FibonacciTask(n)); + } + + private class FibonacciTask extends RecursiveTask { + private final int n; + + public FibonacciTask(int n) { + this.n = n; + } + + @WithSpan("compute") + @Override + protected Long compute() { + if (n <= 1) { + return (long) n; + } + FibonacciTask taskOne = new FibonacciTask(n - 1); + taskOne.fork(); + FibonacciTask taskTwo = new FibonacciTask(n - 2); + return taskTwo.compute() + taskOne.join(); + } + } + + @Override + public void close() { + forkJoinPool.shutdown(); + } +} diff --git a/dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/FibonacciCalculator.java b/dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/FibonacciCalculator.java new file mode 100644 index 00000000000..73974d7b135 --- /dev/null +++ b/dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/FibonacciCalculator.java @@ -0,0 +1,10 @@ +package datadog.smoketest.concurrent; + +import java.util.concurrent.ExecutionException; + +public interface FibonacciCalculator extends AutoCloseable { + long computeFibonacci(int n) throws ExecutionException, InterruptedException; + + @Override + void close(); +} diff --git a/dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/AbstractDemoTest.groovy b/dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/AbstractDemoTest.groovy new file mode 100644 index 00000000000..1628d0459df --- /dev/null +++ b/dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/AbstractDemoTest.groovy @@ -0,0 +1,66 @@ +package datadog.smoketest + +import static java.util.concurrent.TimeUnit.SECONDS +import datadog.trace.test.agent.decoder.DecodedTrace +import java.util.function.Function + +abstract class AbstractDemoTest extends AbstractSmokeTest { + protected static final int TIMEOUT_SECS = 10 + protected abstract List getTestArguments() + + @Override + ProcessBuilder createProcessBuilder() { + def jarPath = System.getProperty("datadog.smoketest.shadowJar.path") + def command = new ArrayList() + command.add(javaPath()) + command.addAll(defaultJavaProperties) + command.add("-Ddd.trace.otel.enabled=true") + command.addAll(["-jar", jarPath]) + command.addAll(getTestArguments()) + + ProcessBuilder processBuilder = new ProcessBuilder(command) + processBuilder.directory(new File(buildDirectory)) + } + + @Override + Closure decodedTracesCallback() { + return {} // force traces decoding + } + + protected static Function checkTrace() { + return { + trace -> + // Check for 'main' span + def mainSpan = trace.spans.find { it.name == 'main' } + if (!mainSpan) { + return false + } + // Check that there are only 'main' and 'compute' spans + def otherSpans = trace.spans.findAll { it.name != 'main' && it.name != 'compute' } + if (!otherSpans.isEmpty()) { + return false + } + // Check that every 'compute' span is in the same trace and is either a child of the 'main' span or another 'compute' span + def computeSpans = trace.spans.findAll { it.name == 'compute' } + if (computeSpans.isEmpty()) { + return false + } + return computeSpans.every { + if (it.traceId != mainSpan.traceId) { + return false + } + if (it.parentId != mainSpan.spanId && trace.spans.find(s -> s.spanId == it.parentId).name != 'compute') { + return false + } + return true + } + } + } + + protected void receivedCorrectTrace() { + waitForTrace(defaultPoll, checkTrace()) + assert traceCount.get() == 1 + assert testedProcess.waitFor(TIMEOUT_SECS, SECONDS) + assert testedProcess.exitValue() == 0 + } +} diff --git a/dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/DemoExecutorServiceTest.groovy b/dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/DemoExecutorServiceTest.groovy new file mode 100644 index 00000000000..b99891b89bb --- /dev/null +++ b/dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/DemoExecutorServiceTest.groovy @@ -0,0 +1,12 @@ +package datadog.smoketest + +class DemoExecutorServiceTest extends AbstractDemoTest { + protected List getTestArguments() { + return ["executorService"] + } + + def 'receive one correct trace when using ExecutorService'() { + expect: + receivedCorrectTrace() + } +} diff --git a/dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/DemoForkJoinTest.groovy b/dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/DemoForkJoinTest.groovy new file mode 100644 index 00000000000..00994a6ef4f --- /dev/null +++ b/dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/DemoForkJoinTest.groovy @@ -0,0 +1,12 @@ +package datadog.smoketest + +class DemoForkJoinTest extends AbstractDemoTest { + protected List getTestArguments() { + return ["forkJoin"] + } + + def 'receive one correct trace when using ForkJoin'() { + expect: + receivedCorrectTrace() + } +} diff --git a/dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/DemoMultipleConcurrenciesTest.groovy b/dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/DemoMultipleConcurrenciesTest.groovy new file mode 100644 index 00000000000..06ec5dc67b2 --- /dev/null +++ b/dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/DemoMultipleConcurrenciesTest.groovy @@ -0,0 +1,12 @@ +package datadog.smoketest + +class DemoMultipleConcurrenciesTest extends AbstractDemoTest { + protected List getTestArguments() { + return ["executorService", "forkJoin"] + } + + def 'receive one correct trace when using multiple concurrency strategies (ExecutorService and ForkJoin)'() { + expect: + receivedCorrectTrace() + } +} diff --git a/dd-smoke-tests/src/main/groovy/datadog/smoketest/AbstractSmokeTest.groovy b/dd-smoke-tests/src/main/groovy/datadog/smoketest/AbstractSmokeTest.groovy index 0d1192696f5..e5d1c70f019 100644 --- a/dd-smoke-tests/src/main/groovy/datadog/smoketest/AbstractSmokeTest.groovy +++ b/dd-smoke-tests/src/main/groovy/datadog/smoketest/AbstractSmokeTest.groovy @@ -50,6 +50,9 @@ abstract class AbstractSmokeTest extends ProcessManager { @Shared protected TestHttpServer.Headers lastTraceRequestHeaders = null + @Shared + protected final PollingConditions defaultPoll = new PollingConditions(timeout: 30, initialDelay: 0, delay: 1, factor: 1) + @Shared @AutoCleanup protected TestHttpServer server = httpServer { @@ -292,8 +295,7 @@ abstract class AbstractSmokeTest extends ProcessManager { } int waitForTraceCount(int count) { - def conditions = new PollingConditions(timeout: 30, initialDelay: 0, delay: 0.5, factor: 1) - return waitForTraceCount(count, conditions) + return waitForTraceCount(count, defaultPoll) } int waitForTraceCount(int count, PollingConditions conditions) { @@ -325,8 +327,7 @@ abstract class AbstractSmokeTest extends ProcessManager { } void waitForTelemetryCount(final int count) { - def conditions = new PollingConditions(timeout: 30, initialDelay: 0, delay: 1, factor: 1) - waitForTelemetryCount(conditions, count) + waitForTelemetryCount(defaultPoll, count) } void waitForTelemetryCount(final PollingConditions poll, final int count) { @@ -336,8 +337,7 @@ abstract class AbstractSmokeTest extends ProcessManager { } void waitForTelemetryFlat(final Function, Boolean> predicate) { - def conditions = new PollingConditions(timeout: 30, initialDelay: 0, delay: 1, factor: 1) - waitForTelemetryFlat(conditions, predicate) + waitForTelemetryFlat(defaultPoll, predicate) } void waitForTelemetryFlat(final PollingConditions poll, final Function, Boolean> predicate) { diff --git a/settings.gradle b/settings.gradle index ae394bf910f..11c65fef6dd 100644 --- a/settings.gradle +++ b/settings.gradle @@ -98,6 +98,7 @@ include ':dd-smoke-tests:apm-tracing-disabled' include ':dd-smoke-tests:armeria-grpc' include ':dd-smoke-tests:backend-mock' include ':dd-smoke-tests:cli' +include ':dd-smoke-tests:concurrent' include ':dd-smoke-tests:crashtracking' include ':dd-smoke-tests:custom-systemloader' include ':dd-smoke-tests:dynamic-config' @@ -534,4 +535,3 @@ include ':dd-java-agent:benchmark' include ':dd-java-agent:benchmark-integration' include ':dd-java-agent:benchmark-integration:jetty-perftest' include ':dd-java-agent:benchmark-integration:play-perftest' - From f1da84ce4d0a67b70353afae344cb5a54db1eccd Mon Sep 17 00:00:00 2001 From: Daniel Mohedano Date: Wed, 12 Mar 2025 15:40:33 +0100 Subject: [PATCH 26/98] Update capabilities tagging to use versioning (#8540) --- .../config/ConfigurationApiImpl.java | 36 ++++++- .../config/ExecutionSettings.java | 41 -------- .../config/ExecutionSettingsFactoryImpl.java | 1 + .../config/TracerEnvironment.java | 19 ++++ .../trace/civisibility/domain/TestImpl.java | 7 +- .../civisibility/domain/TestSuiteImpl.java | 9 +- .../domain/buildsystem/ProxyTestModule.java | 9 +- .../domain/buildsystem/ProxyTestSession.java | 8 +- .../domain/headless/HeadlessTestModule.java | 9 +- .../domain/headless/HeadlessTestSession.java | 8 +- .../domain/manualapi/ManualApiTestModule.java | 2 +- .../config/ConfigurationApiImplTest.groovy | 1 + .../config/ExecutionSettingsTest.groovy | 17 ---- .../civisibility/domain/TestImplTest.groovy | 21 ++-- .../domain/TestSuiteImplTest.groovy | 2 +- .../buildsystem/ProxyTestModuleTest.groovy | 2 +- .../headless/HeadlessTestModuleTest.groovy | 2 +- .../config/test-management-tests-request.ftl | 22 +---- .../test-failed-flaky-retries/events.ftl | 70 ++++++------- .../events.ftl | 14 +-- .../events.ftl | 14 +-- .../events.ftl | 16 +-- .../resources/test-succeed-junit-5/events.ftl | 32 +++--- .../events.ftl | 28 +++--- .../coverages.ftl | 22 ++--- .../events.ftl | 30 +++--- .../coverages.ftl | 22 ++--- .../events.ftl | 30 +++--- .../events.ftl | 28 +++--- .../events.ftl | 28 +++--- .../events.ftl | 28 +++--- .../test-succeed-old-gradle/events.ftl | 28 +++--- .../events.ftl | 70 ++++++------- .../test_successful_maven_run/events.ftl | 28 +++--- .../events.ftl | 28 +++--- .../events.ftl | 28 +++--- .../events.ftl | 14 +-- .../events.ftl | 32 +++--- .../events.ftl | 28 +++--- .../events.ftl | 28 +++--- .../events.ftl | 98 +++++++++---------- .../events.ftl | 14 +-- .../events.ftl | 12 +-- .../events.ftl | 28 +++--- .../config/LibraryCapability.java | 24 +++-- 45 files changed, 506 insertions(+), 532 deletions(-) diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/config/ConfigurationApiImpl.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/config/ConfigurationApiImpl.java index b9314005bee..2098ce9d87b 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/config/ConfigurationApiImpl.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/config/ConfigurationApiImpl.java @@ -1,6 +1,7 @@ package datadog.trace.civisibility.config; import com.squareup.moshi.FromJson; +import com.squareup.moshi.Json; import com.squareup.moshi.JsonAdapter; import com.squareup.moshi.Moshi; import com.squareup.moshi.ToJson; @@ -65,6 +66,7 @@ public class ConfigurationApiImpl implements ConfigurationApi { private final JsonAdapter> settingsResponseAdapter; private final JsonAdapter> testIdentifiersResponseAdapter; private final JsonAdapter> testFullNamesResponseAdapter; + private final JsonAdapter> testManagementRequestAdapter; private final JsonAdapter> testManagementTestsResponseAdapter; private final JsonAdapter> changedFilesResponseAdapter; @@ -108,6 +110,11 @@ public ConfigurationApiImpl(BackendApi backendApi, CiVisibilityMetricCollector m ConfigurationApiImpl.class, EnvelopeDto.class, KnownTestsDto.class); testFullNamesResponseAdapter = moshi.adapter(testFullNamesResponseType); + ParameterizedType testManagementRequestType = + Types.newParameterizedTypeWithOwner( + ConfigurationApiImpl.class, EnvelopeDto.class, TestManagementDto.class); + testManagementRequestAdapter = moshi.adapter(testManagementRequestType); + ParameterizedType testManagementTestsResponseType = Types.newParameterizedTypeWithOwner( ConfigurationApiImpl.class, EnvelopeDto.class, TestManagementTestsDto.class); @@ -329,9 +336,16 @@ public Map>> getTestManagementTests .build(); String uuid = uuidGenerator.get(); - EnvelopeDto request = - new EnvelopeDto<>(new DataDto<>(uuid, "ci_app_libraries_tests_request", tracerEnvironment)); - String json = requestAdapter.toJson(request); + EnvelopeDto request = + new EnvelopeDto<>( + new DataDto<>( + uuid, + "ci_app_libraries_tests_request", + new TestManagementDto( + tracerEnvironment.getRepositoryUrl(), + tracerEnvironment.getCommitMessage(), + tracerEnvironment.getConfigurations().getTestBundle()))); + String json = testManagementRequestAdapter.toJson(request); RequestBody requestBody = RequestBody.create(JSON, json); TestManagementTestsDto testManagementTestsDto = backendApi.post( @@ -520,6 +534,22 @@ private KnownTestsDto(Map>> tests) { } } + private static final class TestManagementDto { + @Json(name = "repository_url") + private final String repositoryUrl; + + @Json(name = "commit_message") + private final String commitMessage; + + private final String module; + + private TestManagementDto(String repositoryUrl, String commitMessage, String module) { + this.repositoryUrl = repositoryUrl; + this.commitMessage = commitMessage; + this.module = module; + } + } + private static final class TestManagementTestsDto { private static final class Properties { private final Map properties; diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/config/ExecutionSettings.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/config/ExecutionSettings.java index cdca5314c6e..4d93dcf5d38 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/config/ExecutionSettings.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/config/ExecutionSettings.java @@ -1,8 +1,5 @@ package datadog.trace.civisibility.config; -import datadog.trace.api.Config; -import datadog.trace.api.civisibility.CIConstants; -import datadog.trace.api.civisibility.config.LibraryCapability; import datadog.trace.api.civisibility.config.TestFQN; import datadog.trace.api.civisibility.config.TestIdentifier; import datadog.trace.api.civisibility.config.TestMetadata; @@ -232,44 +229,6 @@ public Diff getPullRequestDiff() { return pullRequestDiff; } - @Nonnull - public Map getCapabilitiesStatus( - Collection capabilities) { - Map status = new EnumMap<>(LibraryCapability.class); - - for (LibraryCapability c : capabilities) { - switch (c) { - case TIA: - status.put(c, isTestSkippingEnabled()); - break; - case EFD: - EarlyFlakeDetectionSettings efdSettings = getEarlyFlakeDetectionSettings(); - status.put(c, efdSettings.isEnabled()); - break; - case ATR: - status.put(c, isFlakyTestRetriesEnabled()); - break; - case IMPACTED: - status.put(c, isImpactedTestsDetectionEnabled()); - break; - case FAIL_FAST: - String testOrder = Config.get().getCiVisibilityTestOrder(); - status.put(c, CIConstants.FAIL_FAST_TEST_ORDER.equalsIgnoreCase(testOrder)); - break; - case QUARANTINE: - case DISABLED: - case ATTEMPT_TO_FIX: - TestManagementSettings testManagementSettings = getTestManagementSettings(); - status.put(c, testManagementSettings.isEnabled()); - break; - default: - break; - } - } - - return status; - } - @Override public boolean equals(Object o) { if (this == o) { diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/config/ExecutionSettingsFactoryImpl.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/config/ExecutionSettingsFactoryImpl.java index c0beee97019..3e0a62105e5 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/config/ExecutionSettingsFactoryImpl.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/config/ExecutionSettingsFactoryImpl.java @@ -107,6 +107,7 @@ private TracerEnvironment buildTracerEnvironment(JvmInfo jvmInfo, @Nullable Stri .repositoryUrl(gitInfo.getRepositoryURL()) .branch(gitInfo.getBranch()) .sha(gitInfo.getCommit().getSha()) + .commitMessage(gitInfo.getCommit().getFullMessage()) .osPlatform(wellKnownTags.getOsPlatform().toString()) .osArchitecture(wellKnownTags.getOsArch().toString()) .osVersion(wellKnownTags.getOsVersion().toString()) diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/config/TracerEnvironment.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/config/TracerEnvironment.java index e622bb14021..a405902bd2c 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/config/TracerEnvironment.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/config/TracerEnvironment.java @@ -16,6 +16,9 @@ public class TracerEnvironment { private final String branch; private final String sha; + @Json(name = "commit_message") + private final String commitMessage; + @Json(name = "test_level") private final String testLevel = "test"; @@ -27,12 +30,14 @@ private TracerEnvironment( String repositoryUrl, String branch, String sha, + String commitMessage, Configurations configurations) { this.service = service; this.env = env; this.repositoryUrl = repositoryUrl; this.branch = branch; this.sha = sha; + this.commitMessage = commitMessage; this.configurations = configurations; } @@ -40,6 +45,10 @@ public String getSha() { return sha; } + public String getCommitMessage() { + return commitMessage; + } + public String getService() { return service; } @@ -82,6 +91,9 @@ public String toString() { + ", sha='" + sha + '\'' + + ", commitMessage='" + + commitMessage + + '\'' + ", testLevel='" + testLevel + '\'' @@ -100,6 +112,7 @@ public static final class Builder { private String repositoryUrl; private String branch; private String sha; + private String commitMessage; private String osPlatform; private String osArchitecture; private String osVersion; @@ -135,6 +148,11 @@ public Builder sha(String sha) { return this; } + public Builder commitMessage(String commitMessage) { + this.commitMessage = commitMessage; + return this; + } + public Builder osPlatform(String osPlatform) { this.osPlatform = osPlatform; return this; @@ -187,6 +205,7 @@ public TracerEnvironment build() { repositoryUrl, branch, sha, + commitMessage, new Configurations( osPlatform, osArchitecture, diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/TestImpl.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/TestImpl.java index df7a3eaef67..3bb5054dee0 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/TestImpl.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/TestImpl.java @@ -45,7 +45,6 @@ import java.lang.reflect.Method; import java.util.Collection; import java.util.Collections; -import java.util.Map; import java.util.function.Consumer; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -87,7 +86,7 @@ public TestImpl( Codeowners codeowners, CoverageStore.Factory coverageStoreFactory, ExecutionResults executionResults, - @Nonnull Map libraryCapabilities, + @Nonnull Collection capabilities, Consumer onSpanFinish) { this.instrumentation = instrumentation; this.metricCollector = metricCollector; @@ -146,8 +145,8 @@ public TestImpl( span.setTag(Tags.ITR_CORRELATION_ID, itrCorrelationId); } - for (Map.Entry entry : libraryCapabilities.entrySet()) { - span.setTag(entry.getKey().asTag(), entry.getValue()); + for (LibraryCapability capability : capabilities) { + span.setTag(capability.asTag(), capability.getVersion()); } testDecorator.afterStart(span); diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/TestSuiteImpl.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/TestSuiteImpl.java index db00a8dfba7..0ba81176691 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/TestSuiteImpl.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/TestSuiteImpl.java @@ -26,7 +26,6 @@ import datadog.trace.civisibility.utils.SpanUtils; import java.lang.reflect.Method; import java.util.Collection; -import java.util.Map; import java.util.function.Consumer; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -54,7 +53,7 @@ public class TestSuiteImpl implements DDTestSuite { private final CoverageStore.Factory coverageStoreFactory; private final ExecutionResults executionResults; private final boolean parallelized; - private final Map libraryCapabilities; + private final Collection capabilities; private final Consumer onSpanFinish; public TestSuiteImpl( @@ -75,7 +74,7 @@ public TestSuiteImpl( LinesResolver linesResolver, CoverageStore.Factory coverageStoreFactory, ExecutionResults executionResults, - @Nonnull Map libraryCapabilities, + @Nonnull Collection capabilities, Consumer onSpanFinish) { this.moduleSpanContext = moduleSpanContext; this.moduleName = moduleName; @@ -92,7 +91,7 @@ public TestSuiteImpl( this.linesResolver = linesResolver; this.coverageStoreFactory = coverageStoreFactory; this.executionResults = executionResults; - this.libraryCapabilities = libraryCapabilities; + this.capabilities = capabilities; this.onSpanFinish = onSpanFinish; AgentTracer.SpanBuilder spanBuilder = @@ -263,7 +262,7 @@ public TestImpl testStart( codeowners, coverageStoreFactory, executionResults, - libraryCapabilities, + capabilities, SpanUtils.propagateCiVisibilityTagsTo(span)); } } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/buildsystem/ProxyTestModule.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/buildsystem/ProxyTestModule.java index 0b77d2b0824..bd50ba88dc3 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/buildsystem/ProxyTestModule.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/buildsystem/ProxyTestModule.java @@ -31,7 +31,6 @@ import datadog.trace.civisibility.test.ExecutionResults; import datadog.trace.civisibility.test.ExecutionStrategy; import java.util.Collection; -import java.util.Map; import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; import javax.annotation.Nonnull; @@ -62,7 +61,7 @@ public class ProxyTestModule implements TestFrameworkModule { private final LinesResolver linesResolver; private final CoverageStore.Factory coverageStoreFactory; private final Collection testFrameworks = ConcurrentHashMap.newKeySet(); - private final Map libraryCapabilities; + private final Collection capabilities; public ProxyTestModule( AgentSpanContext parentProcessModuleContext, @@ -77,7 +76,7 @@ public ProxyTestModule( CoverageStore.Factory coverageStoreFactory, ChildProcessCoverageReporter childProcessCoverageReporter, SignalClient.Factory signalClientFactory, - Map libraryCapabilities) { + Collection capabilities) { this.parentProcessModuleContext = parentProcessModuleContext; this.moduleName = moduleName; this.executionStrategy = executionStrategy; @@ -91,7 +90,7 @@ public ProxyTestModule( this.codeowners = codeowners; this.linesResolver = linesResolver; this.coverageStoreFactory = coverageStoreFactory; - this.libraryCapabilities = libraryCapabilities; + this.capabilities = capabilities; } @Override @@ -216,7 +215,7 @@ public TestSuiteImpl testSuiteStart( linesResolver, coverageStoreFactory, executionResults, - libraryCapabilities, + capabilities, this::propagateTestFrameworkData); } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/buildsystem/ProxyTestSession.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/buildsystem/ProxyTestSession.java index a44dc030bbf..aefb9f05d4b 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/buildsystem/ProxyTestSession.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/buildsystem/ProxyTestSession.java @@ -16,7 +16,6 @@ import datadog.trace.civisibility.source.SourcePathResolver; import datadog.trace.civisibility.test.ExecutionStrategy; import java.util.Collection; -import java.util.Map; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -38,7 +37,7 @@ public class ProxyTestSession implements TestFrameworkSession { private final ChildProcessCoverageReporter childProcessCoverageReporter; private final SignalClient.Factory signalClientFactory; private final ExecutionStrategy executionStrategy; - private final Map libraryCapabilities; + private final Collection capabilities; public ProxyTestSession( AgentSpanContext parentProcessModuleContext, @@ -64,8 +63,7 @@ public ProxyTestSession( this.childProcessCoverageReporter = childProcessCoverageReporter; this.signalClientFactory = signalClientFactory; this.executionStrategy = executionStrategy; - this.libraryCapabilities = - executionStrategy.getExecutionSettings().getCapabilitiesStatus(capabilities); + this.capabilities = capabilities; } @Override @@ -91,6 +89,6 @@ public TestFrameworkModule testModuleStart(String moduleName, @Nullable Long sta coverageStoreFactory, childProcessCoverageReporter, signalClientFactory, - libraryCapabilities); + capabilities); } } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/headless/HeadlessTestModule.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/headless/HeadlessTestModule.java index 96c182990fd..65a75ed685a 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/headless/HeadlessTestModule.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/headless/HeadlessTestModule.java @@ -29,7 +29,6 @@ import datadog.trace.civisibility.test.ExecutionStrategy; import datadog.trace.civisibility.utils.SpanUtils; import java.util.Collection; -import java.util.Map; import java.util.function.Consumer; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -46,7 +45,7 @@ public class HeadlessTestModule extends AbstractTestModule implements TestFramew private final CoverageStore.Factory coverageStoreFactory; private final ExecutionStrategy executionStrategy; private final ExecutionResults executionResults; - private final Map libraryCapabilities; + private final Collection capabilities; public HeadlessTestModule( AgentSpanContext sessionSpanContext, @@ -60,7 +59,7 @@ public HeadlessTestModule( LinesResolver linesResolver, CoverageStore.Factory coverageStoreFactory, ExecutionStrategy executionStrategy, - Map libraryCapabilities, + Collection capabilities, Consumer onSpanFinish) { super( sessionSpanContext, @@ -77,7 +76,7 @@ public HeadlessTestModule( this.coverageStoreFactory = coverageStoreFactory; this.executionStrategy = executionStrategy; this.executionResults = new ExecutionResults(); - this.libraryCapabilities = libraryCapabilities; + this.capabilities = capabilities; } @Override @@ -188,7 +187,7 @@ public TestSuiteImpl testSuiteStart( linesResolver, coverageStoreFactory, executionResults, - libraryCapabilities, + capabilities, SpanUtils.propagateCiVisibilityTagsTo(span)); } } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/headless/HeadlessTestSession.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/headless/HeadlessTestSession.java index 7d43d8db71c..a499793115b 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/headless/HeadlessTestSession.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/headless/HeadlessTestSession.java @@ -22,7 +22,6 @@ import datadog.trace.civisibility.utils.SpanUtils; import java.util.Collection; import java.util.Collections; -import java.util.Map; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -37,7 +36,7 @@ public class HeadlessTestSession extends AbstractTestSession implements TestFram private final ExecutionStrategy executionStrategy; private final CoverageStore.Factory coverageStoreFactory; - private final Map libraryCapabilities; + private final Collection capabilities; public HeadlessTestSession( String projectName, @@ -65,8 +64,7 @@ public HeadlessTestSession( linesResolver); this.executionStrategy = executionStrategy; this.coverageStoreFactory = coverageStoreFactory; - this.libraryCapabilities = - executionStrategy.getExecutionSettings().getCapabilitiesStatus(capabilities); + this.capabilities = capabilities; } @Override @@ -83,7 +81,7 @@ public HeadlessTestModule testModuleStart(String moduleName, @Nullable Long star linesResolver, coverageStoreFactory, executionStrategy, - libraryCapabilities, + capabilities, this::propagateModuleTags); } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/manualapi/ManualApiTestModule.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/manualapi/ManualApiTestModule.java index 627edd654c4..217409521c7 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/manualapi/ManualApiTestModule.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/manualapi/ManualApiTestModule.java @@ -80,7 +80,7 @@ public TestSuiteImpl testSuiteStart( linesResolver, coverageStoreFactory, executionResults, - Collections.emptyMap(), + Collections.emptyList(), SpanUtils.propagateCiVisibilityTagsTo(span)); } } diff --git a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/config/ConfigurationApiImplTest.groovy b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/config/ConfigurationApiImplTest.groovy index f65c434a9c8..6afd6186b4a 100644 --- a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/config/ConfigurationApiImplTest.groovy +++ b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/config/ConfigurationApiImplTest.groovy @@ -320,6 +320,7 @@ class ConfigurationApiImplTest extends Specification { .repositoryUrl("https://github.com/DataDog/foo") .branch("prod") .sha("d64185e45d1722ab3a53c45be47accae") + .commitMessage("full commit message") .osPlatform("linux") .osArchitecture("amd64") .osVersion("bionic") diff --git a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/config/ExecutionSettingsTest.groovy b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/config/ExecutionSettingsTest.groovy index 495767cf336..cd9a84e3fd8 100644 --- a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/config/ExecutionSettingsTest.groovy +++ b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/config/ExecutionSettingsTest.groovy @@ -110,23 +110,6 @@ class ExecutionSettingsTest extends DDSpecification { ] } - def "test capabilities status: #testcaseName"() { - when: - def executionSettings = givenExecutionSettings(settingsEnabled) - - def capabilitiesStatus = executionSettings.getCapabilitiesStatus(capabilities) - def expectedStatus = capabilities.stream().collect(Collectors.toMap(item -> item, item -> settingsEnabled)) - - then: - capabilitiesStatus == expectedStatus - - where: - testcaseName | settingsEnabled | capabilities - "capabilities-disabled" | false | LibraryCapability.values().toList() - "capabilities-enabled" | true | LibraryCapability.values().toList() - "capabilities-filtering" | true | [LibraryCapability.TIA, LibraryCapability.ATR, LibraryCapability.IMPACTED, LibraryCapability.QUARANTINE] - } - private ExecutionSettings givenExecutionSettings(boolean settingsEnabled) { if (settingsEnabled) { injectSysConfig(CiVisibilityConfig.CIVISIBILITY_TEST_ORDER, CIConstants.FAIL_FAST_TEST_ORDER) diff --git a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/domain/TestImplTest.groovy b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/domain/TestImplTest.groovy index e1e659010f9..eac92fa8474 100644 --- a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/domain/TestImplTest.groovy +++ b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/domain/TestImplTest.groovy @@ -35,11 +35,11 @@ class TestImplTest extends SpanWriterTest { parent() spanType DDSpanTypes.TEST tags(false) { - "${LibraryCapability.TIA.asTag()}" true - "${LibraryCapability.EFD.asTag()}" false - "${LibraryCapability.QUARANTINE.asTag()}" true - "${LibraryCapability.DISABLED.asTag()}" false - "${LibraryCapability.ATTEMPT_TO_FIX.asTag()}" true + "${LibraryCapability.TIA.asTag()}" "${LibraryCapability.TIA.getVersion()}" + "${LibraryCapability.EFD.asTag()}" "${LibraryCapability.EFD.getVersion()}" + "${LibraryCapability.QUARANTINE.asTag()}" "${LibraryCapability.QUARANTINE.getVersion()}" + "${LibraryCapability.DISABLED.asTag()}" "${LibraryCapability.DISABLED.getVersion()}" + "${LibraryCapability.ATTEMPT_TO_FIX.asTag()}" "${LibraryCapability.ATTEMPT_TO_FIX.getVersion()}" } } } @@ -114,11 +114,12 @@ class TestImplTest extends SpanWriterTest { def codeowners = NoCodeowners.INSTANCE def libraryCapabilities = [ - (LibraryCapability.TIA) : true, - (LibraryCapability.EFD) : false, - (LibraryCapability.QUARANTINE) : true, - (LibraryCapability.DISABLED) : false, - (LibraryCapability.ATTEMPT_TO_FIX): true] + LibraryCapability.TIA, + LibraryCapability.EFD, + LibraryCapability.QUARANTINE, + LibraryCapability.DISABLED, + LibraryCapability.ATTEMPT_TO_FIX + ] new TestImpl( moduleSpanContext, diff --git a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/domain/TestSuiteImplTest.groovy b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/domain/TestSuiteImplTest.groovy index f51f8df278f..aed8ffa88db 100644 --- a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/domain/TestSuiteImplTest.groovy +++ b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/domain/TestSuiteImplTest.groovy @@ -85,7 +85,7 @@ class TestSuiteImplTest extends SpanWriterTest { linesResolver, coverageStoreFactory, executionResults, - [:], + [], SpanUtils.DO_NOT_PROPAGATE_CI_VISIBILITY_TAGS ) } diff --git a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/domain/buildsystem/ProxyTestModuleTest.groovy b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/domain/buildsystem/ProxyTestModuleTest.groovy index 006fe2b9c66..cd8492ce566 100644 --- a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/domain/buildsystem/ProxyTestModuleTest.groovy +++ b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/domain/buildsystem/ProxyTestModuleTest.groovy @@ -52,7 +52,7 @@ class ProxyTestModuleTest extends DDSpecification { Stub(CoverageStore.Factory), Stub(ChildProcessCoverageReporter), GroovyMock(SignalClient.Factory), - [:] + [] ) when: diff --git a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/domain/headless/HeadlessTestModuleTest.groovy b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/domain/headless/HeadlessTestModuleTest.groovy index 57924803cd3..192b77374e7 100644 --- a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/domain/headless/HeadlessTestModuleTest.groovy +++ b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/domain/headless/HeadlessTestModuleTest.groovy @@ -66,7 +66,7 @@ class HeadlessTestModuleTest extends SpanWriterTest { Stub(LinesResolver), Stub(CoverageStore.Factory), executionStrategy, - [:], + [], (span) -> { } ) } diff --git a/dd-java-agent/agent-ci-visibility/src/test/resources/datadog/trace/civisibility/config/test-management-tests-request.ftl b/dd-java-agent/agent-ci-visibility/src/test/resources/datadog/trace/civisibility/config/test-management-tests-request.ftl index 4b9593e0a43..d16b3e43c8d 100644 --- a/dd-java-agent/agent-ci-visibility/src/test/resources/datadog/trace/civisibility/config/test-management-tests-request.ftl +++ b/dd-java-agent/agent-ci-visibility/src/test/resources/datadog/trace/civisibility/config/test-management-tests-request.ftl @@ -3,26 +3,8 @@ "type" : "ci_app_libraries_tests_request", "id" : "${uid}", "attributes": { - "service" : "${tracerEnvironment.service}", - "env" : "${tracerEnvironment.env}", - "repository_url": "${tracerEnvironment.repositoryUrl}", - "branch" : "${tracerEnvironment.branch}", - "sha" : "${tracerEnvironment.sha}", - "test_level" : "${tracerEnvironment.testLevel}", - "configurations": { - "os.platform" : "${tracerEnvironment.configurations.osPlatform}", - "os.architecture" : "${tracerEnvironment.configurations.osArchitecture}", - "os.arch" : "${tracerEnvironment.configurations.osArchitecture}", - "os.version" : "${tracerEnvironment.configurations.osVersion}", - "runtime.name" : "${tracerEnvironment.configurations.runtimeName}", - "runtime.version" : "${tracerEnvironment.configurations.runtimeVersion}", - "runtime.vendor" : "${tracerEnvironment.configurations.runtimeVendor}", - "runtime.architecture": "${tracerEnvironment.configurations.runtimeArchitecture}", - "custom" : { - <#list tracerEnvironment.configurations.custom as customTag, customValue> - "${customTag}": "${customValue}"<#if customTag?has_next>, - - } + "repository_url" : "${tracerEnvironment.repositoryUrl}", + "commit_message" : "${tracerEnvironment.commitMessage}" } } } diff --git a/dd-smoke-tests/gradle/src/test/resources/test-failed-flaky-retries/events.ftl b/dd-smoke-tests/gradle/src/test/resources/test-failed-flaky-retries/events.ftl index 80821a8a9c0..0be69f618b3 100644 --- a/dd-smoke-tests/gradle/src/test/resources/test-failed-flaky-retries/events.ftl +++ b/dd-smoke-tests/gradle/src/test/resources/test-failed-flaky-retries/events.ftl @@ -239,13 +239,13 @@ "duration" : ${content_duration_7}, "error" : 1, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "true", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "false", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_7}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, @@ -301,13 +301,13 @@ "duration" : ${content_duration_8}, "error" : 1, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "true", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "false", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_8}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, @@ -365,13 +365,13 @@ "duration" : ${content_duration_9}, "error" : 1, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "true", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "false", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_9}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, @@ -429,13 +429,13 @@ "duration" : ${content_duration_10}, "error" : 1, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "true", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "false", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_10}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, @@ -493,13 +493,13 @@ "duration" : ${content_duration_11}, "error" : 1, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "true", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "false", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_11}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, diff --git a/dd-smoke-tests/gradle/src/test/resources/test-failed-legacy-instrumentation/events.ftl b/dd-smoke-tests/gradle/src/test/resources/test-failed-legacy-instrumentation/events.ftl index c60d70b9b19..d39acb2c290 100644 --- a/dd-smoke-tests/gradle/src/test/resources/test-failed-legacy-instrumentation/events.ftl +++ b/dd-smoke-tests/gradle/src/test/resources/test-failed-legacy-instrumentation/events.ftl @@ -187,13 +187,13 @@ "duration" : ${content_duration_6}, "error" : 1, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "false", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_6}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, diff --git a/dd-smoke-tests/gradle/src/test/resources/test-failed-new-instrumentation/events.ftl b/dd-smoke-tests/gradle/src/test/resources/test-failed-new-instrumentation/events.ftl index 2eff4d5848a..ed2f768404d 100644 --- a/dd-smoke-tests/gradle/src/test/resources/test-failed-new-instrumentation/events.ftl +++ b/dd-smoke-tests/gradle/src/test/resources/test-failed-new-instrumentation/events.ftl @@ -239,13 +239,13 @@ "duration" : ${content_duration_7}, "error" : 1, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "false", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_7}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, diff --git a/dd-smoke-tests/gradle/src/test/resources/test-succeed-gradle-plugin-test/events.ftl b/dd-smoke-tests/gradle/src/test/resources/test-succeed-gradle-plugin-test/events.ftl index 3462c439bd2..171db88f8f7 100644 --- a/dd-smoke-tests/gradle/src/test/resources/test-succeed-gradle-plugin-test/events.ftl +++ b/dd-smoke-tests/gradle/src/test/resources/test-succeed-gradle-plugin-test/events.ftl @@ -233,14 +233,14 @@ "duration" : ${content_duration_7}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.fail_fast_test_order" : "false", - "_dd.library_capabilities.impacted_tests" : "false", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.fail_fast_test_order" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_7}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, diff --git a/dd-smoke-tests/gradle/src/test/resources/test-succeed-junit-5/events.ftl b/dd-smoke-tests/gradle/src/test/resources/test-succeed-junit-5/events.ftl index 5807153d23d..2ccf73e373a 100644 --- a/dd-smoke-tests/gradle/src/test/resources/test-succeed-junit-5/events.ftl +++ b/dd-smoke-tests/gradle/src/test/resources/test-succeed-junit-5/events.ftl @@ -235,14 +235,14 @@ "duration" : ${content_duration_7}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.fail_fast_test_order" : "false", - "_dd.library_capabilities.impacted_tests" : "false", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.fail_fast_test_order" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_7}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, @@ -296,14 +296,14 @@ "duration" : ${content_duration_8}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.fail_fast_test_order" : "false", - "_dd.library_capabilities.impacted_tests" : "false", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.fail_fast_test_order" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_8}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, diff --git a/dd-smoke-tests/gradle/src/test/resources/test-succeed-legacy-instrumentation/events.ftl b/dd-smoke-tests/gradle/src/test/resources/test-succeed-legacy-instrumentation/events.ftl index e67352e1531..cd356199d77 100644 --- a/dd-smoke-tests/gradle/src/test/resources/test-succeed-legacy-instrumentation/events.ftl +++ b/dd-smoke-tests/gradle/src/test/resources/test-succeed-legacy-instrumentation/events.ftl @@ -185,13 +185,13 @@ "duration" : ${content_duration_6}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "false", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_6}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, @@ -245,13 +245,13 @@ "duration" : ${content_duration_7}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "false", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_7}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, diff --git a/dd-smoke-tests/gradle/src/test/resources/test-succeed-multi-forks-legacy-instrumentation/coverages.ftl b/dd-smoke-tests/gradle/src/test/resources/test-succeed-multi-forks-legacy-instrumentation/coverages.ftl index 2fe41431bbf..567ef02b425 100644 --- a/dd-smoke-tests/gradle/src/test/resources/test-succeed-multi-forks-legacy-instrumentation/coverages.ftl +++ b/dd-smoke-tests/gradle/src/test/resources/test-succeed-multi-forks-legacy-instrumentation/coverages.ftl @@ -1,15 +1,4 @@ [ { - "files" : [ { - "bitmap" : "gAw=", - "filename" : "src/test/java/datadog/smoke/TestSucceed.java" - }, { - "bitmap" : "IA==", - "filename" : "src/main/java/datadog/smoke/Calculator.java" - } ], - "span_id" : ${content_span_id_4}, - "test_session_id" : ${content_test_session_id}, - "test_suite_id" : ${content_test_suite_id} -}, { "files" : [ { "bitmap" : "AAE=", "filename" : "src/main/java/datadog/smoke/Calculator.java" @@ -20,4 +9,15 @@ "span_id" : ${content_span_id_5}, "test_session_id" : ${content_test_session_id}, "test_suite_id" : ${content_test_suite_id_2} +}, { + "files" : [ { + "bitmap" : "gAw=", + "filename" : "src/test/java/datadog/smoke/TestSucceed.java" + }, { + "bitmap" : "IA==", + "filename" : "src/main/java/datadog/smoke/Calculator.java" + } ], + "span_id" : ${content_span_id_4}, + "test_session_id" : ${content_test_session_id}, + "test_suite_id" : ${content_test_suite_id} } ] \ No newline at end of file diff --git a/dd-smoke-tests/gradle/src/test/resources/test-succeed-multi-forks-legacy-instrumentation/events.ftl b/dd-smoke-tests/gradle/src/test/resources/test-succeed-multi-forks-legacy-instrumentation/events.ftl index 3357f857988..6e69dc1d8fc 100644 --- a/dd-smoke-tests/gradle/src/test/resources/test-succeed-multi-forks-legacy-instrumentation/events.ftl +++ b/dd-smoke-tests/gradle/src/test/resources/test-succeed-multi-forks-legacy-instrumentation/events.ftl @@ -184,13 +184,13 @@ "duration" : ${content_duration_6}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "false", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_6}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, @@ -292,14 +292,14 @@ "duration" : ${content_duration_8}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.fail_fast_test_order" : "false", - "_dd.library_capabilities.impacted_tests" : "false", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.fail_fast_test_order" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_8}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, diff --git a/dd-smoke-tests/gradle/src/test/resources/test-succeed-multi-forks-new-instrumentation/coverages.ftl b/dd-smoke-tests/gradle/src/test/resources/test-succeed-multi-forks-new-instrumentation/coverages.ftl index 567ef02b425..2fe41431bbf 100644 --- a/dd-smoke-tests/gradle/src/test/resources/test-succeed-multi-forks-new-instrumentation/coverages.ftl +++ b/dd-smoke-tests/gradle/src/test/resources/test-succeed-multi-forks-new-instrumentation/coverages.ftl @@ -1,15 +1,4 @@ [ { - "files" : [ { - "bitmap" : "AAE=", - "filename" : "src/main/java/datadog/smoke/Calculator.java" - }, { - "bitmap" : "AAw=", - "filename" : "src/test/java/datadog/smoke/TestSucceedJunit5.java" - } ], - "span_id" : ${content_span_id_5}, - "test_session_id" : ${content_test_session_id}, - "test_suite_id" : ${content_test_suite_id_2} -}, { "files" : [ { "bitmap" : "gAw=", "filename" : "src/test/java/datadog/smoke/TestSucceed.java" @@ -20,4 +9,15 @@ "span_id" : ${content_span_id_4}, "test_session_id" : ${content_test_session_id}, "test_suite_id" : ${content_test_suite_id} +}, { + "files" : [ { + "bitmap" : "AAE=", + "filename" : "src/main/java/datadog/smoke/Calculator.java" + }, { + "bitmap" : "AAw=", + "filename" : "src/test/java/datadog/smoke/TestSucceedJunit5.java" + } ], + "span_id" : ${content_span_id_5}, + "test_session_id" : ${content_test_session_id}, + "test_suite_id" : ${content_test_suite_id_2} } ] \ No newline at end of file diff --git a/dd-smoke-tests/gradle/src/test/resources/test-succeed-multi-forks-new-instrumentation/events.ftl b/dd-smoke-tests/gradle/src/test/resources/test-succeed-multi-forks-new-instrumentation/events.ftl index 9d66aab6ad6..f6787d25b40 100644 --- a/dd-smoke-tests/gradle/src/test/resources/test-succeed-multi-forks-new-instrumentation/events.ftl +++ b/dd-smoke-tests/gradle/src/test/resources/test-succeed-multi-forks-new-instrumentation/events.ftl @@ -233,13 +233,13 @@ "duration" : ${content_duration_7}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "false", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_7}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, @@ -341,14 +341,14 @@ "duration" : ${content_duration_9}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.fail_fast_test_order" : "false", - "_dd.library_capabilities.impacted_tests" : "false", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.fail_fast_test_order" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_9}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, diff --git a/dd-smoke-tests/gradle/src/test/resources/test-succeed-multi-module-legacy-instrumentation/events.ftl b/dd-smoke-tests/gradle/src/test/resources/test-succeed-multi-module-legacy-instrumentation/events.ftl index c9d9587c30f..86c8cfc55c6 100644 --- a/dd-smoke-tests/gradle/src/test/resources/test-succeed-multi-module-legacy-instrumentation/events.ftl +++ b/dd-smoke-tests/gradle/src/test/resources/test-succeed-multi-module-legacy-instrumentation/events.ftl @@ -191,13 +191,13 @@ "duration" : ${content_duration_5}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "false", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_5}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, @@ -251,13 +251,13 @@ "duration" : ${content_duration_6}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "false", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_6}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, diff --git a/dd-smoke-tests/gradle/src/test/resources/test-succeed-multi-module-new-instrumentation/events.ftl b/dd-smoke-tests/gradle/src/test/resources/test-succeed-multi-module-new-instrumentation/events.ftl index a8d9cb20ab2..fb292803f29 100644 --- a/dd-smoke-tests/gradle/src/test/resources/test-succeed-multi-module-new-instrumentation/events.ftl +++ b/dd-smoke-tests/gradle/src/test/resources/test-succeed-multi-module-new-instrumentation/events.ftl @@ -240,13 +240,13 @@ "duration" : ${content_duration_6}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "false", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_6}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, @@ -300,13 +300,13 @@ "duration" : ${content_duration_7}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "false", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_7}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, diff --git a/dd-smoke-tests/gradle/src/test/resources/test-succeed-new-instrumentation/events.ftl b/dd-smoke-tests/gradle/src/test/resources/test-succeed-new-instrumentation/events.ftl index 460c9fe9d6c..8ed830161db 100644 --- a/dd-smoke-tests/gradle/src/test/resources/test-succeed-new-instrumentation/events.ftl +++ b/dd-smoke-tests/gradle/src/test/resources/test-succeed-new-instrumentation/events.ftl @@ -235,13 +235,13 @@ "duration" : ${content_duration_7}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "false", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_7}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, @@ -295,13 +295,13 @@ "duration" : ${content_duration_8}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "false", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_8}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, diff --git a/dd-smoke-tests/gradle/src/test/resources/test-succeed-old-gradle/events.ftl b/dd-smoke-tests/gradle/src/test/resources/test-succeed-old-gradle/events.ftl index 23d159025ef..b3be4e67298 100644 --- a/dd-smoke-tests/gradle/src/test/resources/test-succeed-old-gradle/events.ftl +++ b/dd-smoke-tests/gradle/src/test/resources/test-succeed-old-gradle/events.ftl @@ -185,13 +185,13 @@ "duration" : ${content_duration_6}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "false", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_6}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, @@ -245,13 +245,13 @@ "duration" : ${content_duration_7}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "false", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_7}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, diff --git a/dd-smoke-tests/maven/src/test/resources/test_failed_maven_run_flaky_retries/events.ftl b/dd-smoke-tests/maven/src/test/resources/test_failed_maven_run_flaky_retries/events.ftl index 94e172a837f..3dcdf89901a 100644 --- a/dd-smoke-tests/maven/src/test/resources/test_failed_maven_run_flaky_retries/events.ftl +++ b/dd-smoke-tests/maven/src/test/resources/test_failed_maven_run_flaky_retries/events.ftl @@ -305,13 +305,13 @@ "duration" : ${content_duration_9}, "error" : 1, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "true", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "true", - "_dd.library_capabilities.test_impact_analysis" : "false", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_9}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, @@ -367,13 +367,13 @@ "duration" : ${content_duration_10}, "error" : 1, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "true", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "true", - "_dd.library_capabilities.test_impact_analysis" : "false", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_10}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, @@ -431,13 +431,13 @@ "duration" : ${content_duration_11}, "error" : 1, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "true", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "true", - "_dd.library_capabilities.test_impact_analysis" : "false", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_11}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, @@ -495,13 +495,13 @@ "duration" : ${content_duration_12}, "error" : 1, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "true", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "true", - "_dd.library_capabilities.test_impact_analysis" : "false", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_12}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, @@ -559,13 +559,13 @@ "duration" : ${content_duration_13}, "error" : 1, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "true", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "true", - "_dd.library_capabilities.test_impact_analysis" : "false", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_13}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, diff --git a/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run/events.ftl b/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run/events.ftl index c4515a48f24..028ae502e83 100644 --- a/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run/events.ftl +++ b/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run/events.ftl @@ -309,13 +309,13 @@ "duration" : ${content_duration_9}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "true", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_9}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, @@ -369,13 +369,13 @@ "duration" : ${content_duration_10}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "true", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_10}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, diff --git a/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_builtin_coverage/events.ftl b/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_builtin_coverage/events.ftl index f2646014b9d..9c08cc57fe1 100644 --- a/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_builtin_coverage/events.ftl +++ b/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_builtin_coverage/events.ftl @@ -273,13 +273,13 @@ "duration" : ${content_duration_8}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "true", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_8}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, @@ -333,13 +333,13 @@ "duration" : ${content_duration_9}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "true", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_9}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, diff --git a/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_impacted_tests/events.ftl b/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_impacted_tests/events.ftl index 7a4cb662146..73aba91b29f 100644 --- a/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_impacted_tests/events.ftl +++ b/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_impacted_tests/events.ftl @@ -271,13 +271,13 @@ "duration" : ${content_duration_8}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "true", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_8}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, @@ -332,13 +332,13 @@ "duration" : ${content_duration_9}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "true", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_9}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, diff --git a/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_junit_platform_runner/events.ftl b/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_junit_platform_runner/events.ftl index a4006651801..721fc4e239a 100644 --- a/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_junit_platform_runner/events.ftl +++ b/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_junit_platform_runner/events.ftl @@ -326,13 +326,13 @@ "duration" : ${content_duration_10}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "true", - "_dd.library_capabilities.test_impact_analysis" : "false", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_10}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, diff --git a/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_multiple_forks/events.ftl b/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_multiple_forks/events.ftl index 67ef45ed060..8affc7a1319 100644 --- a/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_multiple_forks/events.ftl +++ b/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_multiple_forks/events.ftl @@ -309,14 +309,14 @@ "duration" : ${content_duration_9}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.fail_fast_test_order" : "false", - "_dd.library_capabilities.impacted_tests" : "true", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.fail_fast_test_order" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_9}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, @@ -370,14 +370,14 @@ "duration" : ${content_duration_10}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.fail_fast_test_order" : "false", - "_dd.library_capabilities.impacted_tests" : "true", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.fail_fast_test_order" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_10}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, diff --git a/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_surefire_3_0_0/events.ftl b/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_surefire_3_0_0/events.ftl index c4515a48f24..028ae502e83 100644 --- a/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_surefire_3_0_0/events.ftl +++ b/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_surefire_3_0_0/events.ftl @@ -309,13 +309,13 @@ "duration" : ${content_duration_9}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "true", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_9}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, @@ -369,13 +369,13 @@ "duration" : ${content_duration_10}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "true", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_10}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, diff --git a/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_surefire_3_5_0/events.ftl b/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_surefire_3_5_0/events.ftl index c4515a48f24..028ae502e83 100644 --- a/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_surefire_3_5_0/events.ftl +++ b/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_surefire_3_5_0/events.ftl @@ -309,13 +309,13 @@ "duration" : ${content_duration_9}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "true", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_9}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, @@ -369,13 +369,13 @@ "duration" : ${content_duration_10}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "true", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_10}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, diff --git a/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_test_management/events.ftl b/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_test_management/events.ftl index 42cd14dc56e..da63275f2e9 100644 --- a/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_test_management/events.ftl +++ b/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_test_management/events.ftl @@ -273,13 +273,13 @@ "duration" : ${content_duration_8}, "error" : 1, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "true", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "true", - "_dd.library_capabilities.test_management.disable" : "true", - "_dd.library_capabilities.test_management.quarantine" : "true", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_8}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, @@ -337,13 +337,13 @@ "duration" : ${content_duration_9}, "error" : 1, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "true", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "true", - "_dd.library_capabilities.test_management.disable" : "true", - "_dd.library_capabilities.test_management.quarantine" : "true", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_9}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, @@ -403,13 +403,13 @@ "duration" : ${content_duration_10}, "error" : 1, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "true", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "true", - "_dd.library_capabilities.test_management.disable" : "true", - "_dd.library_capabilities.test_management.quarantine" : "true", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_10}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, @@ -469,13 +469,13 @@ "duration" : ${content_duration_11}, "error" : 1, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "true", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "true", - "_dd.library_capabilities.test_management.disable" : "true", - "_dd.library_capabilities.test_management.quarantine" : "true", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_11}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, @@ -535,13 +535,13 @@ "duration" : ${content_duration_12}, "error" : 1, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "true", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "true", - "_dd.library_capabilities.test_management.disable" : "true", - "_dd.library_capabilities.test_management.quarantine" : "true", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_12}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, @@ -602,13 +602,13 @@ "duration" : ${content_duration_13}, "error" : 1, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "true", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "true", - "_dd.library_capabilities.test_management.disable" : "true", - "_dd.library_capabilities.test_management.quarantine" : "true", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_13}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, @@ -713,13 +713,13 @@ "duration" : ${content_duration_15}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "true", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "true", - "_dd.library_capabilities.test_management.disable" : "true", - "_dd.library_capabilities.test_management.quarantine" : "true", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_15}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, diff --git a/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_with_arg_line_property/events.ftl b/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_with_arg_line_property/events.ftl index 3b1e2230da5..43bcef123f8 100644 --- a/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_with_arg_line_property/events.ftl +++ b/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_with_arg_line_property/events.ftl @@ -265,13 +265,13 @@ "duration" : ${content_duration_8}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "true", - "_dd.library_capabilities.test_impact_analysis" : "false", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_8}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, diff --git a/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_with_cucumber/events.ftl b/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_with_cucumber/events.ftl index bc6b96c9fe9..608a5ed70e7 100644 --- a/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_with_cucumber/events.ftl +++ b/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_with_cucumber/events.ftl @@ -363,12 +363,12 @@ "duration" : ${content_duration_11}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.test_impact_analysis" : "false", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_11}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, diff --git a/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_with_jacoco_and_argline/events.ftl b/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_with_jacoco_and_argline/events.ftl index 521e50ac686..15425720a16 100644 --- a/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_with_jacoco_and_argline/events.ftl +++ b/dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_with_jacoco_and_argline/events.ftl @@ -309,13 +309,13 @@ "duration" : ${content_duration_9}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "true", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_9}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, @@ -369,13 +369,13 @@ "duration" : ${content_duration_10}, "error" : 0, "meta" : { - "_dd.library_capabilities.auto_test_retries" : "false", - "_dd.library_capabilities.early_flake_detection" : "false", - "_dd.library_capabilities.impacted_tests" : "true", - "_dd.library_capabilities.test_impact_analysis" : "true", - "_dd.library_capabilities.test_management.attempt_to_fix" : "false", - "_dd.library_capabilities.test_management.disable" : "false", - "_dd.library_capabilities.test_management.quarantine" : "false", + "_dd.library_capabilities.auto_test_retries" : "1", + "_dd.library_capabilities.early_flake_detection" : "1", + "_dd.library_capabilities.impacted_tests" : "1", + "_dd.library_capabilities.test_impact_analysis" : "1", + "_dd.library_capabilities.test_management.attempt_to_fix" : "2", + "_dd.library_capabilities.test_management.disable" : "1", + "_dd.library_capabilities.test_management.quarantine" : "1", "_dd.p.tid" : ${content_meta__dd_p_tid_10}, "_dd.test.is_user_provided_service" : "true", "_dd.tracer_host" : ${content_meta__dd_tracer_host}, diff --git a/internal-api/src/main/java/datadog/trace/api/civisibility/config/LibraryCapability.java b/internal-api/src/main/java/datadog/trace/api/civisibility/config/LibraryCapability.java index 7e3980fc51f..7df45849286 100644 --- a/internal-api/src/main/java/datadog/trace/api/civisibility/config/LibraryCapability.java +++ b/internal-api/src/main/java/datadog/trace/api/civisibility/config/LibraryCapability.java @@ -1,22 +1,28 @@ package datadog.trace.api.civisibility.config; public enum LibraryCapability { - TIA("test_impact_analysis"), - EFD("early_flake_detection"), - ATR("auto_test_retries"), - IMPACTED("impacted_tests"), - FAIL_FAST("fail_fast_test_order"), - QUARANTINE("test_management.quarantine"), - DISABLED("test_management.disable"), - ATTEMPT_TO_FIX("test_management.attempt_to_fix"); + TIA("test_impact_analysis", "1"), + EFD("early_flake_detection", "1"), + ATR("auto_test_retries", "1"), + IMPACTED("impacted_tests", "1"), + FAIL_FAST("fail_fast_test_order", "1"), + QUARANTINE("test_management.quarantine", "1"), + DISABLED("test_management.disable", "1"), + ATTEMPT_TO_FIX("test_management.attempt_to_fix", "2"); private final String tag; + private final String version; - LibraryCapability(String tag) { + LibraryCapability(String tag, String version) { this.tag = tag; + this.version = version; } public String asTag() { return "_dd.library_capabilities." + tag; } + + public String getVersion() { + return version; + } } From 7d5b034ece694ed9c61fc1149db89f0dd047091c Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Wed, 12 Mar 2025 15:54:22 +0000 Subject: [PATCH 27/98] Remove ScopeSource from instrumentation API (#8542) * Migrate activateSpan calls with ScopeSource.MANUAL to activateManualSpan * Remove remaining references to ScopeSource from instrumentation API * Remove ScopeSource reference from test code --- .../datadog/debugger/agent/DebuggerTracer.java | 3 +-- .../com/datadog/debugger/probe/LogProbeTest.java | 5 ++--- .../com/datadog/debugger/CapturedSnapshot20.java | 3 +-- .../com/datadog/debugger/CapturedSnapshot21.java | 9 ++++----- .../com/datadog/debugger/CapturedSnapshot28.java | 3 +-- .../com/datadog/debugger/CapturedSnapshot29.java | 1 - .../com/datadog/debugger/CodeOrigin01.java | 7 +++---- .../com/datadog/debugger/CodeOrigin02.java | 7 +++---- .../com/datadog/debugger/CodeOrigin03.java | 7 +++---- .../com/datadog/debugger/CodeOrigin04.java | 3 +-- .../com/datadog/debugger/CodeOrigin05.java | 7 +++---- .../com/datadog/debugger/TriggerProbe01.java | 7 +++---- .../com/datadog/debugger/TriggerProbe02.java | 5 ++--- .../src/main/java/com/datadog/iast/Reporter.java | 2 +- .../groovy/com/datadog/iast/ReporterTest.groovy | 3 +-- .../java/org/example/TestFailedThenSucceed.java | 5 ++--- .../TestParameterizedSetupSpecSpock.groovy | 3 +-- .../org/example/TestSucceedSetupSpecSpock.groovy | 3 +-- .../java/org/example/TestFailedThenSucceed.java | 5 ++--- .../kotlin/coroutines/CoreKotlinCoroutineTests.kt | 3 +-- .../instrumentation/opentelemetry/OtelTracer.java | 3 +-- .../opentelemetry14/context/ContextTest.groovy | 9 ++++----- .../AddingSpanAttributesAnnotationTest.groovy | 3 +-- .../opentracing31/OTScopeManager.java | 3 +-- .../instrumentation/opentracing31/OTTracer.java | 4 +--- .../opentracing32/OTScopeManager.java | 3 +-- .../instrumentation/opentracing32/OTTracer.java | 7 ++----- .../zio-2.0/src/test/scala/ZioTestFixtures.scala | 3 +-- .../src/test/groovy/AgentTestRunnerTest.groovy | 3 +-- .../src/test/groovy/TraceCorrelationTest.groovy | 2 +- .../main/java/datadog/trace/core/CoreTracer.java | 10 +++++----- .../java/datadog/opentracing/OTScopeManager.java | 3 +-- .../instrumentation/api/AgentTracer.java | 15 ++++++++------- 33 files changed, 64 insertions(+), 95 deletions(-) diff --git a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/agent/DebuggerTracer.java b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/agent/DebuggerTracer.java index 94549fdffd8..92df0d5a654 100644 --- a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/agent/DebuggerTracer.java +++ b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/agent/DebuggerTracer.java @@ -8,7 +8,6 @@ import datadog.trace.bootstrap.instrumentation.api.AgentScope; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.AgentTracer; -import datadog.trace.bootstrap.instrumentation.api.ScopeSource; public class DebuggerTracer implements DebuggerContext.Tracer { public static final String OPERATION_NAME = "dd.dynamic.span"; @@ -36,7 +35,7 @@ public DebuggerSpan createSpan(String encodedProbeId, String resourceName, Strin dynamicSpan.setTag(tag.substring(0, idx), tag.substring(idx + 1)); } } - AgentScope scope = tracerAPI.activateSpan(dynamicSpan, ScopeSource.MANUAL); + AgentScope scope = tracerAPI.activateManualSpan(dynamicSpan); return new DebuggerSpanImpl(dynamicSpan, scope, probeStatusSink, encodedProbeId); } diff --git a/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/probe/LogProbeTest.java b/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/probe/LogProbeTest.java index 4e90641b3e3..247324b3c1c 100644 --- a/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/probe/LogProbeTest.java +++ b/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/probe/LogProbeTest.java @@ -27,7 +27,6 @@ import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.AgentTracer; import datadog.trace.bootstrap.instrumentation.api.AgentTracer.TracerAPI; -import datadog.trace.bootstrap.instrumentation.api.ScopeSource; import datadog.trace.bootstrap.instrumentation.api.Tags; import datadog.trace.core.CoreTracer; import java.util.stream.Stream; @@ -137,7 +136,7 @@ private int runTrace(TracerAPI tracer, boolean captureSnapshot, Integer line, St if (sessionId != null) { span.setTag(Tags.PROPAGATED_DEBUG, sessionId + ":1"); } - try (AgentScope scope = tracer.activateSpan(span, ScopeSource.MANUAL)) { + try (AgentScope scope = tracer.activateManualSpan(span)) { Builder builder = createLog("Budget testing").probeId(ProbeId.newId()).captureSnapshot(captureSnapshot); if (sessionId != null) { @@ -178,7 +177,7 @@ private boolean fillSnapshot(DebugSessionStatus status) { CoreTracer.builder().idGenerationStrategy(IdGenerationStrategy.fromName("random")).build(); AgentTracer.registerIfAbsent(tracer); AgentSpan span = tracer.startSpan("log probe debug session testing", "test span"); - try (AgentScope scope = tracer.activateSpan(span, ScopeSource.MANUAL)) { + try (AgentScope scope = tracer.activateManualSpan(span)) { if (status == DebugSessionStatus.ACTIVE) { span.setTag(Tags.PROPAGATED_DEBUG, DEBUG_SESSION_ID + ":1"); } else if (status == DebugSessionStatus.DISABLED) { diff --git a/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CapturedSnapshot20.java b/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CapturedSnapshot20.java index b7f0f22b193..7dd2f39552c 100644 --- a/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CapturedSnapshot20.java +++ b/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CapturedSnapshot20.java @@ -4,7 +4,6 @@ import datadog.trace.bootstrap.instrumentation.api.AgentScope; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.AgentTracer; -import datadog.trace.bootstrap.instrumentation.api.ScopeSource; import datadog.trace.core.CoreTracer; import java.util.Arrays; @@ -26,7 +25,7 @@ public class CapturedSnapshot20 { public static int main(String arg) { AgentTracer.TracerAPI tracerAPI = AgentTracer.get(); AgentSpan span = tracerAPI.buildSpan("process").start(); - try (AgentScope scope = tracerAPI.activateSpan(span, ScopeSource.MANUAL)) { + try (AgentScope scope = tracerAPI.activateManualSpan(span)) { if (arg.equals("exception") || arg.equals("illegal")) { return new CapturedSnapshot20().processWithException(arg); } diff --git a/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CapturedSnapshot21.java b/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CapturedSnapshot21.java index 1e13c39b3c4..0423fae5fc7 100644 --- a/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CapturedSnapshot21.java +++ b/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CapturedSnapshot21.java @@ -4,7 +4,6 @@ import datadog.trace.bootstrap.instrumentation.api.AgentScope; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.AgentTracer; -import datadog.trace.bootstrap.instrumentation.api.ScopeSource; import datadog.trace.core.CoreTracer; import java.util.Arrays; @@ -26,7 +25,7 @@ public class CapturedSnapshot21 { public static int main(String arg) { AgentTracer.TracerAPI tracerAPI = AgentTracer.get(); AgentSpan span = tracerAPI.buildSpan("rootProcess").start(); - try (AgentScope scope = tracerAPI.activateSpan(span, ScopeSource.MANUAL)) { + try (AgentScope scope = tracerAPI.activateManualSpan(span)) { return new CapturedSnapshot21().rootProcess(arg); } finally { span.finish(); @@ -36,7 +35,7 @@ public static int main(String arg) { private int rootProcess(String arg) { AgentTracer.TracerAPI tracerAPI = AgentTracer.get(); AgentSpan span = tracerAPI.buildSpan("process1").start(); - try (AgentScope scope = tracerAPI.activateSpan(span, ScopeSource.MANUAL)) { + try (AgentScope scope = tracerAPI.activateManualSpan(span)) { return process1(arg) + 1; } finally { span.finish(); @@ -46,7 +45,7 @@ private int rootProcess(String arg) { private int process1(String arg) { AgentTracer.TracerAPI tracerAPI = AgentTracer.get(); AgentSpan span = tracerAPI.buildSpan("process2").start(); - try (AgentScope scope = tracerAPI.activateSpan(span, ScopeSource.MANUAL)) { + try (AgentScope scope = tracerAPI.activateManualSpan(span)) { return process2(arg) + 1; } finally { span.finish(); @@ -56,7 +55,7 @@ private int process1(String arg) { private int process2(String arg) { AgentTracer.TracerAPI tracerAPI = AgentTracer.get(); AgentSpan span = tracerAPI.buildSpan("process3").start(); - try (AgentScope scope = tracerAPI.activateSpan(span, ScopeSource.MANUAL)) { + try (AgentScope scope = tracerAPI.activateManualSpan(span)) { return process3(arg) + 1; } finally { span.finish(); diff --git a/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CapturedSnapshot28.java b/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CapturedSnapshot28.java index 160472ecf92..c1d5212e2d8 100644 --- a/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CapturedSnapshot28.java +++ b/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CapturedSnapshot28.java @@ -4,7 +4,6 @@ import datadog.trace.bootstrap.instrumentation.api.AgentScope; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.AgentTracer; -import datadog.trace.bootstrap.instrumentation.api.ScopeSource; import datadog.trace.core.CoreTracer; import java.util.Arrays; @@ -27,7 +26,7 @@ public class CapturedSnapshot28 { public static int main(String arg) { AgentTracer.TracerAPI tracerAPI = AgentTracer.get(); AgentSpan span = tracerAPI.buildSpan("process").start(); - try (AgentScope scope = tracerAPI.activateSpan(span, ScopeSource.MANUAL)) { + try (AgentScope scope = tracerAPI.activateManualSpan(span)) { return new CapturedSnapshot28().process(arg); } finally { span.finish(); diff --git a/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CapturedSnapshot29.java b/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CapturedSnapshot29.java index c1cb782ae3c..246b7791b6a 100644 --- a/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CapturedSnapshot29.java +++ b/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CapturedSnapshot29.java @@ -4,7 +4,6 @@ import datadog.trace.bootstrap.instrumentation.api.AgentScope; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.AgentTracer; -import datadog.trace.bootstrap.instrumentation.api.ScopeSource; import datadog.trace.core.CoreTracer; import java.util.Arrays; diff --git a/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CodeOrigin01.java b/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CodeOrigin01.java index 356cc2ae36f..e848e4ba841 100644 --- a/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CodeOrigin01.java +++ b/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CodeOrigin01.java @@ -5,7 +5,6 @@ import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.AgentTracer; import datadog.trace.bootstrap.instrumentation.api.AgentTracer.TracerAPI; -import datadog.trace.bootstrap.instrumentation.api.ScopeSource; import datadog.trace.core.DDSpan; public class CodeOrigin01 { @@ -15,7 +14,7 @@ public class CodeOrigin01 { public static int main(String arg) throws ReflectiveOperationException { AgentSpan span = newSpan("main"); - AgentScope scope = tracerAPI.activateSpan(span, ScopeSource.MANUAL); + AgentScope scope = tracerAPI.activateManualSpan(span); if (arg.equals("debug_1")) { ((DDSpan) span.getLocalRootSpan()).setTag("_dd.p.debug", "1"); } else if (arg.equals("debug_0")) { @@ -32,13 +31,13 @@ public static int main(String arg) throws ReflectiveOperationException { private static void fullTrace() throws NoSuchMethodException { AgentSpan span = newSpan("entry"); - AgentScope scope = tracerAPI.activateSpan(span, ScopeSource.MANUAL); + AgentScope scope = tracerAPI.activateManualSpan(span); entry(); span.finish(); scope.close(); span = newSpan("exit"); - scope = tracerAPI.activateSpan(span, ScopeSource.MANUAL); + scope = tracerAPI.activateManualSpan(span); exit(); span.finish(); scope.close(); diff --git a/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CodeOrigin02.java b/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CodeOrigin02.java index b15127496a2..8e277b02605 100644 --- a/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CodeOrigin02.java +++ b/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CodeOrigin02.java @@ -5,7 +5,6 @@ import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.AgentTracer; import datadog.trace.bootstrap.instrumentation.api.AgentTracer.TracerAPI; -import datadog.trace.bootstrap.instrumentation.api.ScopeSource; import datadog.trace.core.DDSpan; public class CodeOrigin02 { @@ -15,7 +14,7 @@ public class CodeOrigin02 { public static int main(String arg) throws ReflectiveOperationException { AgentSpan span = newSpan("main"); - AgentScope scope = tracerAPI.activateSpan(span, ScopeSource.MANUAL); + AgentScope scope = tracerAPI.activateManualSpan(span); if (arg.equals("debug_1")) { ((DDSpan) span.getLocalRootSpan()).setTag("_dd.p.debug", "1"); } else if (arg.equals("debug_0")) { @@ -32,13 +31,13 @@ public static int main(String arg) throws ReflectiveOperationException { private static void fullTrace() throws NoSuchMethodException { AgentSpan span = newSpan("entry"); - AgentScope scope = tracerAPI.activateSpan(span, ScopeSource.MANUAL); + AgentScope scope = tracerAPI.activateManualSpan(span); entry(); span.finish(); scope.close(); span = newSpan("exit"); - scope = tracerAPI.activateSpan(span, ScopeSource.MANUAL); + scope = tracerAPI.activateManualSpan(span); exit(); span.finish(); scope.close(); diff --git a/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CodeOrigin03.java b/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CodeOrigin03.java index cfd0b9ee219..a256bb51050 100644 --- a/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CodeOrigin03.java +++ b/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CodeOrigin03.java @@ -5,7 +5,6 @@ import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.AgentTracer; import datadog.trace.bootstrap.instrumentation.api.AgentTracer.TracerAPI; -import datadog.trace.bootstrap.instrumentation.api.ScopeSource; import datadog.trace.core.DDSpan; public class CodeOrigin03 { @@ -15,7 +14,7 @@ public class CodeOrigin03 { public static int main(String arg) throws ReflectiveOperationException { AgentSpan span = newSpan("main"); - AgentScope scope = tracerAPI.activateSpan(span, ScopeSource.MANUAL); + AgentScope scope = tracerAPI.activateManualSpan(span); if (arg.equals("debug_1")) { ((DDSpan) span.getLocalRootSpan()).setTag("_dd.p.debug", "1"); } else if (arg.equals("debug_0")) { @@ -32,13 +31,13 @@ public static int main(String arg) throws ReflectiveOperationException { private static void fullTrace() throws NoSuchMethodException { AgentSpan span = newSpan("entry"); - AgentScope scope = tracerAPI.activateSpan(span, ScopeSource.MANUAL); + AgentScope scope = tracerAPI.activateManualSpan(span); entry(); span.finish(); scope.close(); span = newSpan("exit"); - scope = tracerAPI.activateSpan(span, ScopeSource.MANUAL); + scope = tracerAPI.activateManualSpan(span); exit(); span.finish(); scope.close(); diff --git a/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CodeOrigin04.java b/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CodeOrigin04.java index 7ce08e2d1f1..7cabe4231a1 100644 --- a/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CodeOrigin04.java +++ b/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CodeOrigin04.java @@ -4,7 +4,6 @@ import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.AgentTracer; import datadog.trace.bootstrap.instrumentation.api.AgentTracer.TracerAPI; -import datadog.trace.bootstrap.instrumentation.api.ScopeSource; public class CodeOrigin04 { private int intField = 42; @@ -24,7 +23,7 @@ private static void doExit(int level) { AgentSpan span; AgentScope scope; span = newSpan("exit"); - scope = tracerAPI.activateSpan(span, ScopeSource.MANUAL); + scope = tracerAPI.activateManualSpan(span); exit(); span.finish(); scope.close(); diff --git a/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CodeOrigin05.java b/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CodeOrigin05.java index c55c5cc8511..55b40d6bafc 100644 --- a/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CodeOrigin05.java +++ b/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/CodeOrigin05.java @@ -5,7 +5,6 @@ import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.AgentTracer; import datadog.trace.bootstrap.instrumentation.api.AgentTracer.TracerAPI; -import datadog.trace.bootstrap.instrumentation.api.ScopeSource; import datadog.trace.core.DDSpan; public class CodeOrigin05 { @@ -15,7 +14,7 @@ public class CodeOrigin05 { public static int main(String arg) throws ReflectiveOperationException { AgentSpan span = newSpan("main"); - AgentScope scope = tracerAPI.activateSpan(span, ScopeSource.MANUAL); + AgentScope scope = tracerAPI.activateManualSpan(span); if (arg.equals("debug_1")) { ((DDSpan) span.getLocalRootSpan()).setTag("_dd.p.debug", "1"); } else if (arg.equals("debug_0")) { @@ -32,13 +31,13 @@ public static int main(String arg) throws ReflectiveOperationException { private static void fullTrace() throws NoSuchMethodException { AgentSpan span = newSpan("entry"); - AgentScope scope = tracerAPI.activateSpan(span, ScopeSource.MANUAL); + AgentScope scope = tracerAPI.activateManualSpan(span); entry(); span.finish(); scope.close(); span = newSpan("exit"); - scope = tracerAPI.activateSpan(span, ScopeSource.MANUAL); + scope = tracerAPI.activateManualSpan(span); exit(); span.finish(); scope.close(); diff --git a/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/TriggerProbe01.java b/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/TriggerProbe01.java index 167ff85b791..8181142c581 100644 --- a/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/TriggerProbe01.java +++ b/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/TriggerProbe01.java @@ -5,7 +5,6 @@ import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.AgentTracer; import datadog.trace.bootstrap.instrumentation.api.AgentTracer.TracerAPI; -import datadog.trace.bootstrap.instrumentation.api.ScopeSource; import datadog.trace.core.DDSpan; public class TriggerProbe01 { @@ -15,7 +14,7 @@ public class TriggerProbe01 { public static int main(String arg) throws ReflectiveOperationException { AgentSpan span = newSpan("main"); - AgentScope scope = tracerAPI.activateSpan(span, ScopeSource.MANUAL); + AgentScope scope = tracerAPI.activateManualSpan(span); fullTrace(); @@ -27,13 +26,13 @@ public static int main(String arg) throws ReflectiveOperationException { private static void fullTrace() throws NoSuchMethodException { AgentSpan span = newSpan("entry"); - AgentScope scope = tracerAPI.activateSpan(span, ScopeSource.MANUAL); + AgentScope scope = tracerAPI.activateManualSpan(span); entry(); span.finish(); scope.close(); span = newSpan("exit"); - scope = tracerAPI.activateSpan(span, ScopeSource.MANUAL); + scope = tracerAPI.activateManualSpan(span); exit(); span.finish(); scope.close(); diff --git a/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/TriggerProbe02.java b/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/TriggerProbe02.java index 0fcee82f695..f3323b89872 100644 --- a/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/TriggerProbe02.java +++ b/dd-java-agent/agent-debugger/src/test/resources/com/datadog/debugger/TriggerProbe02.java @@ -5,7 +5,6 @@ import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.AgentTracer; import datadog.trace.bootstrap.instrumentation.api.AgentTracer.TracerAPI; -import datadog.trace.bootstrap.instrumentation.api.ScopeSource; import datadog.trace.core.DDSpan; public class TriggerProbe02 { @@ -15,7 +14,7 @@ public class TriggerProbe02 { public static int main(Integer value) throws ReflectiveOperationException { AgentSpan span = newSpan("main"); - AgentScope scope = tracerAPI.activateSpan(span, ScopeSource.MANUAL); + AgentScope scope = tracerAPI.activateManualSpan(span); fullTrace(value); @@ -27,7 +26,7 @@ public static int main(Integer value) throws ReflectiveOperationException { private static void fullTrace(int value) throws NoSuchMethodException { AgentSpan span = newSpan("entry"); - AgentScope scope = tracerAPI.activateSpan(span, ScopeSource.MANUAL); + AgentScope scope = tracerAPI.activateManualSpan(span); entry(value); span.finish(); scope.close(); diff --git a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/Reporter.java b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/Reporter.java index 370d111bc65..20222ba551c 100644 --- a/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/Reporter.java +++ b/dd-java-agent/agent-iast/src/main/java/com/datadog/iast/Reporter.java @@ -61,7 +61,7 @@ public void report(@Nullable final AgentSpan span, @Nonnull final Vulnerability } if (span == null) { final AgentSpan newSpan = startNewSpan(); - try (final AgentScope autoClosed = tracer().activateSpan(newSpan, ScopeSource.MANUAL)) { + try (final AgentScope autoClosed = tracer().activateManualSpan(newSpan)) { vulnerability.updateSpan(newSpan); reportVulnerability(newSpan, vulnerability); } finally { diff --git a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/ReporterTest.groovy b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/ReporterTest.groovy index c162faadcfe..28898db89a6 100644 --- a/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/ReporterTest.groovy +++ b/dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/ReporterTest.groovy @@ -16,7 +16,6 @@ import datadog.trace.bootstrap.instrumentation.api.AgentSpanContext import datadog.trace.bootstrap.instrumentation.api.AgentTracer import datadog.trace.bootstrap.instrumentation.api.AgentTracer.TracerAPI import datadog.trace.bootstrap.instrumentation.api.InternalSpanTypes -import datadog.trace.bootstrap.instrumentation.api.ScopeSource import datadog.trace.test.util.DDSpecification import datadog.trace.util.AgentTaskScheduler import datadog.trace.util.stacktrace.StackTraceEvent @@ -232,7 +231,7 @@ class ReporterTest extends DDSpecification { then: noExceptionThrown() 1 * tracerAPI.startSpan('iast', 'vulnerability', _ as AgentSpanContext) >> span - 1 * tracerAPI.activateSpan(span, ScopeSource.MANUAL) >> scope + 1 * tracerAPI.activateManualSpan(span) >> scope 1 * span.getRequestContext() >> reqCtx 1 * span.setSpanType(InternalSpanTypes.VULNERABILITY) >> span 1 * span.setTag(ANALYZED.key(), ANALYZED.value()) diff --git a/dd-java-agent/instrumentation/junit-4.10/src/test/java/org/example/TestFailedThenSucceed.java b/dd-java-agent/instrumentation/junit-4.10/src/test/java/org/example/TestFailedThenSucceed.java index 1183ae17d6c..7c46ae4042e 100644 --- a/dd-java-agent/instrumentation/junit-4.10/src/test/java/org/example/TestFailedThenSucceed.java +++ b/dd-java-agent/instrumentation/junit-4.10/src/test/java/org/example/TestFailedThenSucceed.java @@ -5,7 +5,6 @@ import datadog.trace.bootstrap.instrumentation.api.AgentScope; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.AgentTracer; -import datadog.trace.bootstrap.instrumentation.api.ScopeSource; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -18,7 +17,7 @@ public class TestFailedThenSucceed { public void setUp() { AgentTracer.TracerAPI agentTracer = AgentTracer.get(); AgentSpan span = agentTracer.buildSpan("junit-manual", "set-up").start(); - try (AgentScope scope = agentTracer.activateSpan(span, ScopeSource.MANUAL)) { + try (AgentScope scope = agentTracer.activateManualSpan(span)) { // tracing setup to verify that it is executed for every retry } span.finish(); @@ -33,7 +32,7 @@ public void test_failed_then_succeed() { public void tearDown() { AgentTracer.TracerAPI agentTracer = AgentTracer.get(); AgentSpan span = agentTracer.buildSpan("junit-manual", "tear-down").start(); - try (AgentScope scope = agentTracer.activateSpan(span, ScopeSource.MANUAL)) { + try (AgentScope scope = agentTracer.activateManualSpan(span)) { // tracing teardown to verify that it is executed for every retry } span.finish(); diff --git a/dd-java-agent/instrumentation/junit-5.3/spock-junit-5/src/test/groovy/org/example/TestParameterizedSetupSpecSpock.groovy b/dd-java-agent/instrumentation/junit-5.3/spock-junit-5/src/test/groovy/org/example/TestParameterizedSetupSpecSpock.groovy index bd48300107f..20b65ca7bf6 100644 --- a/dd-java-agent/instrumentation/junit-5.3/spock-junit-5/src/test/groovy/org/example/TestParameterizedSetupSpecSpock.groovy +++ b/dd-java-agent/instrumentation/junit-5.3/spock-junit-5/src/test/groovy/org/example/TestParameterizedSetupSpecSpock.groovy @@ -3,7 +3,6 @@ package org.example import datadog.trace.bootstrap.instrumentation.api.AgentScope import datadog.trace.bootstrap.instrumentation.api.AgentSpan import datadog.trace.bootstrap.instrumentation.api.AgentTracer -import datadog.trace.bootstrap.instrumentation.api.ScopeSource import spock.lang.Specification class TestParameterizedSetupSpecSpock extends Specification { @@ -11,7 +10,7 @@ class TestParameterizedSetupSpecSpock extends Specification { def setupSpec() { AgentTracer.TracerAPI agentTracer = AgentTracer.get() AgentSpan span = agentTracer.buildSpan("spock-manual", "spec-setup").start() - try (AgentScope scope = agentTracer.activateSpan(span, ScopeSource.MANUAL)) { + try (AgentScope scope = agentTracer.activateManualSpan(span)) { // manually trace spec setup to check whether ITR skips it or not } span.finish() diff --git a/dd-java-agent/instrumentation/junit-5.3/spock-junit-5/src/test/groovy/org/example/TestSucceedSetupSpecSpock.groovy b/dd-java-agent/instrumentation/junit-5.3/spock-junit-5/src/test/groovy/org/example/TestSucceedSetupSpecSpock.groovy index 56c505e200b..d31301e8379 100644 --- a/dd-java-agent/instrumentation/junit-5.3/spock-junit-5/src/test/groovy/org/example/TestSucceedSetupSpecSpock.groovy +++ b/dd-java-agent/instrumentation/junit-5.3/spock-junit-5/src/test/groovy/org/example/TestSucceedSetupSpecSpock.groovy @@ -3,7 +3,6 @@ package org.example import datadog.trace.bootstrap.instrumentation.api.AgentScope import datadog.trace.bootstrap.instrumentation.api.AgentSpan import datadog.trace.bootstrap.instrumentation.api.AgentTracer -import datadog.trace.bootstrap.instrumentation.api.ScopeSource import spock.lang.Specification class TestSucceedSetupSpecSpock extends Specification { @@ -11,7 +10,7 @@ class TestSucceedSetupSpecSpock extends Specification { def setupSpec() { AgentTracer.TracerAPI agentTracer = AgentTracer.get() AgentSpan span = agentTracer.buildSpan("spock-manual", "spec-setup").start() - try (AgentScope scope = agentTracer.activateSpan(span, ScopeSource.MANUAL)) { + try (AgentScope scope = agentTracer.activateManualSpan(span)) { // manually trace spec setup to check whether ITR skips it or not } span.finish() diff --git a/dd-java-agent/instrumentation/junit-5.3/src/test/java/org/example/TestFailedThenSucceed.java b/dd-java-agent/instrumentation/junit-5.3/src/test/java/org/example/TestFailedThenSucceed.java index 77196bfe73e..38ea775d7d8 100644 --- a/dd-java-agent/instrumentation/junit-5.3/src/test/java/org/example/TestFailedThenSucceed.java +++ b/dd-java-agent/instrumentation/junit-5.3/src/test/java/org/example/TestFailedThenSucceed.java @@ -5,7 +5,6 @@ import datadog.trace.bootstrap.instrumentation.api.AgentScope; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.AgentTracer; -import datadog.trace.bootstrap.instrumentation.api.ScopeSource; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -18,7 +17,7 @@ public class TestFailedThenSucceed { public void setUp() { AgentTracer.TracerAPI agentTracer = AgentTracer.get(); AgentSpan span = agentTracer.buildSpan("junit-manual", "set-up").start(); - try (AgentScope scope = agentTracer.activateSpan(span, ScopeSource.MANUAL)) { + try (AgentScope scope = agentTracer.activateManualSpan(span)) { // tracing setup to verify that it is executed for every retry } span.finish(); @@ -33,7 +32,7 @@ public void test_failed_then_succeed() { public void tearDown() { AgentTracer.TracerAPI agentTracer = AgentTracer.get(); AgentSpan span = agentTracer.buildSpan("junit-manual", "tear-down").start(); - try (AgentScope scope = agentTracer.activateSpan(span, ScopeSource.MANUAL)) { + try (AgentScope scope = agentTracer.activateManualSpan(span)) { // tracing teardown to verify that it is executed for every retry } span.finish(); diff --git a/dd-java-agent/instrumentation/kotlin-coroutines/src/testFixtures/kotlin/datadog/trace/instrumentation/kotlin/coroutines/CoreKotlinCoroutineTests.kt b/dd-java-agent/instrumentation/kotlin-coroutines/src/testFixtures/kotlin/datadog/trace/instrumentation/kotlin/coroutines/CoreKotlinCoroutineTests.kt index e8f711dd214..d7f45b68627 100644 --- a/dd-java-agent/instrumentation/kotlin-coroutines/src/testFixtures/kotlin/datadog/trace/instrumentation/kotlin/coroutines/CoreKotlinCoroutineTests.kt +++ b/dd-java-agent/instrumentation/kotlin-coroutines/src/testFixtures/kotlin/datadog/trace/instrumentation/kotlin/coroutines/CoreKotlinCoroutineTests.kt @@ -5,7 +5,6 @@ import datadog.trace.bootstrap.instrumentation.api.AgentSpan import datadog.trace.bootstrap.instrumentation.api.AgentTracer.activeSpan import datadog.trace.bootstrap.instrumentation.api.AgentTracer.get import datadog.trace.bootstrap.instrumentation.api.AgentTracer.setAsyncPropagationEnabled -import datadog.trace.bootstrap.instrumentation.api.ScopeSource.INSTRUMENTATION import edu.umd.cs.findbugs.annotations.SuppressFBWarnings import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CoroutineDispatcher @@ -381,7 +380,7 @@ abstract class CoreKotlinCoroutineTests(private val dispatcher: CoroutineDispatc protected suspend fun AgentSpan.activateAndUse(block: suspend () -> Unit) { try { - get().activateSpan(this, INSTRUMENTATION).use { + get().activateManualSpan(this).use { block() } } finally { diff --git a/dd-java-agent/instrumentation/opentelemetry/opentelemetry-0.3/src/main/java/datadog/trace/instrumentation/opentelemetry/OtelTracer.java b/dd-java-agent/instrumentation/opentelemetry/opentelemetry-0.3/src/main/java/datadog/trace/instrumentation/opentelemetry/OtelTracer.java index 56fe823ac6d..0ba050f2ad3 100644 --- a/dd-java-agent/instrumentation/opentelemetry/opentelemetry-0.3/src/main/java/datadog/trace/instrumentation/opentelemetry/OtelTracer.java +++ b/dd-java-agent/instrumentation/opentelemetry/opentelemetry-0.3/src/main/java/datadog/trace/instrumentation/opentelemetry/OtelTracer.java @@ -3,7 +3,6 @@ import datadog.trace.bootstrap.instrumentation.api.AgentScope; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.AgentTracer; -import datadog.trace.bootstrap.instrumentation.api.ScopeSource; import datadog.trace.bootstrap.instrumentation.api.Tags; import io.opentelemetry.common.AttributeValue; import io.opentelemetry.context.Scope; @@ -39,7 +38,7 @@ public Scope withSpan(final Span span) { } final AgentSpan agentSpan = converter.toAgentSpan(span); - final AgentScope agentScope = tracer.activateSpan(agentSpan, ScopeSource.MANUAL); + final AgentScope agentScope = tracer.activateManualSpan(agentSpan); return converter.toScope(agentScope); } diff --git a/dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.4/src/test/groovy/opentelemetry14/context/ContextTest.groovy b/dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.4/src/test/groovy/opentelemetry14/context/ContextTest.groovy index 023cdce1643..856da3b830f 100644 --- a/dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.4/src/test/groovy/opentelemetry14/context/ContextTest.groovy +++ b/dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.4/src/test/groovy/opentelemetry14/context/ContextTest.groovy @@ -10,7 +10,6 @@ import io.opentelemetry.context.ImplicitContextKeyed import io.opentelemetry.context.ThreadLocalContextStorage import spock.lang.Subject -import static datadog.trace.bootstrap.instrumentation.api.ScopeSource.MANUAL import static datadog.opentelemetry.shim.context.OtelContext.OTEL_CONTEXT_ROOT_SPAN_KEY import static datadog.opentelemetry.shim.context.OtelContext.OTEL_CONTEXT_SPAN_KEY import static datadog.opentelemetry.shim.trace.OtelConventions.SPAN_KIND_INTERNAL @@ -48,7 +47,7 @@ class ContextTest extends AgentTestRunner { when: def ddSpan = TEST_TRACER.startSpan("dd-api", "other-name") - def ddScope = TEST_TRACER.activateSpan(ddSpan, MANUAL) + def ddScope = TEST_TRACER.activateManualSpan(ddSpan) currentSpan = Span.current() then: @@ -97,7 +96,7 @@ class ContextTest extends AgentTestRunner { def "test Context.makeCurrent() to activate a span with another currently active span"() { setup: def ddSpan = TEST_TRACER.startSpan("dd-api", "some-name") - def ddScope = TEST_TRACER.activateSpan(ddSpan, MANUAL) + def ddScope = TEST_TRACER.activateManualSpan(ddSpan) def builder = tracer.spanBuilder("other-name") def otelSpan = builder.startSpan() @@ -135,7 +134,7 @@ class ContextTest extends AgentTestRunner { def "test Context.makeCurrent() to activate an already active span"() { when: def ddSpan = TEST_TRACER.startSpan("dd-api", "some-name") - def ddScope = TEST_TRACER.activateSpan(ddSpan, MANUAL) + def ddScope = TEST_TRACER.activateManualSpan(ddSpan) def currentSpan = Span.current() then: @@ -196,7 +195,7 @@ class ContextTest extends AgentTestRunner { when: def ddChildSpan = TEST_TRACER.startSpan("dd-api", "other-name") - def ddChildScope = TEST_TRACER.activateSpan(ddChildSpan, MANUAL) + def ddChildScope = TEST_TRACER.activateManualSpan(ddChildSpan) def current = Span.current() then: diff --git a/dd-java-agent/instrumentation/opentelemetry/opentelemetry-annotations-1.26/src/test/groovy/AddingSpanAttributesAnnotationTest.groovy b/dd-java-agent/instrumentation/opentelemetry/opentelemetry-annotations-1.26/src/test/groovy/AddingSpanAttributesAnnotationTest.groovy index a4bb4d02481..f8fc32dd42f 100644 --- a/dd-java-agent/instrumentation/opentelemetry/opentelemetry-annotations-1.26/src/test/groovy/AddingSpanAttributesAnnotationTest.groovy +++ b/dd-java-agent/instrumentation/opentelemetry/opentelemetry-annotations-1.26/src/test/groovy/AddingSpanAttributesAnnotationTest.groovy @@ -1,6 +1,5 @@ import annotatedsample.AnnotatedMethods import datadog.trace.agent.test.AgentTestRunner -import datadog.trace.bootstrap.instrumentation.api.ScopeSource class AddingSpanAttributesAnnotationTest extends AgentTestRunner { @Override @@ -14,7 +13,7 @@ class AddingSpanAttributesAnnotationTest extends AgentTestRunner { setup: def methodName = "sayHelloWith${typeName}Attribute" def testSpan = TEST_TRACER.startSpan("test", "operation") - def scope = TEST_TRACER.activateSpan(testSpan, ScopeSource.INSTRUMENTATION) + def scope = TEST_TRACER.activateManualSpan(testSpan) AnnotatedMethods."$methodName"(value) scope.close() testSpan.finish() diff --git a/dd-java-agent/instrumentation/opentracing/api-0.31/src/main/java/datadog/trace/instrumentation/opentracing31/OTScopeManager.java b/dd-java-agent/instrumentation/opentracing/api-0.31/src/main/java/datadog/trace/instrumentation/opentracing31/OTScopeManager.java index e7f1987163a..6028aefea15 100644 --- a/dd-java-agent/instrumentation/opentracing/api-0.31/src/main/java/datadog/trace/instrumentation/opentracing31/OTScopeManager.java +++ b/dd-java-agent/instrumentation/opentracing/api-0.31/src/main/java/datadog/trace/instrumentation/opentracing31/OTScopeManager.java @@ -4,7 +4,6 @@ import datadog.trace.bootstrap.instrumentation.api.AgentScope; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.AgentTracer; -import datadog.trace.bootstrap.instrumentation.api.ScopeSource; import datadog.trace.context.TraceScope; import io.opentracing.Scope; import io.opentracing.ScopeManager; @@ -30,7 +29,7 @@ public Scope activate(final Span span, final boolean finishSpanOnClose) { } final AgentSpan agentSpan = converter.toAgentSpan(span); - final AgentScope agentScope = tracer.activateSpan(agentSpan, ScopeSource.MANUAL); + final AgentScope agentScope = tracer.activateManualSpan(agentSpan); return converter.toScope(agentScope, finishSpanOnClose); } diff --git a/dd-java-agent/instrumentation/opentracing/api-0.31/src/main/java/datadog/trace/instrumentation/opentracing31/OTTracer.java b/dd-java-agent/instrumentation/opentracing/api-0.31/src/main/java/datadog/trace/instrumentation/opentracing31/OTTracer.java index 5997127b619..7074a62b377 100644 --- a/dd-java-agent/instrumentation/opentracing/api-0.31/src/main/java/datadog/trace/instrumentation/opentracing31/OTTracer.java +++ b/dd-java-agent/instrumentation/opentracing/api-0.31/src/main/java/datadog/trace/instrumentation/opentracing31/OTTracer.java @@ -8,7 +8,6 @@ import datadog.trace.bootstrap.instrumentation.api.AgentSpanContext; import datadog.trace.bootstrap.instrumentation.api.AgentTracer; import datadog.trace.bootstrap.instrumentation.api.ContextVisitors; -import datadog.trace.bootstrap.instrumentation.api.ScopeSource; import datadog.trace.instrumentation.opentracing.DefaultLogHandler; import io.opentracing.References; import io.opentracing.Scope; @@ -157,8 +156,7 @@ public Span start() { @Override public Scope startActive(final boolean finishSpanOnClose) { - return converter.toScope( - tracer.activateSpan(delegate.start(), ScopeSource.MANUAL), finishSpanOnClose); + return converter.toScope(tracer.activateManualSpan(delegate.start()), finishSpanOnClose); } } } diff --git a/dd-java-agent/instrumentation/opentracing/api-0.32/src/main/java/datadog/trace/instrumentation/opentracing32/OTScopeManager.java b/dd-java-agent/instrumentation/opentracing/api-0.32/src/main/java/datadog/trace/instrumentation/opentracing32/OTScopeManager.java index bb9da45e1ec..ee007d8d770 100644 --- a/dd-java-agent/instrumentation/opentracing/api-0.32/src/main/java/datadog/trace/instrumentation/opentracing32/OTScopeManager.java +++ b/dd-java-agent/instrumentation/opentracing/api-0.32/src/main/java/datadog/trace/instrumentation/opentracing32/OTScopeManager.java @@ -4,7 +4,6 @@ import datadog.trace.bootstrap.instrumentation.api.AgentScope; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.AgentTracer; -import datadog.trace.bootstrap.instrumentation.api.ScopeSource; import datadog.trace.context.TraceScope; import io.opentracing.Scope; import io.opentracing.ScopeManager; @@ -35,7 +34,7 @@ public Scope activate(final Span span, final boolean finishSpanOnClose) { } final AgentSpan agentSpan = converter.toAgentSpan(span); - final AgentScope agentScope = tracer.activateSpan(agentSpan, ScopeSource.MANUAL); + final AgentScope agentScope = tracer.activateManualSpan(agentSpan); return converter.toScope(agentScope, finishSpanOnClose); } diff --git a/dd-java-agent/instrumentation/opentracing/api-0.32/src/main/java/datadog/trace/instrumentation/opentracing32/OTTracer.java b/dd-java-agent/instrumentation/opentracing/api-0.32/src/main/java/datadog/trace/instrumentation/opentracing32/OTTracer.java index acb4b8c5e67..83094d05722 100644 --- a/dd-java-agent/instrumentation/opentracing/api-0.32/src/main/java/datadog/trace/instrumentation/opentracing32/OTTracer.java +++ b/dd-java-agent/instrumentation/opentracing/api-0.32/src/main/java/datadog/trace/instrumentation/opentracing32/OTTracer.java @@ -8,7 +8,6 @@ import datadog.trace.bootstrap.instrumentation.api.AgentSpanContext; import datadog.trace.bootstrap.instrumentation.api.AgentTracer; import datadog.trace.bootstrap.instrumentation.api.ContextVisitors; -import datadog.trace.bootstrap.instrumentation.api.ScopeSource; import datadog.trace.instrumentation.opentracing.DefaultLogHandler; import io.opentracing.References; import io.opentracing.Scope; @@ -52,8 +51,7 @@ public Scope activateSpan(final Span span) { return null; } - return converter.toScope( - tracer.activateSpan(converter.toAgentSpan(span), ScopeSource.MANUAL), false); + return converter.toScope(tracer.activateManualSpan(converter.toAgentSpan(span)), false); } @Override @@ -180,8 +178,7 @@ public Span start() { @Override public Scope startActive(final boolean finishSpanOnClose) { - return converter.toScope( - tracer.activateSpan(delegate.start(), ScopeSource.MANUAL), finishSpanOnClose); + return converter.toScope(tracer.activateManualSpan(delegate.start()), finishSpanOnClose); } } } diff --git a/dd-java-agent/instrumentation/zio/zio-2.0/src/test/scala/ZioTestFixtures.scala b/dd-java-agent/instrumentation/zio/zio-2.0/src/test/scala/ZioTestFixtures.scala index b0b4fba990d..053074ded3d 100644 --- a/dd-java-agent/instrumentation/zio/zio-2.0/src/test/scala/ZioTestFixtures.scala +++ b/dd-java-agent/instrumentation/zio/zio-2.0/src/test/scala/ZioTestFixtures.scala @@ -1,5 +1,4 @@ import datadog.trace.bootstrap.instrumentation.api.AgentTracer -import datadog.trace.bootstrap.instrumentation.api.ScopeSource.INSTRUMENTATION import zio._ import java.util.concurrent.Executors @@ -127,7 +126,7 @@ object ZioTestFixtures { .start() ) ddScope <- ZIO.succeed( - AgentTracer.get().activateSpan(ddSpan, INSTRUMENTATION) + AgentTracer.get().activateManualSpan(ddSpan) ) _ <- scope.addFinalizer(ZIO.succeed(ddScope.close())) _ <- scope.addFinalizer(ZIO.succeed(ddSpan.finish())) diff --git a/dd-java-agent/testing/src/test/groovy/AgentTestRunnerTest.groovy b/dd-java-agent/testing/src/test/groovy/AgentTestRunnerTest.groovy index f29fd7a859a..50a09a2c8ab 100644 --- a/dd-java-agent/testing/src/test/groovy/AgentTestRunnerTest.groovy +++ b/dd-java-agent/testing/src/test/groovy/AgentTestRunnerTest.groovy @@ -8,7 +8,6 @@ import datadog.trace.bootstrap.Constants import datadog.trace.bootstrap.instrumentation.api.AgentScope import datadog.trace.bootstrap.instrumentation.api.AgentSpan import datadog.trace.bootstrap.instrumentation.api.AgentTracer -import datadog.trace.bootstrap.instrumentation.api.ScopeSource import spock.lang.Shared import java.util.concurrent.TimeoutException @@ -115,7 +114,7 @@ class AgentTestRunnerTest extends AgentTestRunner { when: AgentScope scope runUnderTrace("parent") { - scope = TEST_TRACER.activateSpan(noopSpan(), ScopeSource.INSTRUMENTATION) + scope = TEST_TRACER.activateManualSpan(noopSpan()) blockUntilChildSpansFinished(1) } diff --git a/dd-java-agent/testing/src/test/groovy/TraceCorrelationTest.groovy b/dd-java-agent/testing/src/test/groovy/TraceCorrelationTest.groovy index 5e1698c15b2..0d90726f42d 100644 --- a/dd-java-agent/testing/src/test/groovy/TraceCorrelationTest.groovy +++ b/dd-java-agent/testing/src/test/groovy/TraceCorrelationTest.groovy @@ -9,7 +9,7 @@ class TraceCorrelationTest extends AgentTestRunner { def "access trace correlation only under trace"() { when: def span = TEST_TRACER.startSpan("test", "myspan") - def scope = TEST_TRACER.activateSpan(span) + def scope = TEST_TRACER.activateManualSpan(span) then: CorrelationIdentifier.traceId == (span.traceId.toHighOrderLong() == 0 ? span.traceId.toString() : span.traceId.toHexString()) diff --git a/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java b/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java index 2a9198d736b..320610bdd60 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java @@ -907,17 +907,17 @@ public AgentSpan startSpan( } public AgentScope activateSpan(final AgentSpan span) { - return scopeManager.activate(span, ScopeSource.INSTRUMENTATION, DEFAULT_ASYNC_PROPAGATING); + return activateSpan(span, DEFAULT_ASYNC_PROPAGATING); } @Override - public AgentScope activateSpan(final AgentSpan span, final ScopeSource source) { - return scopeManager.activate(span, source); + public AgentScope activateSpan(AgentSpan span, boolean isAsyncPropagating) { + return scopeManager.activate(span, ScopeSource.INSTRUMENTATION, isAsyncPropagating); } @Override - public AgentScope activateSpan(AgentSpan span, ScopeSource source, boolean isAsyncPropagating) { - return scopeManager.activate(span, source, isAsyncPropagating); + public AgentScope activateManualSpan(final AgentSpan span) { + return scopeManager.activate(span, ScopeSource.MANUAL); } @Override diff --git a/dd-trace-ot/src/main/java/datadog/opentracing/OTScopeManager.java b/dd-trace-ot/src/main/java/datadog/opentracing/OTScopeManager.java index 0ca67a260a1..a620838b4e6 100644 --- a/dd-trace-ot/src/main/java/datadog/opentracing/OTScopeManager.java +++ b/dd-trace-ot/src/main/java/datadog/opentracing/OTScopeManager.java @@ -4,7 +4,6 @@ import datadog.trace.bootstrap.instrumentation.api.AgentScope; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.AgentTracer; -import datadog.trace.bootstrap.instrumentation.api.ScopeSource; import datadog.trace.context.TraceScope; import io.opentracing.Scope; import io.opentracing.ScopeManager; @@ -36,7 +35,7 @@ public Scope activate(final Span span, final boolean finishSpanOnClose) { } final AgentSpan agentSpan = converter.toAgentSpan(span); - final AgentScope agentScope = tracer.activateSpan(agentSpan, ScopeSource.MANUAL); + final AgentScope agentScope = tracer.activateManualSpan(agentSpan); return converter.toScope(agentScope, finishSpanOnClose); } diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTracer.java b/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTracer.java index 7dfbc56d251..17ee75761f7 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTracer.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTracer.java @@ -86,11 +86,11 @@ public static AgentSpan startSpan( } public static AgentScope activateSpan(final AgentSpan span) { - return get().activateSpan(span, ScopeSource.INSTRUMENTATION, DEFAULT_ASYNC_PROPAGATING); + return get().activateSpan(span, DEFAULT_ASYNC_PROPAGATING); } public static AgentScope activateSpan(final AgentSpan span, final boolean isAsyncPropagating) { - return get().activateSpan(span, ScopeSource.INSTRUMENTATION, isAsyncPropagating); + return get().activateSpan(span, isAsyncPropagating); } /** @@ -338,9 +338,11 @@ AgentSpan startSpan( AgentSpanContext parent, long startTimeMicros); - AgentScope activateSpan(AgentSpan span, ScopeSource source); + /** Activate a span from inside auto-instrumentation. */ + AgentScope activateSpan(AgentSpan span, boolean isAsyncPropagating); - AgentScope activateSpan(AgentSpan span, ScopeSource source, boolean isAsyncPropagating); + /** Activate a span from outside auto-instrumentation, i.e. a manual or custom span. */ + AgentScope activateManualSpan(AgentSpan span); @Override AgentScope.Continuation captureActiveSpan(); @@ -478,13 +480,12 @@ public AgentSpan startSpan( } @Override - public AgentScope activateSpan(final AgentSpan span, final ScopeSource source) { + public AgentScope activateSpan(final AgentSpan span, final boolean isAsyncPropagating) { return NoopScope.INSTANCE; } @Override - public AgentScope activateSpan( - final AgentSpan span, final ScopeSource source, final boolean isAsyncPropagating) { + public AgentScope activateManualSpan(final AgentSpan span) { return NoopScope.INSTANCE; } From c1d16933b40f9dfe9a0d050cf61a47b5bf31ec73 Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Wed, 12 Mar 2025 15:54:39 +0000 Subject: [PATCH 28/98] Simplify activateSpan calls which use the default value for isAsyncPropagating (#8543) --- .../java/datadog/trace/civisibility/domain/TestImpl.java | 2 +- .../datadog/trace/civisibility/domain/TestSuiteImpl.java | 2 +- .../akka-concurrent/src/test/java/LinearTask.java | 2 +- .../instrumentation/akkahttp/DatadogWrapperHelper.java | 2 +- .../instrumentation/finatra/FinatraInstrumentation.java | 2 +- .../grizzly/GrizzlyHttpHandlerInstrumentation.java | 2 +- .../instrumentation/grizzlyhttp232/FilterAdvice.java | 2 +- .../instrumentation/grizzlyhttp232/GrizzlyDecorator.java | 2 +- .../ignite/v2/cache/IgniteCacheAsyncInstrumentation.java | 4 ++-- .../jakarta3/DefaultRequestContextInstrumentation.java | 2 +- .../jakarta3/JakartaRsAnnotationsInstrumentation.java | 2 +- .../instrumentation/jakarta3/RequestFilterHelper.java | 2 +- .../executor/recursive/RecursiveThreadPoolExecution.java | 2 +- .../RecursiveThreadPoolMixedSubmissionAndExecution.java | 2 +- .../executor/recursive/RecursiveThreadPoolSubmission.java | 2 +- .../src/test/java/forkjoin/LinearTask.java | 2 +- .../trace/instrumentation/httpclient/SendAsyncAdvice.java | 2 +- .../jaxrs1/JaxRsAnnotationsInstrumentation.java | 2 +- .../jaxrs2/DefaultRequestContextInstrumentation.java | 2 +- .../jaxrs2/JaxRsAnnotationsInstrumentation.java | 2 +- .../trace/instrumentation/jaxrs2/RequestFilterHelper.java | 2 +- .../instrumentation/jdbc/DataSourceInstrumentation.java | 2 +- .../trace/instrumentation/jetty11/JettyServerAdvice.java | 2 +- .../trace/instrumentation/jetty12/JettyServerAdvice.java | 2 +- .../jetty70/JettyServerInstrumentation.java | 2 +- .../jetty76/JettyServerInstrumentation.java | 2 +- .../jetty9/JettyServerInstrumentation.java | 2 +- .../trace/instrumentation/jetty10/HandleAdvice.java | 2 +- .../kafka_clients/KafkaProducerCallback.java | 2 +- .../kafka_clients38/KafkaProducerCallback.java | 2 +- .../liberty20/LibertyServerInstrumentation.java | 2 +- .../liberty23/LibertyServerInstrumentation.java | 2 +- .../netty38/client/HttpClientResponseTracingHandler.java | 4 ++-- .../netty38/server/HttpServerRequestTracingHandler.java | 4 ++-- .../netty40/client/HttpClientResponseTracingHandler.java | 6 +++--- .../netty40/server/HttpServerRequestTracingHandler.java | 4 ++-- .../netty41/client/HttpClientResponseTracingHandler.java | 6 +++--- .../netty41/server/HttpServerRequestTracingHandler.java | 4 ++-- .../opentelemetry/annotations/WithSpanAdvice.java | 2 +- .../instrumentation/pekkohttp/DatadogWrapperHelper.java | 2 +- .../datadog/trace/instrumentation/play23/PlayAdvice.java | 2 +- .../datadog/trace/instrumentation/play24/PlayAdvice.java | 2 +- .../datadog/trace/instrumentation/play26/PlayAdvice.java | 2 +- .../trace/instrumentation/ratpack/ActionWrapper.java | 2 +- .../trace/instrumentation/ratpack/BlockWrapper.java | 2 +- .../trace/instrumentation/ratpack/TracingHandler.java | 2 +- .../src/latestDepTest/groovy/ReactorCoreTest.groovy | 4 ++-- .../src/test/groovy/ReactorCoreTest.groovy | 4 ++-- .../trace/instrumentation/rxjava/TracedOnSubscribe.java | 2 +- .../trace/instrumentation/rxjava/TracedSubscriber.java | 8 ++++---- .../rxjava-2/src/test/groovy/RxJava2Test.groovy | 4 ++-- .../scala-concurrent/src/test/java/LinearTask.java | 2 +- .../trace/instrumentation/servlet2/Servlet2Advice.java | 2 +- .../trace/instrumentation/servlet3/Servlet3Advice.java | 2 +- .../dispatcher/RequestDispatcherInstrumentation.java | 2 +- .../servlet/filter/FilterInstrumentation.java | 2 +- .../servlet/http/HttpServletInstrumentation.java | 2 +- .../servlet/http/HttpServletResponseInstrumentation.java | 2 +- .../spray/SprayHttpServerRunSealedRouteAdvice.java | 2 +- .../instrumentation/springdata/RepositoryInterceptor.java | 2 +- .../springscheduling/SpannedMethodInvocation.java | 2 +- .../springscheduling/SpringSchedulingRunnableWrapper.java | 2 +- .../springwebflux/server/HandlerAdapterAdvice.java | 2 +- .../springweb/HandlerAdapterInstrumentation.java | 2 +- .../instrumentation/springweb6/ControllerAdvice.java | 2 +- .../tomcat/TomcatServerInstrumentation.java | 2 +- .../twilio/TwilioAsyncInstrumentation.java | 2 +- .../instrumentation/undertow/HandlerInstrumentation.java | 2 +- .../vertx_redis_client/RedisAPICallAdvice.java | 2 +- .../vertx_redis_client/RedisFutureSendAdvice.java | 2 +- .../vertx_redis_client/RedisSendAdvice.java | 2 +- .../vertx_sql_client_39/CursorReadAdvice.java | 2 +- .../vertx_3_4/server/RouteHandlerWrapper.java | 2 +- .../vertx_4_0/server/RouteHandlerWrapper.java | 2 +- .../datadog/trace/agent/test/utils/TraceUtils.groovy | 2 +- 75 files changed, 90 insertions(+), 90 deletions(-) diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/TestImpl.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/TestImpl.java index 3bb5054dee0..270c3c1c7ee 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/TestImpl.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/TestImpl.java @@ -116,7 +116,7 @@ public TestImpl( span = spanBuilder.start(); - activateSpan(span, true); + activateSpan(span); span.setSpanType(InternalSpanTypes.TEST); span.setTag(Tags.SPAN_KIND, Tags.SPAN_KIND_TEST); diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/TestSuiteImpl.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/TestSuiteImpl.java index 0ba81176691..65ee32ad17f 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/TestSuiteImpl.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/TestSuiteImpl.java @@ -130,7 +130,7 @@ public TestSuiteImpl( testDecorator.afterStart(span); if (!parallelized) { - activateSpan(span, true); + activateSpan(span); } metricCollector.add(CiVisibilityCountMetric.EVENT_CREATED, 1, instrumentation, EventType.SUITE); diff --git a/dd-java-agent/instrumentation/akka-concurrent/src/test/java/LinearTask.java b/dd-java-agent/instrumentation/akka-concurrent/src/test/java/LinearTask.java index 3f52dc3610d..a60302436db 100644 --- a/dd-java-agent/instrumentation/akka-concurrent/src/test/java/LinearTask.java +++ b/dd-java-agent/instrumentation/akka-concurrent/src/test/java/LinearTask.java @@ -32,7 +32,7 @@ protected Integer compute() { } else { int next = parent + 1; AgentSpan span = startSpan(Integer.toString(next)); - try (AgentScope scope = activateSpan(span, true)) { + try (AgentScope scope = activateSpan(span)) { LinearTask child = new LinearTask(next, depth); return child.fork().join(); } finally { diff --git a/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogWrapperHelper.java b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogWrapperHelper.java index 5741b8dd945..a339eff7542 100644 --- a/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogWrapperHelper.java +++ b/dd-java-agent/instrumentation/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/DatadogWrapperHelper.java @@ -16,7 +16,7 @@ public static AgentScope createSpan(final HttpRequest request) { DECORATE.afterStart(span); DECORATE.onRequest(span, request, request, extractedContext); - return activateSpan(span, true); + return activateSpan(span); } public static void finishSpan(final AgentSpan span, final HttpResponse response) { diff --git a/dd-java-agent/instrumentation/finatra-2.9/src/main/java/datadog/trace/instrumentation/finatra/FinatraInstrumentation.java b/dd-java-agent/instrumentation/finatra-2.9/src/main/java/datadog/trace/instrumentation/finatra/FinatraInstrumentation.java index 040423b6183..a534b6d3c6d 100644 --- a/dd-java-agent/instrumentation/finatra-2.9/src/main/java/datadog/trace/instrumentation/finatra/FinatraInstrumentation.java +++ b/dd-java-agent/instrumentation/finatra-2.9/src/main/java/datadog/trace/instrumentation/finatra/FinatraInstrumentation.java @@ -76,7 +76,7 @@ public static AgentScope nameSpan( DECORATE.afterStart(span); span.setResourceName(DECORATE.className(clazz)); - return activateSpan(span, true); + return activateSpan(span); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) diff --git a/dd-java-agent/instrumentation/grizzly-2/src/main/java/datadog/trace/instrumentation/grizzly/GrizzlyHttpHandlerInstrumentation.java b/dd-java-agent/instrumentation/grizzly-2/src/main/java/datadog/trace/instrumentation/grizzly/GrizzlyHttpHandlerInstrumentation.java index fa38d172261..f556f9bf920 100644 --- a/dd-java-agent/instrumentation/grizzly-2/src/main/java/datadog/trace/instrumentation/grizzly/GrizzlyHttpHandlerInstrumentation.java +++ b/dd-java-agent/instrumentation/grizzly-2/src/main/java/datadog/trace/instrumentation/grizzly/GrizzlyHttpHandlerInstrumentation.java @@ -78,7 +78,7 @@ public static class HandleAdvice { DECORATE.afterStart(span); DECORATE.onRequest(span, request, request, parentContext); - scope = activateSpan(span, true); + scope = activateSpan(span); request.setAttribute(DD_SPAN_ATTRIBUTE, span); request.setAttribute(CorrelationIdentifier.getTraceIdKey(), GlobalTracer.get().getTraceId()); diff --git a/dd-java-agent/instrumentation/grizzly-http-2.3.20/src/main/java/datadog/trace/instrumentation/grizzlyhttp232/FilterAdvice.java b/dd-java-agent/instrumentation/grizzly-http-2.3.20/src/main/java/datadog/trace/instrumentation/grizzlyhttp232/FilterAdvice.java index 147439794db..d7a20c33e99 100644 --- a/dd-java-agent/instrumentation/grizzly-http-2.3.20/src/main/java/datadog/trace/instrumentation/grizzlyhttp232/FilterAdvice.java +++ b/dd-java-agent/instrumentation/grizzly-http-2.3.20/src/main/java/datadog/trace/instrumentation/grizzlyhttp232/FilterAdvice.java @@ -17,7 +17,7 @@ public static AgentScope onEnter(@Advice.Argument(0) final FilterChainContext ct if (span == null || activeSpan() != null) { return null; } - return activateSpan((AgentSpan) span, true); + return activateSpan((AgentSpan) span); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) diff --git a/dd-java-agent/instrumentation/grizzly-http-2.3.20/src/main/java/datadog/trace/instrumentation/grizzlyhttp232/GrizzlyDecorator.java b/dd-java-agent/instrumentation/grizzly-http-2.3.20/src/main/java/datadog/trace/instrumentation/grizzlyhttp232/GrizzlyDecorator.java index 4b4e4f3addd..1f8029a0940 100644 --- a/dd-java-agent/instrumentation/grizzly-http-2.3.20/src/main/java/datadog/trace/instrumentation/grizzlyhttp232/GrizzlyDecorator.java +++ b/dd-java-agent/instrumentation/grizzly-http-2.3.20/src/main/java/datadog/trace/instrumentation/grizzlyhttp232/GrizzlyDecorator.java @@ -116,7 +116,7 @@ public static NextAction onHttpCodecFilterExit( HttpResponsePacket httpResponse = httpRequest.getResponse(); AgentSpanContext.Extracted context = DECORATE.extract(httpRequest); AgentSpan span = DECORATE.startSpan(httpRequest, context); - AgentScope scope = activateSpan(span, true); + AgentScope scope = activateSpan(span); DECORATE.afterStart(span); ctx.getAttributes().setAttribute(DD_SPAN_ATTRIBUTE, span); ctx.getAttributes().setAttribute(DD_RESPONSE_ATTRIBUTE, httpResponse); diff --git a/dd-java-agent/instrumentation/ignite-2.0/src/main/java/datadog/trace/instrumentation/ignite/v2/cache/IgniteCacheAsyncInstrumentation.java b/dd-java-agent/instrumentation/ignite-2.0/src/main/java/datadog/trace/instrumentation/ignite/v2/cache/IgniteCacheAsyncInstrumentation.java index 4f2de9b112d..d207903c78f 100644 --- a/dd-java-agent/instrumentation/ignite-2.0/src/main/java/datadog/trace/instrumentation/ignite/v2/cache/IgniteCacheAsyncInstrumentation.java +++ b/dd-java-agent/instrumentation/ignite-2.0/src/main/java/datadog/trace/instrumentation/ignite/v2/cache/IgniteCacheAsyncInstrumentation.java @@ -93,7 +93,7 @@ public static AgentScope onEnter( // Enable async propagation, so the newly spawned task will be associated back with this // original trace. - return activateSpan(span, true); + return activateSpan(span); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) @@ -149,7 +149,7 @@ public static AgentScope onEnter( // Enable async propagation, so the newly spawned task will be associated back with this // original trace. - return activateSpan(span, true); + return activateSpan(span); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) diff --git a/dd-java-agent/instrumentation/jakarta-rs-annotations-3/src/main/java/datadog/trace/instrumentation/jakarta3/DefaultRequestContextInstrumentation.java b/dd-java-agent/instrumentation/jakarta-rs-annotations-3/src/main/java/datadog/trace/instrumentation/jakarta3/DefaultRequestContextInstrumentation.java index 69fa219a1e4..0d1159248f7 100644 --- a/dd-java-agent/instrumentation/jakarta-rs-annotations-3/src/main/java/datadog/trace/instrumentation/jakarta3/DefaultRequestContextInstrumentation.java +++ b/dd-java-agent/instrumentation/jakarta-rs-annotations-3/src/main/java/datadog/trace/instrumentation/jakarta3/DefaultRequestContextInstrumentation.java @@ -47,7 +47,7 @@ public static AgentScope createGenericSpan(@Advice.This final ContainerRequestCo // can only be aborted inside the filter method } - final AgentScope scope = activateSpan(span, true); + final AgentScope scope = activateSpan(span); DECORATE.afterStart(span); DECORATE.onJakartaRsSpan(span, parent, filterClass, method); diff --git a/dd-java-agent/instrumentation/jakarta-rs-annotations-3/src/main/java/datadog/trace/instrumentation/jakarta3/JakartaRsAnnotationsInstrumentation.java b/dd-java-agent/instrumentation/jakarta-rs-annotations-3/src/main/java/datadog/trace/instrumentation/jakarta3/JakartaRsAnnotationsInstrumentation.java index 1ea184ede74..5d37eb87197 100644 --- a/dd-java-agent/instrumentation/jakarta-rs-annotations-3/src/main/java/datadog/trace/instrumentation/jakarta3/JakartaRsAnnotationsInstrumentation.java +++ b/dd-java-agent/instrumentation/jakarta-rs-annotations-3/src/main/java/datadog/trace/instrumentation/jakarta3/JakartaRsAnnotationsInstrumentation.java @@ -123,7 +123,7 @@ public static AgentScope nameSpan( DECORATE.onJakartaRsSpan(span, parent, target.getClass(), method); DECORATE.afterStart(span); - final AgentScope scope = activateSpan(span, true); + final AgentScope scope = activateSpan(span); if (contextStore != null && asyncResponse != null) { contextStore.put(asyncResponse, span); diff --git a/dd-java-agent/instrumentation/jakarta-rs-annotations-3/src/main/java/datadog/trace/instrumentation/jakarta3/RequestFilterHelper.java b/dd-java-agent/instrumentation/jakarta-rs-annotations-3/src/main/java/datadog/trace/instrumentation/jakarta3/RequestFilterHelper.java index 27486963cd7..e0c66184d92 100644 --- a/dd-java-agent/instrumentation/jakarta-rs-annotations-3/src/main/java/datadog/trace/instrumentation/jakarta3/RequestFilterHelper.java +++ b/dd-java-agent/instrumentation/jakarta-rs-annotations-3/src/main/java/datadog/trace/instrumentation/jakarta3/RequestFilterHelper.java @@ -28,7 +28,7 @@ public static AgentScope createOrUpdateAbortSpan( parent = activeSpan(); span = startSpan(JAKARTA_RS_REQUEST_ABORT); - final AgentScope scope = activateSpan(span, true); + final AgentScope scope = activateSpan(span); DECORATE.afterStart(span); DECORATE.onJakartaRsSpan(span, parent, resourceClass, method); diff --git a/dd-java-agent/instrumentation/java-concurrent/src/test/java/executor/recursive/RecursiveThreadPoolExecution.java b/dd-java-agent/instrumentation/java-concurrent/src/test/java/executor/recursive/RecursiveThreadPoolExecution.java index 1fe45976ae1..59ee9a8d4ec 100644 --- a/dd-java-agent/instrumentation/java-concurrent/src/test/java/executor/recursive/RecursiveThreadPoolExecution.java +++ b/dd-java-agent/instrumentation/java-concurrent/src/test/java/executor/recursive/RecursiveThreadPoolExecution.java @@ -26,7 +26,7 @@ public void run() { return; } AgentSpan span = startSpan(String.valueOf(depth)); - try (AgentScope scope = activateSpan(span, true)) { + try (AgentScope scope = activateSpan(span)) { executor.execute(new RecursiveThreadPoolExecution(executor, maxDepth, depth + 1)); } finally { span.finish(); diff --git a/dd-java-agent/instrumentation/java-concurrent/src/test/java/executor/recursive/RecursiveThreadPoolMixedSubmissionAndExecution.java b/dd-java-agent/instrumentation/java-concurrent/src/test/java/executor/recursive/RecursiveThreadPoolMixedSubmissionAndExecution.java index 0c7acae3da2..37478f03891 100644 --- a/dd-java-agent/instrumentation/java-concurrent/src/test/java/executor/recursive/RecursiveThreadPoolMixedSubmissionAndExecution.java +++ b/dd-java-agent/instrumentation/java-concurrent/src/test/java/executor/recursive/RecursiveThreadPoolMixedSubmissionAndExecution.java @@ -27,7 +27,7 @@ public void run() { return; } AgentSpan span = startSpan(String.valueOf(depth)); - try (AgentScope scope = activateSpan(span, true)) { + try (AgentScope scope = activateSpan(span)) { if (depth % 2 == 0) { executor.submit( new RecursiveThreadPoolMixedSubmissionAndExecution(executor, maxDepth, depth + 1)); diff --git a/dd-java-agent/instrumentation/java-concurrent/src/test/java/executor/recursive/RecursiveThreadPoolSubmission.java b/dd-java-agent/instrumentation/java-concurrent/src/test/java/executor/recursive/RecursiveThreadPoolSubmission.java index 33904ba2e38..8cbd05924fd 100644 --- a/dd-java-agent/instrumentation/java-concurrent/src/test/java/executor/recursive/RecursiveThreadPoolSubmission.java +++ b/dd-java-agent/instrumentation/java-concurrent/src/test/java/executor/recursive/RecursiveThreadPoolSubmission.java @@ -26,7 +26,7 @@ public void run() { return; } AgentSpan span = startSpan(String.valueOf(depth)); - try (AgentScope scope = activateSpan(span, true)) { + try (AgentScope scope = activateSpan(span)) { executor.submit(new RecursiveThreadPoolSubmission(executor, maxDepth, depth + 1)); } finally { span.finish(); diff --git a/dd-java-agent/instrumentation/java-concurrent/src/test/java/forkjoin/LinearTask.java b/dd-java-agent/instrumentation/java-concurrent/src/test/java/forkjoin/LinearTask.java index 0697ee5ba48..c54fb9db9b7 100644 --- a/dd-java-agent/instrumentation/java-concurrent/src/test/java/forkjoin/LinearTask.java +++ b/dd-java-agent/instrumentation/java-concurrent/src/test/java/forkjoin/LinearTask.java @@ -34,7 +34,7 @@ protected Integer compute() { } else { int next = parent + 1; AgentSpan span = startSpan(Integer.toString(next)); - try (AgentScope scope = activateSpan(span, true)) { + try (AgentScope scope = activateSpan(span)) { LinearTask child = new LinearTask(next, depth); return child.fork().join(); } finally { diff --git a/dd-java-agent/instrumentation/java-http-client/src/main/java11/datadog/trace/instrumentation/httpclient/SendAsyncAdvice.java b/dd-java-agent/instrumentation/java-http-client/src/main/java11/datadog/trace/instrumentation/httpclient/SendAsyncAdvice.java index e3fe04d665c..00eb1adad8a 100644 --- a/dd-java-agent/instrumentation/java-http-client/src/main/java11/datadog/trace/instrumentation/httpclient/SendAsyncAdvice.java +++ b/dd-java-agent/instrumentation/java-http-client/src/main/java11/datadog/trace/instrumentation/httpclient/SendAsyncAdvice.java @@ -31,7 +31,7 @@ public static AgentScope methodEnter( return null; } final AgentSpan span = AgentTracer.startSpan(JavaNetClientDecorator.OPERATION_NAME); - final AgentScope scope = activateSpan(span, true); + final AgentScope scope = activateSpan(span); if (bodyHandler != null) { bodyHandler = new BodyHandlerWrapper<>(bodyHandler, captureSpan(span)); } diff --git a/dd-java-agent/instrumentation/jax-rs-annotations-1/src/main/java/datadog/trace/instrumentation/jaxrs1/JaxRsAnnotationsInstrumentation.java b/dd-java-agent/instrumentation/jax-rs-annotations-1/src/main/java/datadog/trace/instrumentation/jaxrs1/JaxRsAnnotationsInstrumentation.java index 3c1b22631d3..709c209bc48 100644 --- a/dd-java-agent/instrumentation/jax-rs-annotations-1/src/main/java/datadog/trace/instrumentation/jaxrs1/JaxRsAnnotationsInstrumentation.java +++ b/dd-java-agent/instrumentation/jax-rs-annotations-1/src/main/java/datadog/trace/instrumentation/jaxrs1/JaxRsAnnotationsInstrumentation.java @@ -100,7 +100,7 @@ public static AgentScope nameSpan( DECORATE.onJaxRsSpan(span, parent, target.getClass(), method); DECORATE.afterStart(span); - return activateSpan(span, true); + return activateSpan(span); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) diff --git a/dd-java-agent/instrumentation/jax-rs-annotations-2/src/main/java/datadog/trace/instrumentation/jaxrs2/DefaultRequestContextInstrumentation.java b/dd-java-agent/instrumentation/jax-rs-annotations-2/src/main/java/datadog/trace/instrumentation/jaxrs2/DefaultRequestContextInstrumentation.java index 4354cef7baa..87f695b6406 100644 --- a/dd-java-agent/instrumentation/jax-rs-annotations-2/src/main/java/datadog/trace/instrumentation/jaxrs2/DefaultRequestContextInstrumentation.java +++ b/dd-java-agent/instrumentation/jax-rs-annotations-2/src/main/java/datadog/trace/instrumentation/jaxrs2/DefaultRequestContextInstrumentation.java @@ -47,7 +47,7 @@ public static AgentScope createGenericSpan(@Advice.This final ContainerRequestCo // can only be aborted inside the filter method } - final AgentScope scope = activateSpan(span, true); + final AgentScope scope = activateSpan(span); DECORATE.afterStart(span); DECORATE.onJaxRsSpan(span, parent, filterClass, method); diff --git a/dd-java-agent/instrumentation/jax-rs-annotations-2/src/main/java/datadog/trace/instrumentation/jaxrs2/JaxRsAnnotationsInstrumentation.java b/dd-java-agent/instrumentation/jax-rs-annotations-2/src/main/java/datadog/trace/instrumentation/jaxrs2/JaxRsAnnotationsInstrumentation.java index b425776c73c..12ec03be4ab 100644 --- a/dd-java-agent/instrumentation/jax-rs-annotations-2/src/main/java/datadog/trace/instrumentation/jaxrs2/JaxRsAnnotationsInstrumentation.java +++ b/dd-java-agent/instrumentation/jax-rs-annotations-2/src/main/java/datadog/trace/instrumentation/jaxrs2/JaxRsAnnotationsInstrumentation.java @@ -131,7 +131,7 @@ public static AgentScope nameSpan( DECORATE.onJaxRsSpan(span, parent, target.getClass(), method); DECORATE.afterStart(span); - final AgentScope scope = activateSpan(span, true); + final AgentScope scope = activateSpan(span); if (contextStore != null && asyncResponse != null) { contextStore.put(asyncResponse, span); diff --git a/dd-java-agent/instrumentation/jax-rs-annotations-2/src/main/java/datadog/trace/instrumentation/jaxrs2/RequestFilterHelper.java b/dd-java-agent/instrumentation/jax-rs-annotations-2/src/main/java/datadog/trace/instrumentation/jaxrs2/RequestFilterHelper.java index d452eb7e741..fd19657b90b 100644 --- a/dd-java-agent/instrumentation/jax-rs-annotations-2/src/main/java/datadog/trace/instrumentation/jaxrs2/RequestFilterHelper.java +++ b/dd-java-agent/instrumentation/jax-rs-annotations-2/src/main/java/datadog/trace/instrumentation/jaxrs2/RequestFilterHelper.java @@ -27,7 +27,7 @@ public static AgentScope createOrUpdateAbortSpan( parent = activeSpan(); span = startSpan(JAX_RS_REQUEST_ABORT); - final AgentScope scope = activateSpan(span, true); + final AgentScope scope = activateSpan(span); DECORATE.afterStart(span); DECORATE.onJaxRsSpan(span, parent, resourceClass, method); diff --git a/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/DataSourceInstrumentation.java b/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/DataSourceInstrumentation.java index 1ce5bc20c40..69f5f92e532 100644 --- a/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/DataSourceInstrumentation.java +++ b/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/DataSourceInstrumentation.java @@ -69,7 +69,7 @@ public static AgentScope start(@Advice.This final DataSource ds) { span.setResourceName(DECORATE.spanNameForMethod(ds.getClass(), "getConnection")); - return activateSpan(span, true); + return activateSpan(span); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) diff --git a/dd-java-agent/instrumentation/jetty-11/src/main/java11/datadog/trace/instrumentation/jetty11/JettyServerAdvice.java b/dd-java-agent/instrumentation/jetty-11/src/main/java11/datadog/trace/instrumentation/jetty11/JettyServerAdvice.java index 17bd8826594..61c4e9be271 100644 --- a/dd-java-agent/instrumentation/jetty-11/src/main/java11/datadog/trace/instrumentation/jetty11/JettyServerAdvice.java +++ b/dd-java-agent/instrumentation/jetty-11/src/main/java11/datadog/trace/instrumentation/jetty11/JettyServerAdvice.java @@ -28,7 +28,7 @@ public static AgentScope onEnter( final AgentSpanContext.Extracted extractedContext = DECORATE.extract(req); span = DECORATE.startSpan(req, extractedContext); - final AgentScope scope = activateSpan(span, true); + final AgentScope scope = activateSpan(span); span.setMeasured(true); DECORATE.afterStart(span); DECORATE.onRequest(span, req, req, extractedContext); diff --git a/dd-java-agent/instrumentation/jetty-12/src/main/java17/datadog/trace/instrumentation/jetty12/JettyServerAdvice.java b/dd-java-agent/instrumentation/jetty-12/src/main/java17/datadog/trace/instrumentation/jetty12/JettyServerAdvice.java index 86145b59ce9..11b31cdffca 100644 --- a/dd-java-agent/instrumentation/jetty-12/src/main/java17/datadog/trace/instrumentation/jetty12/JettyServerAdvice.java +++ b/dd-java-agent/instrumentation/jetty-12/src/main/java17/datadog/trace/instrumentation/jetty12/JettyServerAdvice.java @@ -30,7 +30,7 @@ public static void onExit( final AgentSpanContext.Extracted extractedContext = JettyDecorator.DECORATE.extract(req); final AgentSpan span = JettyDecorator.DECORATE.startSpan(req, extractedContext); - try (final AgentScope scope = activateSpan(span, true)) { + try (final AgentScope scope = activateSpan(span)) { span.setMeasured(true); JettyDecorator.DECORATE.afterStart(span); JettyDecorator.DECORATE.onRequest(span, req, req, extractedContext); diff --git a/dd-java-agent/instrumentation/jetty-7.0/src/main/java/datadog/trace/instrumentation/jetty70/JettyServerInstrumentation.java b/dd-java-agent/instrumentation/jetty-7.0/src/main/java/datadog/trace/instrumentation/jetty70/JettyServerInstrumentation.java index 1439aa10912..e8a9e449963 100644 --- a/dd-java-agent/instrumentation/jetty-7.0/src/main/java/datadog/trace/instrumentation/jetty70/JettyServerInstrumentation.java +++ b/dd-java-agent/instrumentation/jetty-7.0/src/main/java/datadog/trace/instrumentation/jetty70/JettyServerInstrumentation.java @@ -158,7 +158,7 @@ public static AgentScope onEnter( final AgentSpanContext.Extracted extractedContext = DECORATE.extract(req); span = DECORATE.startSpan(req, extractedContext); - final AgentScope scope = activateSpan(span, true); + final AgentScope scope = activateSpan(span); DECORATE.afterStart(span); DECORATE.onRequest(span, req, req, extractedContext); diff --git a/dd-java-agent/instrumentation/jetty-7.6/src/main/java/datadog/trace/instrumentation/jetty76/JettyServerInstrumentation.java b/dd-java-agent/instrumentation/jetty-7.6/src/main/java/datadog/trace/instrumentation/jetty76/JettyServerInstrumentation.java index 00daf86582e..81225c7c820 100644 --- a/dd-java-agent/instrumentation/jetty-7.6/src/main/java/datadog/trace/instrumentation/jetty76/JettyServerInstrumentation.java +++ b/dd-java-agent/instrumentation/jetty-7.6/src/main/java/datadog/trace/instrumentation/jetty76/JettyServerInstrumentation.java @@ -159,7 +159,7 @@ public static AgentScope onEnter( final AgentSpanContext.Extracted extractedContext = DECORATE.extract(req); span = DECORATE.startSpan(req, extractedContext); - final AgentScope scope = activateSpan(span, true); + final AgentScope scope = activateSpan(span); DECORATE.afterStart(span); DECORATE.onRequest(span, req, req, extractedContext); diff --git a/dd-java-agent/instrumentation/jetty-9/src/main/java/datadog/trace/instrumentation/jetty9/JettyServerInstrumentation.java b/dd-java-agent/instrumentation/jetty-9/src/main/java/datadog/trace/instrumentation/jetty9/JettyServerInstrumentation.java index 8890769c5e2..7aaea42fc4d 100644 --- a/dd-java-agent/instrumentation/jetty-9/src/main/java/datadog/trace/instrumentation/jetty9/JettyServerInstrumentation.java +++ b/dd-java-agent/instrumentation/jetty-9/src/main/java/datadog/trace/instrumentation/jetty9/JettyServerInstrumentation.java @@ -173,7 +173,7 @@ public static AgentScope onEnter( final AgentSpanContext.Extracted extractedContext = DECORATE.extract(req); span = DECORATE.startSpan(req, extractedContext); - final AgentScope scope = activateSpan(span, true); + final AgentScope scope = activateSpan(span); DECORATE.afterStart(span); DECORATE.onRequest(span, req, req, extractedContext); diff --git a/dd-java-agent/instrumentation/jetty-9/src/main/java_jetty10/datadog/trace/instrumentation/jetty10/HandleAdvice.java b/dd-java-agent/instrumentation/jetty-9/src/main/java_jetty10/datadog/trace/instrumentation/jetty10/HandleAdvice.java index fb55788e974..25459847c0d 100644 --- a/dd-java-agent/instrumentation/jetty-9/src/main/java_jetty10/datadog/trace/instrumentation/jetty10/HandleAdvice.java +++ b/dd-java-agent/instrumentation/jetty-9/src/main/java_jetty10/datadog/trace/instrumentation/jetty10/HandleAdvice.java @@ -30,7 +30,7 @@ public static AgentScope onEnter( DECORATE.afterStart(span); DECORATE.onRequest(span, req, req, extractedContext); - final AgentScope scope = activateSpan(span, true); + final AgentScope scope = activateSpan(span); req.setAttribute(DD_SPAN_ATTRIBUTE, span); req.setAttribute(CorrelationIdentifier.getTraceIdKey(), GlobalTracer.get().getTraceId()); req.setAttribute(CorrelationIdentifier.getSpanIdKey(), GlobalTracer.get().getSpanId()); diff --git a/dd-java-agent/instrumentation/kafka-clients-0.11/src/main/java/datadog/trace/instrumentation/kafka_clients/KafkaProducerCallback.java b/dd-java-agent/instrumentation/kafka-clients-0.11/src/main/java/datadog/trace/instrumentation/kafka_clients/KafkaProducerCallback.java index 623b4639faa..d1aa1cd9ec1 100644 --- a/dd-java-agent/instrumentation/kafka-clients-0.11/src/main/java/datadog/trace/instrumentation/kafka_clients/KafkaProducerCallback.java +++ b/dd-java-agent/instrumentation/kafka-clients-0.11/src/main/java/datadog/trace/instrumentation/kafka_clients/KafkaProducerCallback.java @@ -39,7 +39,7 @@ public void onCompletion(final RecordMetadata metadata, final Exception exceptio span.finish(); if (callback != null) { if (parent != null) { - try (final AgentScope scope = activateSpan(parent, true)) { + try (final AgentScope scope = activateSpan(parent)) { callback.onCompletion(metadata, exception); } } else { diff --git a/dd-java-agent/instrumentation/kafka-clients-3.8/src/main/java17/datadog/trace/instrumentation/kafka_clients38/KafkaProducerCallback.java b/dd-java-agent/instrumentation/kafka-clients-3.8/src/main/java17/datadog/trace/instrumentation/kafka_clients38/KafkaProducerCallback.java index 9b8edfbebfd..c6252206ab2 100644 --- a/dd-java-agent/instrumentation/kafka-clients-3.8/src/main/java17/datadog/trace/instrumentation/kafka_clients38/KafkaProducerCallback.java +++ b/dd-java-agent/instrumentation/kafka-clients-3.8/src/main/java17/datadog/trace/instrumentation/kafka_clients38/KafkaProducerCallback.java @@ -38,7 +38,7 @@ public void onCompletion(final RecordMetadata metadata, final Exception exceptio span.finish(); if (callback != null) { if (parent != null) { - try (final AgentScope scope = activateSpan(parent, true)) { + try (final AgentScope scope = activateSpan(parent)) { callback.onCompletion(metadata, exception); } } else { diff --git a/dd-java-agent/instrumentation/liberty-20/src/main/java/datadog/trace/instrumentation/liberty20/LibertyServerInstrumentation.java b/dd-java-agent/instrumentation/liberty-20/src/main/java/datadog/trace/instrumentation/liberty20/LibertyServerInstrumentation.java index c6fdef889ab..1a4769710b3 100644 --- a/dd-java-agent/instrumentation/liberty-20/src/main/java/datadog/trace/instrumentation/liberty20/LibertyServerInstrumentation.java +++ b/dd-java-agent/instrumentation/liberty-20/src/main/java/datadog/trace/instrumentation/liberty20/LibertyServerInstrumentation.java @@ -108,7 +108,7 @@ public static class HandleRequestAdvice { final AgentSpanContext.Extracted extractedContext = DECORATE.extract(request); request.setAttribute(DD_EXTRACTED_CONTEXT_ATTRIBUTE, extractedContext); final AgentSpan span = DECORATE.startSpan(request, extractedContext); - scope = activateSpan(span, true); + scope = activateSpan(span); if (Config.get().isJeeSplitByDeployment()) { final IWebAppDispatcherContext dispatcherContext = request.getWebAppDispatcherContext(); if (dispatcherContext != null) { diff --git a/dd-java-agent/instrumentation/liberty-23/src/main/java/datadog/trace/instrumentation/liberty23/LibertyServerInstrumentation.java b/dd-java-agent/instrumentation/liberty-23/src/main/java/datadog/trace/instrumentation/liberty23/LibertyServerInstrumentation.java index bc101255856..30c8d7980cc 100644 --- a/dd-java-agent/instrumentation/liberty-23/src/main/java/datadog/trace/instrumentation/liberty23/LibertyServerInstrumentation.java +++ b/dd-java-agent/instrumentation/liberty-23/src/main/java/datadog/trace/instrumentation/liberty23/LibertyServerInstrumentation.java @@ -110,7 +110,7 @@ public static class HandleRequestAdvice { final AgentSpanContext.Extracted extractedContext = DECORATE.extract(request); request.setAttribute(DD_EXTRACTED_CONTEXT_ATTRIBUTE, extractedContext); final AgentSpan span = DECORATE.startSpan(request, extractedContext); - scope = activateSpan(span, true); + scope = activateSpan(span); if (Config.get().isJeeSplitByDeployment()) { final IWebAppDispatcherContext dispatcherContext = request.getWebAppDispatcherContext(); if (dispatcherContext != null) { diff --git a/dd-java-agent/instrumentation/netty-3.8/src/main/java/datadog/trace/instrumentation/netty38/client/HttpClientResponseTracingHandler.java b/dd-java-agent/instrumentation/netty-3.8/src/main/java/datadog/trace/instrumentation/netty38/client/HttpClientResponseTracingHandler.java index 911a2665c02..abda3d05acf 100644 --- a/dd-java-agent/instrumentation/netty-3.8/src/main/java/datadog/trace/instrumentation/netty38/client/HttpClientResponseTracingHandler.java +++ b/dd-java-agent/instrumentation/netty-3.8/src/main/java/datadog/trace/instrumentation/netty38/client/HttpClientResponseTracingHandler.java @@ -48,7 +48,7 @@ public void messageReceived(final ChannelHandlerContext ctx, final MessageEvent } // We want the callback in the scope of the parent, not the client span - try (final AgentScope scope = activateSpan(parent, true)) { + try (final AgentScope scope = activateSpan(parent)) { ctx.sendUpstream(msg); } } @@ -76,7 +76,7 @@ public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws } // We want the callback in the scope of the parent, not the client span - try (final AgentScope scope = activateSpan(parent, true)) { + try (final AgentScope scope = activateSpan(parent)) { super.exceptionCaught(ctx, e); } } diff --git a/dd-java-agent/instrumentation/netty-3.8/src/main/java/datadog/trace/instrumentation/netty38/server/HttpServerRequestTracingHandler.java b/dd-java-agent/instrumentation/netty-3.8/src/main/java/datadog/trace/instrumentation/netty38/server/HttpServerRequestTracingHandler.java index 75f62379c21..20c685a581b 100644 --- a/dd-java-agent/instrumentation/netty-3.8/src/main/java/datadog/trace/instrumentation/netty38/server/HttpServerRequestTracingHandler.java +++ b/dd-java-agent/instrumentation/netty-3.8/src/main/java/datadog/trace/instrumentation/netty38/server/HttpServerRequestTracingHandler.java @@ -35,7 +35,7 @@ public void messageReceived(final ChannelHandlerContext ctx, final MessageEvent if (span == null) { ctx.sendUpstream(msg); // superclass does not throw } else { - try (final AgentScope scope = activateSpan(span, true)) { + try (final AgentScope scope = activateSpan(span)) { ctx.sendUpstream(msg); // superclass does not throw } } @@ -50,7 +50,7 @@ public void messageReceived(final ChannelHandlerContext ctx, final MessageEvent channelTraceContext.reset(); channelTraceContext.setRequestHeaders(headers); - try (final AgentScope scope = activateSpan(span, true)) { + try (final AgentScope scope = activateSpan(span)) { DECORATE.afterStart(span); DECORATE.onRequest(span, ctx.getChannel(), request, context); diff --git a/dd-java-agent/instrumentation/netty-4.0/src/main/java/datadog/trace/instrumentation/netty40/client/HttpClientResponseTracingHandler.java b/dd-java-agent/instrumentation/netty-4.0/src/main/java/datadog/trace/instrumentation/netty40/client/HttpClientResponseTracingHandler.java index dfe8f481f7e..b0cc383f5e1 100644 --- a/dd-java-agent/instrumentation/netty-4.0/src/main/java/datadog/trace/instrumentation/netty40/client/HttpClientResponseTracingHandler.java +++ b/dd-java-agent/instrumentation/netty-4.0/src/main/java/datadog/trace/instrumentation/netty40/client/HttpClientResponseTracingHandler.java @@ -37,7 +37,7 @@ public void channelRead(final ChannelHandlerContext ctx, final Object msg) { } // We want the callback in the scope of the parent, not the client span - try (final AgentScope scope = activateSpan(parent, true)) { + try (final AgentScope scope = activateSpan(parent)) { ctx.fireChannelRead(msg); } } @@ -58,7 +58,7 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws E } } // We want the callback in the scope of the parent, not the client span - try (final AgentScope scope = activateSpan(parent, true)) { + try (final AgentScope scope = activateSpan(parent)) { super.exceptionCaught(ctx, cause); } } @@ -76,7 +76,7 @@ public void channelInactive(ChannelHandlerContext ctx) throws Exception { } } // We want the callback in the scope of the parent, not the client span - try (final AgentScope scope = activateSpan(parent, true)) { + try (final AgentScope scope = activateSpan(parent)) { super.channelInactive(ctx); } } diff --git a/dd-java-agent/instrumentation/netty-4.0/src/main/java/datadog/trace/instrumentation/netty40/server/HttpServerRequestTracingHandler.java b/dd-java-agent/instrumentation/netty-4.0/src/main/java/datadog/trace/instrumentation/netty40/server/HttpServerRequestTracingHandler.java index bbf9fea7011..d5b0aabd49e 100644 --- a/dd-java-agent/instrumentation/netty-4.0/src/main/java/datadog/trace/instrumentation/netty40/server/HttpServerRequestTracingHandler.java +++ b/dd-java-agent/instrumentation/netty-4.0/src/main/java/datadog/trace/instrumentation/netty40/server/HttpServerRequestTracingHandler.java @@ -31,7 +31,7 @@ public void channelRead(final ChannelHandlerContext ctx, final Object msg) { if (span == null) { ctx.fireChannelRead(msg); // superclass does not throw } else { - try (final AgentScope scope = activateSpan(span, true)) { + try (final AgentScope scope = activateSpan(span)) { ctx.fireChannelRead(msg); // superclass does not throw } } @@ -43,7 +43,7 @@ public void channelRead(final ChannelHandlerContext ctx, final Object msg) { final AgentSpanContext.Extracted extractedContext = DECORATE.extract(headers); final AgentSpan span = DECORATE.startSpan(headers, extractedContext); - try (final AgentScope scope = activateSpan(span, true)) { + try (final AgentScope scope = activateSpan(span)) { DECORATE.afterStart(span); DECORATE.onRequest(span, channel, request, extractedContext); diff --git a/dd-java-agent/instrumentation/netty-4.1/src/main/java/datadog/trace/instrumentation/netty41/client/HttpClientResponseTracingHandler.java b/dd-java-agent/instrumentation/netty-4.1/src/main/java/datadog/trace/instrumentation/netty41/client/HttpClientResponseTracingHandler.java index a7d8e240085..408c3530e20 100644 --- a/dd-java-agent/instrumentation/netty-4.1/src/main/java/datadog/trace/instrumentation/netty41/client/HttpClientResponseTracingHandler.java +++ b/dd-java-agent/instrumentation/netty-4.1/src/main/java/datadog/trace/instrumentation/netty41/client/HttpClientResponseTracingHandler.java @@ -46,7 +46,7 @@ public void channelRead(final ChannelHandlerContext ctx, final Object msg) { } // We want the callback in the scope of the parent, not the client span - try (final AgentScope scope = activateSpan(parent, true)) { + try (final AgentScope scope = activateSpan(parent)) { ctx.fireChannelRead(msg); } } @@ -67,7 +67,7 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws E } } // We want the callback in the scope of the parent, not the client span - try (final AgentScope scope = activateSpan(parent, true)) { + try (final AgentScope scope = activateSpan(parent)) { super.exceptionCaught(ctx, cause); } } @@ -85,7 +85,7 @@ public void channelInactive(ChannelHandlerContext ctx) throws Exception { } } // We want the callback in the scope of the parent, not the client span - try (final AgentScope scope = activateSpan(parent, true)) { + try (final AgentScope scope = activateSpan(parent)) { super.channelInactive(ctx); } } diff --git a/dd-java-agent/instrumentation/netty-4.1/src/main/java/datadog/trace/instrumentation/netty41/server/HttpServerRequestTracingHandler.java b/dd-java-agent/instrumentation/netty-4.1/src/main/java/datadog/trace/instrumentation/netty41/server/HttpServerRequestTracingHandler.java index cca0c608b72..3fd4e640d44 100644 --- a/dd-java-agent/instrumentation/netty-4.1/src/main/java/datadog/trace/instrumentation/netty41/server/HttpServerRequestTracingHandler.java +++ b/dd-java-agent/instrumentation/netty-4.1/src/main/java/datadog/trace/instrumentation/netty41/server/HttpServerRequestTracingHandler.java @@ -30,7 +30,7 @@ public void channelRead(final ChannelHandlerContext ctx, final Object msg) { if (span == null) { ctx.fireChannelRead(msg); // superclass does not throw } else { - try (final AgentScope scope = activateSpan(span, true)) { + try (final AgentScope scope = activateSpan(span)) { ctx.fireChannelRead(msg); // superclass does not throw } } @@ -42,7 +42,7 @@ public void channelRead(final ChannelHandlerContext ctx, final Object msg) { final AgentSpanContext.Extracted extractedContext = DECORATE.extract(headers); final AgentSpan span = DECORATE.startSpan(headers, extractedContext); - try (final AgentScope scope = activateSpan(span, true)) { + try (final AgentScope scope = activateSpan(span)) { DECORATE.afterStart(span); DECORATE.onRequest(span, channel, request, extractedContext); diff --git a/dd-java-agent/instrumentation/opentelemetry/opentelemetry-annotations-1.20/src/main/java/datadog/trace/instrumentation/opentelemetry/annotations/WithSpanAdvice.java b/dd-java-agent/instrumentation/opentelemetry/opentelemetry-annotations-1.20/src/main/java/datadog/trace/instrumentation/opentelemetry/annotations/WithSpanAdvice.java index 02a444c7130..af46a8ff208 100644 --- a/dd-java-agent/instrumentation/opentelemetry/opentelemetry-annotations-1.20/src/main/java/datadog/trace/instrumentation/opentelemetry/annotations/WithSpanAdvice.java +++ b/dd-java-agent/instrumentation/opentelemetry/opentelemetry-annotations-1.20/src/main/java/datadog/trace/instrumentation/opentelemetry/annotations/WithSpanAdvice.java @@ -14,7 +14,7 @@ public class WithSpanAdvice { @Advice.OnMethodEnter(suppress = Throwable.class) public static AgentScope onEnter(@Advice.Origin final Method method) { AgentSpan span = DECORATE.startMethodSpan(method); - return activateSpan(span, true); + return activateSpan(span); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) diff --git a/dd-java-agent/instrumentation/pekko-http-1.0/src/main/java/datadog/trace/instrumentation/pekkohttp/DatadogWrapperHelper.java b/dd-java-agent/instrumentation/pekko-http-1.0/src/main/java/datadog/trace/instrumentation/pekkohttp/DatadogWrapperHelper.java index e4a159c6e7a..5c82e9bb020 100644 --- a/dd-java-agent/instrumentation/pekko-http-1.0/src/main/java/datadog/trace/instrumentation/pekkohttp/DatadogWrapperHelper.java +++ b/dd-java-agent/instrumentation/pekko-http-1.0/src/main/java/datadog/trace/instrumentation/pekkohttp/DatadogWrapperHelper.java @@ -16,7 +16,7 @@ public static AgentScope createSpan(final HttpRequest request) { DECORATE.afterStart(span); DECORATE.onRequest(span, request, request, extractedContext); - return activateSpan(span, true); + return activateSpan(span); } public static void finishSpan(final AgentSpan span, final HttpResponse response) { diff --git a/dd-java-agent/instrumentation/play-2.3/src/main/java/datadog/trace/instrumentation/play23/PlayAdvice.java b/dd-java-agent/instrumentation/play-2.3/src/main/java/datadog/trace/instrumentation/play23/PlayAdvice.java index 7aaebe110b1..f21f313ce19 100644 --- a/dd-java-agent/instrumentation/play-2.3/src/main/java/datadog/trace/instrumentation/play23/PlayAdvice.java +++ b/dd-java-agent/instrumentation/play-2.3/src/main/java/datadog/trace/instrumentation/play23/PlayAdvice.java @@ -32,7 +32,7 @@ public static AgentScope onEnter(@Advice.Argument(0) final Request req) { span.setMeasured(true); } - final AgentScope scope = activateSpan(span, true); + final AgentScope scope = activateSpan(span); DECORATE.afterStart(span); return scope; } diff --git a/dd-java-agent/instrumentation/play-2.4/src/main/java/datadog/trace/instrumentation/play24/PlayAdvice.java b/dd-java-agent/instrumentation/play-2.4/src/main/java/datadog/trace/instrumentation/play24/PlayAdvice.java index 452a4db65f6..60b55add14f 100644 --- a/dd-java-agent/instrumentation/play-2.4/src/main/java/datadog/trace/instrumentation/play24/PlayAdvice.java +++ b/dd-java-agent/instrumentation/play-2.4/src/main/java/datadog/trace/instrumentation/play24/PlayAdvice.java @@ -38,7 +38,7 @@ public static AgentScope onEnter(@Advice.Argument(value = 0, readOnly = false) R span.setMeasured(true); } - final AgentScope scope = activateSpan(span, true); + final AgentScope scope = activateSpan(span); DECORATE.afterStart(span); req = RequestHelper.withTag(req, "_dd_HasPlayRequestSpan", "true"); diff --git a/dd-java-agent/instrumentation/play-2.6/src/main/java/datadog/trace/instrumentation/play26/PlayAdvice.java b/dd-java-agent/instrumentation/play-2.6/src/main/java/datadog/trace/instrumentation/play26/PlayAdvice.java index a8e17088062..ecd5b903e19 100644 --- a/dd-java-agent/instrumentation/play-2.6/src/main/java/datadog/trace/instrumentation/play26/PlayAdvice.java +++ b/dd-java-agent/instrumentation/play-2.6/src/main/java/datadog/trace/instrumentation/play26/PlayAdvice.java @@ -38,7 +38,7 @@ public static AgentScope onEnter( // Do not extract the context. span = startSpan(PLAY_REQUEST); } - final AgentScope scope = activateSpan(span, true); + final AgentScope scope = activateSpan(span); span.setMeasured(true); DECORATE.afterStart(span); diff --git a/dd-java-agent/instrumentation/ratpack-1.5/src/main/java/datadog/trace/instrumentation/ratpack/ActionWrapper.java b/dd-java-agent/instrumentation/ratpack-1.5/src/main/java/datadog/trace/instrumentation/ratpack/ActionWrapper.java index 6710c8036f3..23ab189156f 100644 --- a/dd-java-agent/instrumentation/ratpack-1.5/src/main/java/datadog/trace/instrumentation/ratpack/ActionWrapper.java +++ b/dd-java-agent/instrumentation/ratpack-1.5/src/main/java/datadog/trace/instrumentation/ratpack/ActionWrapper.java @@ -22,7 +22,7 @@ private ActionWrapper(final Action delegate, final AgentSpan span) { @Override public void execute(final T t) throws Exception { - try (final AgentScope scope = activateSpan(span, true)) { + try (final AgentScope scope = activateSpan(span)) { delegate.execute(t); } } diff --git a/dd-java-agent/instrumentation/ratpack-1.5/src/main/java/datadog/trace/instrumentation/ratpack/BlockWrapper.java b/dd-java-agent/instrumentation/ratpack-1.5/src/main/java/datadog/trace/instrumentation/ratpack/BlockWrapper.java index 650d1c2cb4d..2dc9eb10690 100644 --- a/dd-java-agent/instrumentation/ratpack-1.5/src/main/java/datadog/trace/instrumentation/ratpack/BlockWrapper.java +++ b/dd-java-agent/instrumentation/ratpack-1.5/src/main/java/datadog/trace/instrumentation/ratpack/BlockWrapper.java @@ -23,7 +23,7 @@ private BlockWrapper(final Block delegate, final AgentSpan span) { @Override public void execute() throws Exception { - try (final AgentScope scope = activateSpan(span, true)) { + try (final AgentScope scope = activateSpan(span)) { delegate.execute(); } } diff --git a/dd-java-agent/instrumentation/ratpack-1.5/src/main/java/datadog/trace/instrumentation/ratpack/TracingHandler.java b/dd-java-agent/instrumentation/ratpack-1.5/src/main/java/datadog/trace/instrumentation/ratpack/TracingHandler.java index f4be50df0e3..898bf6b9230 100644 --- a/dd-java-agent/instrumentation/ratpack-1.5/src/main/java/datadog/trace/instrumentation/ratpack/TracingHandler.java +++ b/dd-java-agent/instrumentation/ratpack-1.5/src/main/java/datadog/trace/instrumentation/ratpack/TracingHandler.java @@ -42,7 +42,7 @@ public void handle(final Context ctx) { boolean setFinalizer = false; - try (final AgentScope scope = activateSpan(ratpackSpan, true)) { + try (final AgentScope scope = activateSpan(ratpackSpan)) { ctx.getResponse() .beforeSend( diff --git a/dd-java-agent/instrumentation/reactor-core-3.1/src/latestDepTest/groovy/ReactorCoreTest.groovy b/dd-java-agent/instrumentation/reactor-core-3.1/src/latestDepTest/groovy/ReactorCoreTest.groovy index 597b509d158..a235c07be60 100644 --- a/dd-java-agent/instrumentation/reactor-core-3.1/src/latestDepTest/groovy/ReactorCoreTest.groovy +++ b/dd-java-agent/instrumentation/reactor-core-3.1/src/latestDepTest/groovy/ReactorCoreTest.groovy @@ -483,7 +483,7 @@ class ReactorCoreTest extends AgentTestRunner { def assemblePublisherUnderTrace(def publisherSupplier) { def span = startSpan("publisher-parent") // After this activation, the "add two" operations below should be children of this span - def scope = activateSpan(span, true) + def scope = activateSpan(span) Publisher publisher = publisherSupplier() try { @@ -504,7 +504,7 @@ class ReactorCoreTest extends AgentTestRunner { @Trace(operationName = "trace-parent", resourceName = "trace-parent") def cancelUnderTrace(def publisherSupplier) { final AgentSpan span = startSpan("publisher-parent") - AgentScope scope = activateSpan(span, true) + AgentScope scope = activateSpan(span) def publisher = publisherSupplier() publisher.subscribe(new Subscriber() { diff --git a/dd-java-agent/instrumentation/reactor-core-3.1/src/test/groovy/ReactorCoreTest.groovy b/dd-java-agent/instrumentation/reactor-core-3.1/src/test/groovy/ReactorCoreTest.groovy index 09eb37da714..2c64e2eadcd 100644 --- a/dd-java-agent/instrumentation/reactor-core-3.1/src/test/groovy/ReactorCoreTest.groovy +++ b/dd-java-agent/instrumentation/reactor-core-3.1/src/test/groovy/ReactorCoreTest.groovy @@ -483,7 +483,7 @@ class ReactorCoreTest extends AgentTestRunner { def assemblePublisherUnderTrace(def publisherSupplier) { def span = startSpan("publisher-parent") // After this activation, the "add two" operations below should be children of this span - def scope = activateSpan(span, true) + def scope = activateSpan(span) Publisher publisher = publisherSupplier() try { @@ -504,7 +504,7 @@ class ReactorCoreTest extends AgentTestRunner { @Trace(operationName = "trace-parent", resourceName = "trace-parent") def cancelUnderTrace(def publisherSupplier) { final AgentSpan span = startSpan("publisher-parent") - AgentScope scope = activateSpan(span, true) + AgentScope scope = activateSpan(span) def publisher = publisherSupplier() publisher.subscribe(new Subscriber() { diff --git a/dd-java-agent/instrumentation/rxjava-1/src/main/java/datadog/trace/instrumentation/rxjava/TracedOnSubscribe.java b/dd-java-agent/instrumentation/rxjava-1/src/main/java/datadog/trace/instrumentation/rxjava/TracedOnSubscribe.java index d9b2a826717..f5e470c60f8 100644 --- a/dd-java-agent/instrumentation/rxjava-1/src/main/java/datadog/trace/instrumentation/rxjava/TracedOnSubscribe.java +++ b/dd-java-agent/instrumentation/rxjava-1/src/main/java/datadog/trace/instrumentation/rxjava/TracedOnSubscribe.java @@ -33,7 +33,7 @@ public void call(final Subscriber subscriber) { final AgentSpan span = startSpan(operationName, parent != null ? parent.context() : null); afterStart(span); - try (final AgentScope scope = activateSpan(span, true)) { + try (final AgentScope scope = activateSpan(span)) { delegate.call(new TracedSubscriber(span, subscriber, decorator)); } } diff --git a/dd-java-agent/instrumentation/rxjava-1/src/main/java/datadog/trace/instrumentation/rxjava/TracedSubscriber.java b/dd-java-agent/instrumentation/rxjava-1/src/main/java/datadog/trace/instrumentation/rxjava/TracedSubscriber.java index 15e16008fe1..c9eccecbc85 100644 --- a/dd-java-agent/instrumentation/rxjava-1/src/main/java/datadog/trace/instrumentation/rxjava/TracedSubscriber.java +++ b/dd-java-agent/instrumentation/rxjava-1/src/main/java/datadog/trace/instrumentation/rxjava/TracedSubscriber.java @@ -28,7 +28,7 @@ public TracedSubscriber( public void onStart() { final AgentSpan span = spanRef.get(); if (span != null) { - try (final AgentScope scope = activateSpan(span, true)) { + try (final AgentScope scope = activateSpan(span)) { delegate.onStart(); } } else { @@ -40,7 +40,7 @@ public void onStart() { public void onNext(final T value) { final AgentSpan span = spanRef.get(); if (span != null) { - try (final AgentScope scope = activateSpan(span, true)) { + try (final AgentScope scope = activateSpan(span)) { delegate.onNext(value); } catch (final Throwable e) { onError(e); @@ -55,7 +55,7 @@ public void onCompleted() { final AgentSpan span = spanRef.getAndSet(null); if (span != null) { boolean errored = false; - try (final AgentScope scope = activateSpan(span, true)) { + try (final AgentScope scope = activateSpan(span)) { delegate.onCompleted(); } catch (final Throwable e) { // Repopulate the spanRef for onError @@ -78,7 +78,7 @@ public void onCompleted() { public void onError(final Throwable e) { final AgentSpan span = spanRef.getAndSet(null); if (span != null) { - try (final AgentScope scope = activateSpan(span, true)) { + try (final AgentScope scope = activateSpan(span)) { decorator.onError(span, e); delegate.onError(e); } catch (final Throwable e2) { diff --git a/dd-java-agent/instrumentation/rxjava-2/src/test/groovy/RxJava2Test.groovy b/dd-java-agent/instrumentation/rxjava-2/src/test/groovy/RxJava2Test.groovy index 9b2f71fea4c..43b11a72644 100644 --- a/dd-java-agent/instrumentation/rxjava-2/src/test/groovy/RxJava2Test.groovy +++ b/dd-java-agent/instrumentation/rxjava-2/src/test/groovy/RxJava2Test.groovy @@ -384,7 +384,7 @@ class RxJava2Test extends AgentTestRunner { def assemblePublisherUnderTrace(def publisherSupplier) { def span = startSpan("publisher-parent") // After this activation, the "add two" operations below should be children of this span - def scope = activateSpan(span, true) + def scope = activateSpan(span) def publisher = publisherSupplier() try { @@ -405,7 +405,7 @@ class RxJava2Test extends AgentTestRunner { @Trace(operationName = "trace-parent", resourceName = "trace-parent") def cancelUnderTrace(def publisherSupplier) { final AgentSpan span = startSpan("publisher-parent") - AgentScope scope = activateSpan(span, true) + AgentScope scope = activateSpan(span) def publisher = publisherSupplier() if (publisher instanceof Maybe) { diff --git a/dd-java-agent/instrumentation/scala-concurrent/src/test/java/LinearTask.java b/dd-java-agent/instrumentation/scala-concurrent/src/test/java/LinearTask.java index 56401a21316..08a74a54fb9 100644 --- a/dd-java-agent/instrumentation/scala-concurrent/src/test/java/LinearTask.java +++ b/dd-java-agent/instrumentation/scala-concurrent/src/test/java/LinearTask.java @@ -32,7 +32,7 @@ protected Integer compute() { } else { int next = parent + 1; AgentSpan span = startSpan(Integer.toString(next)); - try (AgentScope scope = activateSpan(span, true)) { + try (AgentScope scope = activateSpan(span)) { LinearTask child = new LinearTask(next, depth); return child.fork().join(); } finally { diff --git a/dd-java-agent/instrumentation/servlet/request-2/src/main/java/datadog/trace/instrumentation/servlet2/Servlet2Advice.java b/dd-java-agent/instrumentation/servlet/request-2/src/main/java/datadog/trace/instrumentation/servlet2/Servlet2Advice.java index b5f565d198a..84d85e8447f 100644 --- a/dd-java-agent/instrumentation/servlet/request-2/src/main/java/datadog/trace/instrumentation/servlet2/Servlet2Advice.java +++ b/dd-java-agent/instrumentation/servlet/request-2/src/main/java/datadog/trace/instrumentation/servlet2/Servlet2Advice.java @@ -55,7 +55,7 @@ public static boolean onEnter( final AgentSpanContext.Extracted extractedContext = DECORATE.extract(httpServletRequest); final AgentSpan span = DECORATE.startSpan(httpServletRequest, extractedContext); - scope = activateSpan(span, true); + scope = activateSpan(span); DECORATE.afterStart(span); DECORATE.onRequest(span, httpServletRequest, httpServletRequest, extractedContext); diff --git a/dd-java-agent/instrumentation/servlet/request-3/src/main/java/datadog/trace/instrumentation/servlet3/Servlet3Advice.java b/dd-java-agent/instrumentation/servlet/request-3/src/main/java/datadog/trace/instrumentation/servlet3/Servlet3Advice.java index 0bf2807e9f8..00e57312bce 100644 --- a/dd-java-agent/instrumentation/servlet/request-3/src/main/java/datadog/trace/instrumentation/servlet3/Servlet3Advice.java +++ b/dd-java-agent/instrumentation/servlet/request-3/src/main/java/datadog/trace/instrumentation/servlet3/Servlet3Advice.java @@ -71,7 +71,7 @@ public static boolean onEnter( final AgentSpanContext.Extracted extractedContext = DECORATE.extract(httpServletRequest); final AgentSpan span = DECORATE.startSpan(httpServletRequest, extractedContext); - scope = activateSpan(span, true); + scope = activateSpan(span); DECORATE.afterStart(span); DECORATE.onRequest(span, httpServletRequest, httpServletRequest, extractedContext); diff --git a/dd-java-agent/instrumentation/servlet/src/main/java/datadog/trace/instrumentation/servlet/dispatcher/RequestDispatcherInstrumentation.java b/dd-java-agent/instrumentation/servlet/src/main/java/datadog/trace/instrumentation/servlet/dispatcher/RequestDispatcherInstrumentation.java index 159eb7bb0a0..d2e3df70436 100644 --- a/dd-java-agent/instrumentation/servlet/src/main/java/datadog/trace/instrumentation/servlet/dispatcher/RequestDispatcherInstrumentation.java +++ b/dd-java-agent/instrumentation/servlet/src/main/java/datadog/trace/instrumentation/servlet/dispatcher/RequestDispatcherInstrumentation.java @@ -129,7 +129,7 @@ public static AgentScope start( requestSpan = request.getAttribute(DD_SPAN_ATTRIBUTE); request.setAttribute(DD_SPAN_ATTRIBUTE, span); - return activateSpan(span, true); + return activateSpan(span); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) diff --git a/dd-java-agent/instrumentation/servlet/src/main/java/datadog/trace/instrumentation/servlet/filter/FilterInstrumentation.java b/dd-java-agent/instrumentation/servlet/src/main/java/datadog/trace/instrumentation/servlet/filter/FilterInstrumentation.java index 2d68b579169..0abe760a452 100644 --- a/dd-java-agent/instrumentation/servlet/src/main/java/datadog/trace/instrumentation/servlet/filter/FilterInstrumentation.java +++ b/dd-java-agent/instrumentation/servlet/src/main/java/datadog/trace/instrumentation/servlet/filter/FilterInstrumentation.java @@ -74,7 +74,7 @@ public static AgentScope start(@Advice.This final Filter filter) { // Here we use "this" instead of "the method target" to distinguish abstract filter instances. span.setResourceName(DECORATE.spanNameForMethod(filter.getClass(), "doFilter")); - return activateSpan(span, true); + return activateSpan(span); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) diff --git a/dd-java-agent/instrumentation/servlet/src/main/java/datadog/trace/instrumentation/servlet/http/HttpServletInstrumentation.java b/dd-java-agent/instrumentation/servlet/src/main/java/datadog/trace/instrumentation/servlet/http/HttpServletInstrumentation.java index 74e33a5be4b..ecd9654dadd 100644 --- a/dd-java-agent/instrumentation/servlet/src/main/java/datadog/trace/instrumentation/servlet/http/HttpServletInstrumentation.java +++ b/dd-java-agent/instrumentation/servlet/src/main/java/datadog/trace/instrumentation/servlet/http/HttpServletInstrumentation.java @@ -84,7 +84,7 @@ public static AgentScope start(@Advice.Origin final Method method) { // Here we use the Method instead of "this.class.name" to distinguish calls to "super". span.setResourceName(DECORATE.spanNameForMethod(method)); - return activateSpan(span, true); + return activateSpan(span); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) diff --git a/dd-java-agent/instrumentation/servlet/src/main/java/datadog/trace/instrumentation/servlet/http/HttpServletResponseInstrumentation.java b/dd-java-agent/instrumentation/servlet/src/main/java/datadog/trace/instrumentation/servlet/http/HttpServletResponseInstrumentation.java index 45e8b15c340..b5afc57e105 100644 --- a/dd-java-agent/instrumentation/servlet/src/main/java/datadog/trace/instrumentation/servlet/http/HttpServletResponseInstrumentation.java +++ b/dd-java-agent/instrumentation/servlet/src/main/java/datadog/trace/instrumentation/servlet/http/HttpServletResponseInstrumentation.java @@ -72,7 +72,7 @@ public static AgentScope start( span.setResourceName(DECORATE.spanNameForMethod(HttpServletResponse.class, method)); - return activateSpan(span, true); + return activateSpan(span); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) diff --git a/dd-java-agent/instrumentation/spray-1.3/src/main/scala/datadog/trace/instrumentation/spray/SprayHttpServerRunSealedRouteAdvice.java b/dd-java-agent/instrumentation/spray-1.3/src/main/scala/datadog/trace/instrumentation/spray/SprayHttpServerRunSealedRouteAdvice.java index 3352c9cabaa..53df15ffd76 100644 --- a/dd-java-agent/instrumentation/spray-1.3/src/main/scala/datadog/trace/instrumentation/spray/SprayHttpServerRunSealedRouteAdvice.java +++ b/dd-java-agent/instrumentation/spray-1.3/src/main/scala/datadog/trace/instrumentation/spray/SprayHttpServerRunSealedRouteAdvice.java @@ -27,7 +27,7 @@ public static AgentScope enter(@Advice.Argument(value = 1, readOnly = false) Req extractedContext = null; span = startSpan(DECORATE.spanName()); } - final AgentScope scope = activateSpan(span, true); + final AgentScope scope = activateSpan(span); DECORATE.afterStart(span); diff --git a/dd-java-agent/instrumentation/spring-data-1.8/src/main/java/datadog/trace/instrumentation/springdata/RepositoryInterceptor.java b/dd-java-agent/instrumentation/spring-data-1.8/src/main/java/datadog/trace/instrumentation/springdata/RepositoryInterceptor.java index 57fd1f4e505..c4224867615 100644 --- a/dd-java-agent/instrumentation/spring-data-1.8/src/main/java/datadog/trace/instrumentation/springdata/RepositoryInterceptor.java +++ b/dd-java-agent/instrumentation/spring-data-1.8/src/main/java/datadog/trace/instrumentation/springdata/RepositoryInterceptor.java @@ -35,7 +35,7 @@ public Object invoke(final MethodInvocation methodInvocation) throws Throwable { DECORATOR.afterStart(span); DECORATOR.onOperation(span, invokedMethod, repositoryInterface); - final AgentScope scope = activateSpan(span, true); + final AgentScope scope = activateSpan(span); Object result = null; try { diff --git a/dd-java-agent/instrumentation/spring-scheduling-3.1/src/main/java/datadog/trace/instrumentation/springscheduling/SpannedMethodInvocation.java b/dd-java-agent/instrumentation/spring-scheduling-3.1/src/main/java/datadog/trace/instrumentation/springscheduling/SpannedMethodInvocation.java index 920891e194e..0200eba5439 100644 --- a/dd-java-agent/instrumentation/spring-scheduling-3.1/src/main/java/datadog/trace/instrumentation/springscheduling/SpannedMethodInvocation.java +++ b/dd-java-agent/instrumentation/spring-scheduling-3.1/src/main/java/datadog/trace/instrumentation/springscheduling/SpannedMethodInvocation.java @@ -51,7 +51,7 @@ private Object invokeWithContinuation(CharSequence spanName) throws Throwable { private Object invokeWithSpan(CharSequence spanName) throws Throwable { AgentSpan span = startSpan(spanName); - try (AgentScope scope = activateSpan(span, true)) { + try (AgentScope scope = activateSpan(span)) { return delegate.proceed(); } finally { span.finish(); diff --git a/dd-java-agent/instrumentation/spring-scheduling-3.1/src/main/java/datadog/trace/instrumentation/springscheduling/SpringSchedulingRunnableWrapper.java b/dd-java-agent/instrumentation/spring-scheduling-3.1/src/main/java/datadog/trace/instrumentation/springscheduling/SpringSchedulingRunnableWrapper.java index 26f45708e15..1e5b2927e4d 100644 --- a/dd-java-agent/instrumentation/spring-scheduling-3.1/src/main/java/datadog/trace/instrumentation/springscheduling/SpringSchedulingRunnableWrapper.java +++ b/dd-java-agent/instrumentation/spring-scheduling-3.1/src/main/java/datadog/trace/instrumentation/springscheduling/SpringSchedulingRunnableWrapper.java @@ -58,7 +58,7 @@ public void run() { LEGACY_TRACING ? startSpan(SCHEDULED_CALL) : startSpan(SCHEDULED_CALL, null); DECORATE.afterStart(span); - try (final AgentScope scope = activateSpan(span, true)) { + try (final AgentScope scope = activateSpan(span)) { DECORATE.onRun(span, runnable); try { diff --git a/dd-java-agent/instrumentation/spring-webflux-5/src/main/java/datadog/trace/instrumentation/springwebflux/server/HandlerAdapterAdvice.java b/dd-java-agent/instrumentation/spring-webflux-5/src/main/java/datadog/trace/instrumentation/springwebflux/server/HandlerAdapterAdvice.java index da69a94ea14..ba7e3e2e446 100644 --- a/dd-java-agent/instrumentation/spring-webflux-5/src/main/java/datadog/trace/instrumentation/springwebflux/server/HandlerAdapterAdvice.java +++ b/dd-java-agent/instrumentation/spring-webflux-5/src/main/java/datadog/trace/instrumentation/springwebflux/server/HandlerAdapterAdvice.java @@ -44,7 +44,7 @@ public static AgentScope methodEnter( span.setSpanName(operationName); span.setTag("handler.type", handlerType); - scope = activateSpan(span, true); + scope = activateSpan(span); } final AgentSpan parentSpan = exchange.getAttribute(AdviceUtils.PARENT_SPAN_ATTRIBUTE); diff --git a/dd-java-agent/instrumentation/spring-webmvc-3.1/src/main/java/datadog/trace/instrumentation/springweb/HandlerAdapterInstrumentation.java b/dd-java-agent/instrumentation/spring-webmvc-3.1/src/main/java/datadog/trace/instrumentation/springweb/HandlerAdapterInstrumentation.java index c0a37adfabe..3722ce989d9 100644 --- a/dd-java-agent/instrumentation/spring-webmvc-3.1/src/main/java/datadog/trace/instrumentation/springweb/HandlerAdapterInstrumentation.java +++ b/dd-java-agent/instrumentation/spring-webmvc-3.1/src/main/java/datadog/trace/instrumentation/springweb/HandlerAdapterInstrumentation.java @@ -81,7 +81,7 @@ public static AgentScope nameResourceAndStartSpan( DECORATE.afterStart(span); DECORATE.onHandle(span, handler); - return activateSpan(span, true); + return activateSpan(span); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) diff --git a/dd-java-agent/instrumentation/spring-webmvc-6.0/src/main/java17/datadog/trace/instrumentation/springweb6/ControllerAdvice.java b/dd-java-agent/instrumentation/spring-webmvc-6.0/src/main/java17/datadog/trace/instrumentation/springweb6/ControllerAdvice.java index 76e2e0f0455..f4b7e8937fe 100644 --- a/dd-java-agent/instrumentation/spring-webmvc-6.0/src/main/java17/datadog/trace/instrumentation/springweb6/ControllerAdvice.java +++ b/dd-java-agent/instrumentation/spring-webmvc-6.0/src/main/java17/datadog/trace/instrumentation/springweb6/ControllerAdvice.java @@ -34,7 +34,7 @@ public static AgentScope nameResourceAndStartSpan( SpringWebHttpServerDecorator.DECORATE.afterStart(span); SpringWebHttpServerDecorator.DECORATE.onHandle(span, handler); - return activateSpan(span, true); + return activateSpan(span); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) diff --git a/dd-java-agent/instrumentation/tomcat-5.5/src/main/java/datadog/trace/instrumentation/tomcat/TomcatServerInstrumentation.java b/dd-java-agent/instrumentation/tomcat-5.5/src/main/java/datadog/trace/instrumentation/tomcat/TomcatServerInstrumentation.java index c6c69245dde..3ae2690d000 100644 --- a/dd-java-agent/instrumentation/tomcat-5.5/src/main/java/datadog/trace/instrumentation/tomcat/TomcatServerInstrumentation.java +++ b/dd-java-agent/instrumentation/tomcat-5.5/src/main/java/datadog/trace/instrumentation/tomcat/TomcatServerInstrumentation.java @@ -126,7 +126,7 @@ public static AgentScope onService(@Advice.Argument(0) org.apache.coyote.Request req.setAttribute(DD_EXTRACTED_CONTEXT_ATTRIBUTE, extractedContext); final AgentSpan span = DECORATE.startSpan(req, extractedContext); - final AgentScope scope = activateSpan(span, true); + final AgentScope scope = activateSpan(span); // This span is finished when Request.recycle() is called by RequestInstrumentation. DECORATE.afterStart(span); diff --git a/dd-java-agent/instrumentation/twilio/src/main/java/datadog/trace/instrumentation/twilio/TwilioAsyncInstrumentation.java b/dd-java-agent/instrumentation/twilio/src/main/java/datadog/trace/instrumentation/twilio/TwilioAsyncInstrumentation.java index 4450a976959..458d7274818 100644 --- a/dd-java-agent/instrumentation/twilio/src/main/java/datadog/trace/instrumentation/twilio/TwilioAsyncInstrumentation.java +++ b/dd-java-agent/instrumentation/twilio/src/main/java/datadog/trace/instrumentation/twilio/TwilioAsyncInstrumentation.java @@ -108,7 +108,7 @@ public static AgentScope methodEnter( // Enable async propagation, so the newly spawned task will be associated back with this // original trace. - return activateSpan(span, true); + return activateSpan(span); } /** Method exit instrumentation. */ diff --git a/dd-java-agent/instrumentation/undertow/undertow-2.0/src/main/java/datadog/trace/instrumentation/undertow/HandlerInstrumentation.java b/dd-java-agent/instrumentation/undertow/undertow-2.0/src/main/java/datadog/trace/instrumentation/undertow/HandlerInstrumentation.java index b2fd49d7c0c..8192c5a9840 100644 --- a/dd-java-agent/instrumentation/undertow/undertow-2.0/src/main/java/datadog/trace/instrumentation/undertow/HandlerInstrumentation.java +++ b/dd-java-agent/instrumentation/undertow/undertow-2.0/src/main/java/datadog/trace/instrumentation/undertow/HandlerInstrumentation.java @@ -95,7 +95,7 @@ public static void onEnter( final AgentSpanContext.Extracted extractedContext = DECORATE.extract(exchange); final AgentSpan span = DECORATE.startSpan(exchange, extractedContext).setMeasured(true); - scope = activateSpan(span, true); + scope = activateSpan(span); DECORATE.afterStart(span); DECORATE.onRequest(span, exchange, exchange, extractedContext); diff --git a/dd-java-agent/instrumentation/vertx-redis-client-3.9/src/main/java/datadog/trace/instrumentation/vertx_redis_client/RedisAPICallAdvice.java b/dd-java-agent/instrumentation/vertx-redis-client-3.9/src/main/java/datadog/trace/instrumentation/vertx_redis_client/RedisAPICallAdvice.java index 9be6466aaef..5a83857e40c 100644 --- a/dd-java-agent/instrumentation/vertx-redis-client-3.9/src/main/java/datadog/trace/instrumentation/vertx_redis_client/RedisAPICallAdvice.java +++ b/dd-java-agent/instrumentation/vertx-redis-client-3.9/src/main/java/datadog/trace/instrumentation/vertx_redis_client/RedisAPICallAdvice.java @@ -111,7 +111,7 @@ public static boolean beforeCall( The potential racy condition when the handler may be added to an already finished task is handled by RedisAPIImplSendAdvice. */ - scope = activateSpan(clientSpan, true); + scope = activateSpan(clientSpan); ResponseHandlerWrapper respHandler = new ResponseHandlerWrapper(handler, clientSpan, parentContinuation); handler = respHandler; diff --git a/dd-java-agent/instrumentation/vertx-redis-client-3.9/src/main/java/datadog/trace/instrumentation/vertx_redis_client/RedisFutureSendAdvice.java b/dd-java-agent/instrumentation/vertx-redis-client-3.9/src/main/java/datadog/trace/instrumentation/vertx_redis_client/RedisFutureSendAdvice.java index 44e3a67d9b9..5e58231501c 100644 --- a/dd-java-agent/instrumentation/vertx-redis-client-3.9/src/main/java/datadog/trace/instrumentation/vertx_redis_client/RedisFutureSendAdvice.java +++ b/dd-java-agent/instrumentation/vertx-redis-client-3.9/src/main/java/datadog/trace/instrumentation/vertx_redis_client/RedisFutureSendAdvice.java @@ -62,7 +62,7 @@ public static AgentScope beforeSend( DECORATE.startAndDecorateSpan( request.command(), InstrumentationContext.get(Command.class, UTF8BytesString.class)); - return activateSpan(clientSpan, true); + return activateSpan(clientSpan); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) diff --git a/dd-java-agent/instrumentation/vertx-redis-client-3.9/src/main/java/datadog/trace/instrumentation/vertx_redis_client/RedisSendAdvice.java b/dd-java-agent/instrumentation/vertx-redis-client-3.9/src/main/java/datadog/trace/instrumentation/vertx_redis_client/RedisSendAdvice.java index 8268a9fae7b..b58ead7b8fe 100644 --- a/dd-java-agent/instrumentation/vertx-redis-client-3.9/src/main/java/datadog/trace/instrumentation/vertx_redis_client/RedisSendAdvice.java +++ b/dd-java-agent/instrumentation/vertx-redis-client-3.9/src/main/java/datadog/trace/instrumentation/vertx_redis_client/RedisSendAdvice.java @@ -67,7 +67,7 @@ public static AgentScope beforeSend( request.command(), InstrumentationContext.get(Command.class, UTF8BytesString.class)); handler = new ResponseHandlerWrapper(handler, clientSpan, parentContinuation); - return activateSpan(clientSpan, true); + return activateSpan(clientSpan); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) diff --git a/dd-java-agent/instrumentation/vertx-sql-client-3.9/src/main/java/datadog/trace/instrumentation/vertx_sql_client_39/CursorReadAdvice.java b/dd-java-agent/instrumentation/vertx-sql-client-3.9/src/main/java/datadog/trace/instrumentation/vertx_sql_client_39/CursorReadAdvice.java index b6b2427886b..fbfc294591b 100644 --- a/dd-java-agent/instrumentation/vertx-sql-client-3.9/src/main/java/datadog/trace/instrumentation/vertx_sql_client_39/CursorReadAdvice.java +++ b/dd-java-agent/instrumentation/vertx-sql-client-3.9/src/main/java/datadog/trace/instrumentation/vertx_sql_client_39/CursorReadAdvice.java @@ -37,7 +37,7 @@ public static AgentScope beforeRead( } handler = new QueryResultHandlerWrapper<>(handler, clientSpan, parentContinuation); - return activateSpan(clientSpan, true); + return activateSpan(clientSpan); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) diff --git a/dd-java-agent/instrumentation/vertx-web-3.4/src/main/java/datadog/trace/instrumentation/vertx_3_4/server/RouteHandlerWrapper.java b/dd-java-agent/instrumentation/vertx-web-3.4/src/main/java/datadog/trace/instrumentation/vertx_3_4/server/RouteHandlerWrapper.java index ea62073a1ff..11d7b1634df 100644 --- a/dd-java-agent/instrumentation/vertx-web-3.4/src/main/java/datadog/trace/instrumentation/vertx_3_4/server/RouteHandlerWrapper.java +++ b/dd-java-agent/instrumentation/vertx-web-3.4/src/main/java/datadog/trace/instrumentation/vertx_3_4/server/RouteHandlerWrapper.java @@ -55,7 +55,7 @@ public void handle(final RoutingContext routingContext) { updateRoutingContextWithRoute(routingContext); } - try (final AgentScope scope = span != null ? activateSpan(span, true) : noopScope()) { + try (final AgentScope scope = span != null ? activateSpan(span) : noopScope()) { try { actual.handle(routingContext); } catch (final Throwable t) { diff --git a/dd-java-agent/instrumentation/vertx-web-4.0/src/main/java/datadog/trace/instrumentation/vertx_4_0/server/RouteHandlerWrapper.java b/dd-java-agent/instrumentation/vertx-web-4.0/src/main/java/datadog/trace/instrumentation/vertx_4_0/server/RouteHandlerWrapper.java index ab292cc2244..94d056fb57e 100644 --- a/dd-java-agent/instrumentation/vertx-web-4.0/src/main/java/datadog/trace/instrumentation/vertx_4_0/server/RouteHandlerWrapper.java +++ b/dd-java-agent/instrumentation/vertx-web-4.0/src/main/java/datadog/trace/instrumentation/vertx_4_0/server/RouteHandlerWrapper.java @@ -49,7 +49,7 @@ public void handle(final RoutingContext routingContext) { updateRoutingContextWithRoute(routingContext); } - try (final AgentScope scope = span != null ? activateSpan(span, true) : noopScope()) { + try (final AgentScope scope = span != null ? activateSpan(span) : noopScope()) { try { actual.handle(routingContext); } catch (final Throwable t) { diff --git a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/utils/TraceUtils.groovy b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/utils/TraceUtils.groovy index cd44a39eb6b..a332ea3182b 100644 --- a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/utils/TraceUtils.groovy +++ b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/utils/TraceUtils.groovy @@ -47,7 +47,7 @@ class TraceUtils { final AgentSpan span = inheritCurrent ? startSpan(rootOperationName) : startSpan(rootOperationName, null) DECORATOR.afterStart(span) - AgentScope scope = activateSpan(span, true) + AgentScope scope = activateSpan(span) try { return r.call() From 5ae56554f24022904b7488a234c7882b90c0eb77 Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Wed, 12 Mar 2025 19:15:42 +0000 Subject: [PATCH 29/98] Make the default config sources more robust when a security manager is installed (#8544) * Make the default config sources more robust when a security manager is installed If we don't have permission to access system properties or the environment then fall back to defaults. * Exclude from instruction coverage as hard to test security exception case in this module --- internal-api/build.gradle | 6 +++++- .../bootstrap/config/provider/EnvironmentConfigSource.java | 6 +++++- .../config/provider/SystemPropertiesConfigSource.java | 6 +++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/internal-api/build.gradle b/internal-api/build.gradle index cb72af95b17..57674cdcdfb 100644 --- a/internal-api/build.gradle +++ b/internal-api/build.gradle @@ -221,7 +221,11 @@ excludedClassesBranchCoverage = [ 'datadog.trace.util.stacktrace.HotSpotStackWalker', 'datadog.trace.util.stacktrace.StackWalkerFactory' ] -excludedClassesInstructionCoverage = ['datadog.trace.util.stacktrace.StackWalkerFactory'] +excludedClassesInstructionCoverage = [ + 'datadog.trace.bootstrap.config.provider.EnvironmentConfigSource', + 'datadog.trace.bootstrap.config.provider.SystemPropertiesConfigSource', + 'datadog.trace.util.stacktrace.StackWalkerFactory' +] compileTestJava.dependsOn 'generateTestClassNameTries' diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/EnvironmentConfigSource.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/EnvironmentConfigSource.java index 6719693fd86..ffbdf6f77f2 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/EnvironmentConfigSource.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/EnvironmentConfigSource.java @@ -8,7 +8,11 @@ final class EnvironmentConfigSource extends ConfigProvider.Source { @Override protected String get(String key) { - return System.getenv(propertyNameToEnvironmentVariableName(key)); + try { + return System.getenv(propertyNameToEnvironmentVariableName(key)); + } catch (SecurityException e) { + return null; + } } @Override diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/SystemPropertiesConfigSource.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/SystemPropertiesConfigSource.java index 08aaf487027..a0d561b5a37 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/SystemPropertiesConfigSource.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/SystemPropertiesConfigSource.java @@ -8,7 +8,11 @@ public final class SystemPropertiesConfigSource extends ConfigProvider.Source { @Override protected String get(String key) { - return System.getProperty(propertyNameToSystemPropertyName(key)); + try { + return System.getProperty(propertyNameToSystemPropertyName(key)); + } catch (SecurityException e) { + return null; + } } @Override From dc70612fd6e56054c75287197c27f2b88727360a Mon Sep 17 00:00:00 2001 From: Nikita Tkachenko <121111529+nikita-tkachenko-datadog@users.noreply.github.com> Date: Thu, 13 Mar 2025 11:49:49 +0100 Subject: [PATCH 30/98] Support common config sources for user-provided git info (#8547) --- .../civisibility/ci/CITagsProviderTest.groovy | 6 +- .../java/datadog/trace/api/git/GitInfo.java | 12 ---- .../api/git/UserSuppliedGitInfoBuilder.java | 64 +++++++++--------- .../git/UserSuppliedGitInfoBuilderTest.groovy | 66 +++++++++++++------ 4 files changed, 80 insertions(+), 68 deletions(-) diff --git a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/CITagsProviderTest.groovy b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/CITagsProviderTest.groovy index 03dad64ba09..d22f7542803 100644 --- a/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/CITagsProviderTest.groovy +++ b/dd-java-agent/agent-ci-visibility/src/test/groovy/datadog/trace/civisibility/ci/CITagsProviderTest.groovy @@ -1,7 +1,6 @@ package datadog.trace.civisibility.ci import datadog.trace.api.Config -import datadog.trace.api.git.GitInfo import datadog.trace.api.git.GitInfoProvider import datadog.trace.api.git.UserSuppliedGitInfoBuilder import datadog.trace.bootstrap.instrumentation.api.Tags @@ -9,6 +8,7 @@ import datadog.trace.civisibility.ci.env.CiEnvironmentImpl import datadog.trace.civisibility.git.CILocalGitInfoBuilder import datadog.trace.civisibility.git.CIProviderGitInfoBuilder import datadog.trace.civisibility.git.tree.GitClient +import datadog.trace.util.Strings import org.junit.Rule import org.junit.contrib.java.lang.system.EnvironmentVariables import org.junit.contrib.java.lang.system.RestoreSystemProperties @@ -69,7 +69,7 @@ abstract class CITagsProviderTest extends Specification { environmentVariables.set(it.key, it.value) } - environmentVariables.set(GitInfo.DD_GIT_COMMIT_SHA, "1234567890123456789012345678901234567890") + environmentVariables.set(Strings.propertyNameToEnvironmentVariableName(UserSuppliedGitInfoBuilder.DD_GIT_COMMIT_SHA), "1234567890123456789012345678901234567890") when: CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS, new CiEnvironmentImpl(System.getenv())) @@ -88,7 +88,7 @@ abstract class CITagsProviderTest extends Specification { environmentVariables.set(it.key, it.value) } - environmentVariables.set(GitInfo.DD_GIT_REPOSITORY_URL, "local supplied repo url") + environmentVariables.set(Strings.propertyNameToEnvironmentVariableName(UserSuppliedGitInfoBuilder.DD_GIT_REPOSITORY_URL), "local supplied repo url") when: CIProviderInfoFactory ciProviderInfoFactory = new CIProviderInfoFactory(Config.get(), GIT_FOLDER_FOR_TESTS, new CiEnvironmentImpl(System.getenv())) diff --git a/internal-api/src/main/java/datadog/trace/api/git/GitInfo.java b/internal-api/src/main/java/datadog/trace/api/git/GitInfo.java index 4708d3b5021..923ee211fdc 100644 --- a/internal-api/src/main/java/datadog/trace/api/git/GitInfo.java +++ b/internal-api/src/main/java/datadog/trace/api/git/GitInfo.java @@ -6,18 +6,6 @@ public class GitInfo { public static final GitInfo NOOP = new GitInfo(null, null, null, CommitInfo.NOOP); - public static final String DD_GIT_REPOSITORY_URL = "DD_GIT_REPOSITORY_URL"; - public static final String DD_GIT_BRANCH = "DD_GIT_BRANCH"; - public static final String DD_GIT_TAG = "DD_GIT_TAG"; - public static final String DD_GIT_COMMIT_SHA = "DD_GIT_COMMIT_SHA"; - public static final String DD_GIT_COMMIT_MESSAGE = "DD_GIT_COMMIT_MESSAGE"; - public static final String DD_GIT_COMMIT_AUTHOR_NAME = "DD_GIT_COMMIT_AUTHOR_NAME"; - public static final String DD_GIT_COMMIT_AUTHOR_EMAIL = "DD_GIT_COMMIT_AUTHOR_EMAIL"; - public static final String DD_GIT_COMMIT_AUTHOR_DATE = "DD_GIT_COMMIT_AUTHOR_DATE"; - public static final String DD_GIT_COMMIT_COMMITTER_NAME = "DD_GIT_COMMIT_COMMITTER_NAME"; - public static final String DD_GIT_COMMIT_COMMITTER_EMAIL = "DD_GIT_COMMIT_COMMITTER_EMAIL"; - public static final String DD_GIT_COMMIT_COMMITTER_DATE = "DD_GIT_COMMIT_COMMITTER_DATE"; - private final String repositoryURL; private final String branch; private final String tag; diff --git a/internal-api/src/main/java/datadog/trace/api/git/UserSuppliedGitInfoBuilder.java b/internal-api/src/main/java/datadog/trace/api/git/UserSuppliedGitInfoBuilder.java index 79f133bcda8..31751ff3bb6 100644 --- a/internal-api/src/main/java/datadog/trace/api/git/UserSuppliedGitInfoBuilder.java +++ b/internal-api/src/main/java/datadog/trace/api/git/UserSuppliedGitInfoBuilder.java @@ -1,33 +1,34 @@ package datadog.trace.api.git; -import static datadog.trace.api.git.GitInfo.DD_GIT_BRANCH; -import static datadog.trace.api.git.GitInfo.DD_GIT_COMMIT_AUTHOR_DATE; -import static datadog.trace.api.git.GitInfo.DD_GIT_COMMIT_AUTHOR_EMAIL; -import static datadog.trace.api.git.GitInfo.DD_GIT_COMMIT_AUTHOR_NAME; -import static datadog.trace.api.git.GitInfo.DD_GIT_COMMIT_COMMITTER_DATE; -import static datadog.trace.api.git.GitInfo.DD_GIT_COMMIT_COMMITTER_EMAIL; -import static datadog.trace.api.git.GitInfo.DD_GIT_COMMIT_COMMITTER_NAME; -import static datadog.trace.api.git.GitInfo.DD_GIT_COMMIT_MESSAGE; -import static datadog.trace.api.git.GitInfo.DD_GIT_COMMIT_SHA; -import static datadog.trace.api.git.GitInfo.DD_GIT_REPOSITORY_URL; -import static datadog.trace.api.git.GitInfo.DD_GIT_TAG; - import datadog.trace.api.Config; -import datadog.trace.api.ConfigCollector; -import datadog.trace.api.ConfigOrigin; import datadog.trace.api.config.GeneralConfig; +import datadog.trace.bootstrap.config.provider.ConfigProvider; import datadog.trace.bootstrap.instrumentation.api.Tags; +import datadog.trace.util.Strings; import javax.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class UserSuppliedGitInfoBuilder implements GitInfoBuilder { + public static final String DD_GIT_REPOSITORY_URL = "git.repository.url"; + public static final String DD_GIT_BRANCH = "git.branch"; + public static final String DD_GIT_TAG = "git.tag"; + public static final String DD_GIT_COMMIT_SHA = "git.commit.sha"; + public static final String DD_GIT_COMMIT_MESSAGE = "git.commit.message"; + public static final String DD_GIT_COMMIT_AUTHOR_NAME = "git.commit.author.name"; + public static final String DD_GIT_COMMIT_AUTHOR_EMAIL = "git.commit.author.email"; + public static final String DD_GIT_COMMIT_AUTHOR_DATE = "git.commit.author.date"; + public static final String DD_GIT_COMMIT_COMMITTER_NAME = "git.commit.committer.name"; + public static final String DD_GIT_COMMIT_COMMITTER_EMAIL = "git.commit.committer.email"; + public static final String DD_GIT_COMMIT_COMMITTER_DATE = "git.commit.committer.date"; private static final Logger log = LoggerFactory.getLogger(UserSuppliedGitInfoBuilder.class); @Override public GitInfo build(@Nullable String repositoryPath) { - String gitRepositoryUrl = System.getenv(DD_GIT_REPOSITORY_URL); + ConfigProvider configProvider = ConfigProvider.getInstance(); + + String gitRepositoryUrl = configProvider.getString(DD_GIT_REPOSITORY_URL); if (gitRepositoryUrl == null) { gitRepositoryUrl = Config.get().getGlobalTags().get(Tags.GIT_REPOSITORY_URL); } @@ -36,9 +37,9 @@ public GitInfo build(@Nullable String repositoryPath) { // using the value returned by the CI Provider, so // we need to normalize the value. Also, it can contain // the tag (e.g. origin/tags/0.1.0) - String gitTag = System.getenv(DD_GIT_TAG); + String gitTag = configProvider.getString(DD_GIT_TAG); String gitBranch = null; - final String gitBranchOrTag = System.getenv(DD_GIT_BRANCH); + final String gitBranchOrTag = configProvider.getString(DD_GIT_BRANCH); if (gitBranchOrTag != null) { if (!GitUtils.isTagReference(gitBranchOrTag)) { gitBranch = GitUtils.normalizeBranch(gitBranchOrTag); @@ -47,21 +48,18 @@ public GitInfo build(@Nullable String repositoryPath) { } } - String gitCommitSha = System.getenv(DD_GIT_COMMIT_SHA); + String gitCommitSha = configProvider.getString(DD_GIT_COMMIT_SHA); if (gitCommitSha == null) { gitCommitSha = Config.get().getGlobalTags().get(Tags.GIT_COMMIT_SHA); } - ConfigCollector.get().put(DD_GIT_REPOSITORY_URL, gitRepositoryUrl, ConfigOrigin.ENV); - ConfigCollector.get().put(DD_GIT_COMMIT_SHA, gitCommitSha, ConfigOrigin.ENV); - - final String gitCommitMessage = System.getenv(DD_GIT_COMMIT_MESSAGE); - final String gitCommitAuthorName = System.getenv(DD_GIT_COMMIT_AUTHOR_NAME); - final String gitCommitAuthorEmail = System.getenv(DD_GIT_COMMIT_AUTHOR_EMAIL); - final String gitCommitAuthorDate = System.getenv(DD_GIT_COMMIT_AUTHOR_DATE); - final String gitCommitCommitterName = System.getenv(DD_GIT_COMMIT_COMMITTER_NAME); - final String gitCommitCommitterEmail = System.getenv(DD_GIT_COMMIT_COMMITTER_EMAIL); - final String gitCommitCommitterDate = System.getenv(DD_GIT_COMMIT_COMMITTER_DATE); + final String gitCommitMessage = configProvider.getString(DD_GIT_COMMIT_MESSAGE); + final String gitCommitAuthorName = configProvider.getString(DD_GIT_COMMIT_AUTHOR_NAME); + final String gitCommitAuthorEmail = configProvider.getString(DD_GIT_COMMIT_AUTHOR_EMAIL); + final String gitCommitAuthorDate = configProvider.getString(DD_GIT_COMMIT_AUTHOR_DATE); + final String gitCommitCommitterName = configProvider.getString(DD_GIT_COMMIT_COMMITTER_NAME); + final String gitCommitCommitterEmail = configProvider.getString(DD_GIT_COMMIT_COMMITTER_EMAIL); + final String gitCommitCommitterDate = configProvider.getString(DD_GIT_COMMIT_COMMITTER_DATE); GitInfo gitInfo = new GitInfo( @@ -82,8 +80,8 @@ public GitInfo build(@Nullable String repositoryPath) { if (repoUrl == null || repoUrl.isEmpty()) { log.error( "Could not resolve git repository URL (can be provided via " - + GitInfo.DD_GIT_REPOSITORY_URL - + " env var, " + + Strings.propertyNameToEnvironmentVariableName(DD_GIT_REPOSITORY_URL) + + " env var or corresponding system property, " + GeneralConfig.TAGS + " config property or by embedding git metadata at build time)"); } @@ -94,10 +92,10 @@ public GitInfo build(@Nullable String repositoryPath) { "Git commit SHA could not be resolved or is invalid: " + commitSha + " (can be provided via " - + GitInfo.DD_GIT_COMMIT_SHA - + " env var, " + + Strings.propertyNameToEnvironmentVariableName(DD_GIT_COMMIT_SHA) + + " env var or corresponding system property, " + GeneralConfig.TAGS - + " config property or by embedding git metadata at build time; must be a full-length SHA_"); + + " config property or by embedding git metadata at build time; must be a full-length SHA"); } } diff --git a/internal-api/src/test/groovy/datadog/trace/api/git/UserSuppliedGitInfoBuilderTest.groovy b/internal-api/src/test/groovy/datadog/trace/api/git/UserSuppliedGitInfoBuilderTest.groovy index ae0ae4a09b5..3d5c886a490 100644 --- a/internal-api/src/test/groovy/datadog/trace/api/git/UserSuppliedGitInfoBuilderTest.groovy +++ b/internal-api/src/test/groovy/datadog/trace/api/git/UserSuppliedGitInfoBuilderTest.groovy @@ -20,9 +20,9 @@ class UserSuppliedGitInfoBuilderTest extends DDSpecification { gitInfo.isEmpty() } - def "user supplied git info: #envVariable"() { + def "user supplied git info: env var #envVariable"() { setup: - environmentVariables.set(envVariable, value) + environmentVariables.set(Strings.propertyNameToEnvironmentVariableName(envVariable), value) when: def gitInfo = new UserSuppliedGitInfoBuilder().build(null) @@ -32,23 +32,49 @@ class UserSuppliedGitInfoBuilderTest extends DDSpecification { gitInfoValueProvider.call(gitInfo) == value where: - envVariable | value | gitInfoValueProvider - GitInfo.DD_GIT_REPOSITORY_URL | "git repo URL" | { it.repositoryURL } - GitInfo.DD_GIT_BRANCH | "git branch" | { it.branch } - GitInfo.DD_GIT_TAG | "git tag" | { it.tag } - GitInfo.DD_GIT_COMMIT_SHA | "commit SHA" | { it.commit.sha } - GitInfo.DD_GIT_COMMIT_MESSAGE | "commit message" | { it.commit.fullMessage } - GitInfo.DD_GIT_COMMIT_AUTHOR_NAME | "commit author" | { it.commit.author.name } - GitInfo.DD_GIT_COMMIT_AUTHOR_EMAIL | "commit author mail" | { it.commit.author.email } - GitInfo.DD_GIT_COMMIT_AUTHOR_DATE | "2022-12-29T11:38:44.254Z" | { it.commit.author.iso8601Date } - GitInfo.DD_GIT_COMMIT_COMMITTER_NAME | "committer" | { it.commit.committer.name } - GitInfo.DD_GIT_COMMIT_COMMITTER_EMAIL | "committer mail" | { it.commit.committer.email } - GitInfo.DD_GIT_COMMIT_COMMITTER_DATE | "2022-12-29T10:38:44.254Z" | { it.commit.committer.iso8601Date } + envVariable | value | gitInfoValueProvider + UserSuppliedGitInfoBuilder.DD_GIT_REPOSITORY_URL | "git repo URL" | { it.repositoryURL } + UserSuppliedGitInfoBuilder.DD_GIT_BRANCH | "git branch" | { it.branch } + UserSuppliedGitInfoBuilder.DD_GIT_TAG | "git tag" | { it.tag } + UserSuppliedGitInfoBuilder.DD_GIT_COMMIT_SHA | "commit SHA" | { it.commit.sha } + UserSuppliedGitInfoBuilder.DD_GIT_COMMIT_MESSAGE | "commit message" | { it.commit.fullMessage } + UserSuppliedGitInfoBuilder.DD_GIT_COMMIT_AUTHOR_NAME | "commit author" | { it.commit.author.name } + UserSuppliedGitInfoBuilder.DD_GIT_COMMIT_AUTHOR_EMAIL | "commit author mail" | { it.commit.author.email } + UserSuppliedGitInfoBuilder.DD_GIT_COMMIT_AUTHOR_DATE | "2022-12-29T11:38:44.254Z" | { it.commit.author.iso8601Date } + UserSuppliedGitInfoBuilder.DD_GIT_COMMIT_COMMITTER_NAME | "committer" | { it.commit.committer.name } + UserSuppliedGitInfoBuilder.DD_GIT_COMMIT_COMMITTER_EMAIL | "committer mail" | { it.commit.committer.email } + UserSuppliedGitInfoBuilder.DD_GIT_COMMIT_COMMITTER_DATE | "2022-12-29T10:38:44.254Z" | { it.commit.committer.iso8601Date } + } + + def "user supplied git info: system property #systemProperty"() { + setup: + System.setProperty(Strings.propertyNameToSystemPropertyName(systemProperty), value) + + when: + def gitInfo = new UserSuppliedGitInfoBuilder().build(null) + + then: + !gitInfo.isEmpty() + gitInfoValueProvider.call(gitInfo) == value + + where: + systemProperty | value | gitInfoValueProvider + UserSuppliedGitInfoBuilder.DD_GIT_REPOSITORY_URL | "git repo URL" | { it.repositoryURL } + UserSuppliedGitInfoBuilder.DD_GIT_BRANCH | "git branch" | { it.branch } + UserSuppliedGitInfoBuilder.DD_GIT_TAG | "git tag" | { it.tag } + UserSuppliedGitInfoBuilder.DD_GIT_COMMIT_SHA | "commit SHA" | { it.commit.sha } + UserSuppliedGitInfoBuilder.DD_GIT_COMMIT_MESSAGE | "commit message" | { it.commit.fullMessage } + UserSuppliedGitInfoBuilder.DD_GIT_COMMIT_AUTHOR_NAME | "commit author" | { it.commit.author.name } + UserSuppliedGitInfoBuilder.DD_GIT_COMMIT_AUTHOR_EMAIL | "commit author mail" | { it.commit.author.email } + UserSuppliedGitInfoBuilder.DD_GIT_COMMIT_AUTHOR_DATE | "2022-12-29T11:38:44.254Z" | { it.commit.author.iso8601Date } + UserSuppliedGitInfoBuilder.DD_GIT_COMMIT_COMMITTER_NAME | "committer" | { it.commit.committer.name } + UserSuppliedGitInfoBuilder.DD_GIT_COMMIT_COMMITTER_EMAIL | "committer mail" | { it.commit.committer.email } + UserSuppliedGitInfoBuilder.DD_GIT_COMMIT_COMMITTER_DATE | "2022-12-29T10:38:44.254Z" | { it.commit.committer.iso8601Date } } def "branch name is normalized"() { setup: - environmentVariables.set(GitInfo.DD_GIT_BRANCH, "origin/myBranch") + environmentVariables.set(Strings.propertyNameToEnvironmentVariableName(UserSuppliedGitInfoBuilder.DD_GIT_BRANCH), "origin/myBranch") when: def gitInfo = new UserSuppliedGitInfoBuilder().build(null) @@ -60,7 +86,7 @@ class UserSuppliedGitInfoBuilderTest extends DDSpecification { def "tag can be supplied in branch var"() { setup: - environmentVariables.set(GitInfo.DD_GIT_BRANCH, "refs/tags/myTag") + environmentVariables.set(Strings.propertyNameToEnvironmentVariableName(UserSuppliedGitInfoBuilder.DD_GIT_BRANCH), "refs/tags/myTag") when: def gitInfo = new UserSuppliedGitInfoBuilder().build(null) @@ -73,8 +99,8 @@ class UserSuppliedGitInfoBuilderTest extends DDSpecification { def "dedicated tag var has preference over tag supplied inside branch var"() { setup: - environmentVariables.set(GitInfo.DD_GIT_TAG, "myProvidedTag") - environmentVariables.set(GitInfo.DD_GIT_BRANCH, "refs/tags/myTag") + environmentVariables.set(Strings.propertyNameToEnvironmentVariableName(UserSuppliedGitInfoBuilder.DD_GIT_TAG), "myProvidedTag") + environmentVariables.set(Strings.propertyNameToEnvironmentVariableName(UserSuppliedGitInfoBuilder.DD_GIT_BRANCH), "refs/tags/myTag") when: def gitInfo = new UserSuppliedGitInfoBuilder().build(null) @@ -101,8 +127,8 @@ class UserSuppliedGitInfoBuilderTest extends DDSpecification { def "global tags have lower priority than dedicated environment variables"() { setup: injectEnvConfig(Strings.toEnvVar(GeneralConfig.TAGS), Tags.GIT_REPOSITORY_URL + ":repo_url," + Tags.GIT_COMMIT_SHA + ":commit_sha") - injectEnvConfig(GitInfo.DD_GIT_REPOSITORY_URL, "overridden_repo_url") - injectEnvConfig(GitInfo.DD_GIT_COMMIT_SHA, "overridden_commit_sha") + injectEnvConfig(Strings.propertyNameToEnvironmentVariableName(UserSuppliedGitInfoBuilder.DD_GIT_REPOSITORY_URL), "overridden_repo_url") + injectEnvConfig(Strings.propertyNameToEnvironmentVariableName(UserSuppliedGitInfoBuilder.DD_GIT_COMMIT_SHA), "overridden_commit_sha") when: def gitInfo = new UserSuppliedGitInfoBuilder().build(null) From 3765fd1a845fdea145c3c7c2a7758084c8981cd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20=C3=81lvarez=20=C3=81lvarez?= Date: Thu, 13 Mar 2025 14:55:33 +0100 Subject: [PATCH 31/98] Allow login events SDK to be used with appsec disabled (#8464) Allow login event SDK to be used with appsec disabled --- .circleci/config.continue.yml.j2 | 2 + .../java/datadog/trace/bootstrap/Agent.java | 9 + .../java/com/datadog/appsec/AppSecSystem.java | 3 - .../appsec/gateway/AppSecRequestContext.java | 49 ++- .../datadog/appsec/gateway/GatewayBridge.java | 172 ++--------- .../gateway/GatewayBridgeSpecification.groovy | 281 ++---------------- .../AppSecEventTrackerSpecification.groovy | 182 ++++++++++-- ...ventTrackerAppSecDisabledForkedTest.groovy | 106 +++++++ .../appsec/AppSecHttpServerTest.groovy | 4 + .../SpringSecurityUserEventDecorator.java | 15 +- .../trace/api/appsec/AppSecEventTracker.java | 250 ++++++++++++++-- .../trace/api/appsec/LoginEventCallback.java | 17 -- .../datadog/trace/api/gateway/Events.java | 12 +- .../api/gateway/InstrumentationGateway.java | 27 +- .../gateway/InstrumentationGatewayTest.java | 27 +- 15 files changed, 611 insertions(+), 545 deletions(-) create mode 100644 dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/user/EventTrackerAppSecDisabledForkedTest.groovy delete mode 100644 internal-api/src/main/java/datadog/trace/api/appsec/LoginEventCallback.java diff --git a/.circleci/config.continue.yml.j2 b/.circleci/config.continue.yml.j2 index 8029d84fb12..03c6b555812 100644 --- a/.circleci/config.continue.yml.j2 +++ b/.circleci/config.continue.yml.j2 @@ -862,6 +862,8 @@ jobs: APPSEC_API_SECURITY APPSEC_API_SECURITY_RC APPSEC_API_SECURITY_WITH_SAMPLING + APPSEC_AUTO_EVENTS_RC + APPSEC_AUTO_EVENTS_EXTENDED APPSEC_WAF_TELEMETRY APPSEC_STANDALONE_V2 IAST_STANDALONE_V2 diff --git a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/Agent.java b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/Agent.java index 6c73e8f1a4c..69156ff9393 100644 --- a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/Agent.java +++ b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/Agent.java @@ -16,6 +16,7 @@ import datadog.trace.api.Platform; import datadog.trace.api.StatsDClientManager; import datadog.trace.api.WithGlobalTracer; +import datadog.trace.api.appsec.AppSecEventTracker; import datadog.trace.api.config.AppSecConfig; import datadog.trace.api.config.CiVisibilityConfig; import datadog.trace.api.config.CwsConfig; @@ -816,6 +817,14 @@ private static StatsDClientManager statsDClientManager() throws Exception { } private static void maybeStartAppSec(Class scoClass, Object o) { + + try { + // event tracking SDK must be available for customers even if AppSec is fully disabled + AppSecEventTracker.install(); + } catch (final Exception e) { + log.debug("Error starting AppSec Event Tracker", e); + } + if (!(appSecEnabled || (remoteConfigEnabled && !appSecFullyDisabled))) { return; } diff --git a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/AppSecSystem.java b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/AppSecSystem.java index 2651f45a61b..9d86b681cc1 100644 --- a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/AppSecSystem.java +++ b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/AppSecSystem.java @@ -17,7 +17,6 @@ import datadog.remoteconfig.ConfigurationPoller; import datadog.trace.api.Config; import datadog.trace.api.ProductActivation; -import datadog.trace.api.appsec.AppSecEventTracker; import datadog.trace.api.gateway.SubscriptionService; import datadog.trace.api.telemetry.ProductChange; import datadog.trace.api.telemetry.ProductChangeCollector; @@ -97,8 +96,6 @@ private static void doStart(SubscriptionService gw, SharedCommunicationObjects s Blocking.setBlockingService(new BlockingServiceImpl(REPLACEABLE_EVENT_PRODUCER)); - AppSecEventTracker.setEventTracker(new AppSecEventTracker()); - STARTED.set(true); String startedAppSecModules = String.join(", ", STARTED_MODULES_INFO.values()); diff --git a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/gateway/AppSecRequestContext.java b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/gateway/AppSecRequestContext.java index 6dc893f2faf..34536773602 100644 --- a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/gateway/AppSecRequestContext.java +++ b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/gateway/AppSecRequestContext.java @@ -8,7 +8,6 @@ import com.datadog.appsec.report.AppSecEvent; import com.datadog.appsec.util.StandardizedLogging; import datadog.trace.api.Config; -import datadog.trace.api.UserIdCollectionMode; import datadog.trace.api.http.StoredBodySupplier; import datadog.trace.api.internal.TraceSegment; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; @@ -136,10 +135,8 @@ public class AppSecRequestContext implements DataBundle, Closeable { // keep a reference to the last published usr.id private volatile String userId; - private volatile UserIdCollectionMode userIdSource; // keep a reference to the last published usr.login private volatile String userLogin; - private volatile UserIdCollectionMode userLoginSource; // keep a reference to the last published usr.session_id private volatile String sessionId; @@ -536,36 +533,30 @@ public void setRespDataPublished(boolean respDataPublished) { this.respDataPublished = respDataPublished; } - public String getUserId() { - return userId; - } - - public void setUserId(String userId) { + /** + * Updates the current used usr.id + * + * @return {@code false} if the user id has not been updated + */ + public boolean updateUserId(String userId) { + if (Objects.equals(this.userId, userId)) { + return false; + } this.userId = userId; + return true; } - public UserIdCollectionMode getUserIdSource() { - return userIdSource; - } - - public void setUserIdSource(UserIdCollectionMode userIdSource) { - this.userIdSource = userIdSource; - } - - public String getUserLogin() { - return userLogin; - } - - public void setUserLogin(String userLogin) { + /** + * Updates current used usr.login + * + * @return {@code false} if the user login has not been updated + */ + public boolean updateUserLogin(String userLogin) { + if (Objects.equals(this.userLogin, userLogin)) { + return false; + } this.userLogin = userLogin; - } - - public UserIdCollectionMode getUserLoginSource() { - return userLoginSource; - } - - public void setUserLoginSource(UserIdCollectionMode userLoginSource) { - this.userLoginSource = userLoginSource; + return true; } public void setSessionId(String sessionId) { diff --git a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/gateway/GatewayBridge.java b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/gateway/GatewayBridge.java index be8d9b487b4..7d6440932ba 100644 --- a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/gateway/GatewayBridge.java +++ b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/gateway/GatewayBridge.java @@ -1,16 +1,10 @@ package com.datadog.appsec.gateway; import static com.datadog.appsec.event.data.MapDataBundle.Builder.CAPACITY_0_2; -import static com.datadog.appsec.event.data.MapDataBundle.Builder.CAPACITY_3_4; import static com.datadog.appsec.event.data.MapDataBundle.Builder.CAPACITY_6_10; import static com.datadog.appsec.gateway.AppSecRequestContext.DEFAULT_REQUEST_HEADERS_ALLOW_LIST; import static com.datadog.appsec.gateway.AppSecRequestContext.REQUEST_HEADERS_ALLOW_LIST; import static com.datadog.appsec.gateway.AppSecRequestContext.RESPONSE_HEADERS_ALLOW_LIST; -import static datadog.trace.api.UserIdCollectionMode.ANONYMIZATION; -import static datadog.trace.api.UserIdCollectionMode.DISABLED; -import static datadog.trace.api.UserIdCollectionMode.SDK; -import static datadog.trace.api.telemetry.LogCollector.SEND_TELEMETRY; -import static datadog.trace.util.Strings.toHexString; import com.datadog.appsec.AppSecSystem; import com.datadog.appsec.api.security.ApiSecurityRequestSampler; @@ -28,7 +22,6 @@ import com.datadog.appsec.report.AppSecEventWrapper; import datadog.trace.api.Config; import datadog.trace.api.ProductTraceSource; -import datadog.trace.api.UserIdCollectionMode; import datadog.trace.api.gateway.Events; import datadog.trace.api.gateway.Flow; import datadog.trace.api.gateway.IGSpanInfo; @@ -48,19 +41,17 @@ import java.net.URISyntaxException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.EnumMap; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.regex.Pattern; import java.util.stream.Collectors; import org.slf4j.Logger; @@ -76,21 +67,16 @@ public class GatewayBridge { private static final Pattern QUERY_PARAM_SPLITTER = Pattern.compile("&"); private static final Map> EMPTY_QUERY_PARAMS = Collections.emptyMap(); - private static final int HASH_SIZE_BYTES = 16; // 128 bits - private static final String ANON_PREFIX = "anon_"; - private static final AtomicBoolean SHA_MISSING_REPORTED = new AtomicBoolean(false); - /** User tracking tags that will force the collection of request headers */ private static final String[] USER_TRACKING_TAGS = { "appsec.events.users.login.success.track", "appsec.events.users.login.failure.track" }; - private static final Map EVENT_MAPPINGS = new HashMap<>(); + private static final Map> EVENT_MAPPINGS = new EnumMap<>(LoginEvent.class); static { - EVENT_MAPPINGS.put("users.login.success", LoginEvent.LOGIN_SUCCESS); - EVENT_MAPPINGS.put("users.login.failure", LoginEvent.LOGIN_FAILURE); - EVENT_MAPPINGS.put("users.signup", LoginEvent.SIGN_UP); + EVENT_MAPPINGS.put(LoginEvent.LOGIN_SUCCESS, KnownAddresses.LOGIN_SUCCESS); + EVENT_MAPPINGS.put(LoginEvent.LOGIN_FAILURE, KnownAddresses.LOGIN_FAILURE); } private static final String METASTRUCT_EXPLOIT = "exploit"; @@ -198,44 +184,16 @@ public void reset() { shellCmdSubInfo = null; } - private Flow onUser( - final RequestContext ctx_, final UserIdCollectionMode mode, final String originalUser) { - if (mode == DISABLED) { - return NoopFlow.INSTANCE; - } - final String user = anonymizeUser(mode, originalUser); - if (user == null) { - return NoopFlow.INSTANCE; - } + private Flow onUser(final RequestContext ctx_, final String user) { final AppSecRequestContext ctx = ctx_.getData(RequestContextSlot.APPSEC); if (ctx == null) { return NoopFlow.INSTANCE; } - final TraceSegment segment = ctx_.getTraceSegment(); - - // span with ASM data - segment.setTagTop(Tags.ASM_KEEP, true); - segment.setTagTop(Tags.PROPAGATED_TRACE_SOURCE, ProductTraceSource.ASM); - - // skip event if we have an SDK one - if (mode != SDK) { - segment.setTagTop("_dd.appsec.usr.id", user); - if (ctx.getUserIdSource() == SDK) { - return NoopFlow.INSTANCE; - } - } - - // update span tags - segment.setTagTop("usr.id", user); - segment.setTagTop("_dd.appsec.user.collection_mode", mode.fullName()); // update current context with new user id - ctx.setUserIdSource(mode); - final boolean newUserId = !user.equals(ctx.getUserId()); - if (!newUserId) { + if (!ctx.updateUserId(user)) { return NoopFlow.INSTANCE; } - ctx.setUserId(user); // call waf if we have a new user id while (true) { @@ -259,96 +217,29 @@ private Flow onUser( } private Flow onLoginEvent( - final RequestContext ctx_, - final UserIdCollectionMode mode, - final String eventName, - final Boolean exists, - final String originalUser, - final Map metadata) { - if (mode == DISABLED) { - return NoopFlow.INSTANCE; - } + final RequestContext ctx_, final LoginEvent event, final String login) { final AppSecRequestContext ctx = ctx_.getData(RequestContextSlot.APPSEC); if (ctx == null) { return NoopFlow.INSTANCE; } - final TraceSegment segment = ctx_.getTraceSegment(); - - // span with ASM data - segment.setTagTop(Tags.ASM_KEEP, true); - segment.setTagTop(Tags.PROPAGATED_TRACE_SOURCE, ProductTraceSource.ASM); - - // update span tags - segment.setTagTop("appsec.events." + eventName + ".track", true, true); - if (metadata != null && !metadata.isEmpty()) { - segment.setTagTop("appsec.events." + eventName, metadata, true); - } - if (mode == SDK) { - segment.setTagTop("_dd.appsec.events." + eventName + ".sdk", true, true); - } else { - segment.setTagTop("_dd.appsec.events." + eventName + ".auto.mode", mode.fullName(), true); - } - - if (exists != null) { - if (mode == SDK || ctx.getUserLoginSource() != SDK) { - segment.setTagTop("appsec.events." + eventName + ".usr.exists", exists, true); - } - } - - final String user = anonymizeUser(mode, originalUser); - if (user == null) { - // can happen in custom events - return NoopFlow.INSTANCE; - } - - // parse the event (might be null for custom events sent via the SDK) - final LoginEvent sourceEvent = EVENT_MAPPINGS.get(eventName); - - // skip event if we have an SDK one - if (mode != SDK) { - segment.setTagTop("_dd.appsec.usr.login", user); - if (ctx.getUserLoginSource() == SDK) { - return NoopFlow.INSTANCE; - } - } else { - if (sourceEvent == LoginEvent.LOGIN_SUCCESS) { - segment.setTagTop("usr.id", user, false); - } else { - segment.setTagTop("appsec.events." + eventName + ".usr.id", user, true); - } - segment.setTagTop("_dd.appsec.user.collection_mode", mode.fullName()); - } - - // update user span tags - segment.setTagTop("appsec.events." + eventName + ".usr.login", user, true); // update current context with new user login - ctx.setUserLoginSource(mode); - if (mode == SDK) { - ctx.setUserIdSource(mode); // we are setting the usr.id through the SDK - } - final boolean newUserLogin = !user.equals(ctx.getUserLogin()); - if (!newUserLogin) { + if (!ctx.updateUserLogin(login)) { return NoopFlow.INSTANCE; } - ctx.setUserLogin(user); // call waf if we have a new user login - final List> addresses = new ArrayList<>(3); - final MapDataBundle.Builder bundleBuilder = new MapDataBundle.Builder(CAPACITY_3_4); + final List> addresses = new ArrayList<>(2); + final MapDataBundle.Builder bundleBuilder = new MapDataBundle.Builder(CAPACITY_0_2); addresses.add(KnownAddresses.USER_LOGIN); - bundleBuilder.add(KnownAddresses.USER_LOGIN, user); - if (mode == SDK) { - addresses.add(KnownAddresses.USER_ID); - bundleBuilder.add(KnownAddresses.USER_ID, user); - } - // we don't support null values for the address so we use an invalid placeholder here - if (sourceEvent == LoginEvent.LOGIN_SUCCESS) { - addresses.add(KnownAddresses.LOGIN_SUCCESS); - bundleBuilder.add(KnownAddresses.LOGIN_SUCCESS, "invalid"); - } else if (sourceEvent == LoginEvent.LOGIN_FAILURE) { - addresses.add(KnownAddresses.LOGIN_FAILURE); - bundleBuilder.add(KnownAddresses.LOGIN_FAILURE, "invalid"); + bundleBuilder.add(KnownAddresses.USER_LOGIN, login); + + // parse the event + Address address = EVENT_MAPPINGS.get(event); + if (address != null) { + addresses.add(address); + // we don't support null values for the address so we use an invalid placeholder here + bundleBuilder.add(address, "invalid"); } final DataBundle bundle = bundleBuilder.build(); final String subInfoKey = @@ -1159,33 +1050,6 @@ private static int byteToDigit(byte b) { return -1; } - protected static String anonymizeUser(final UserIdCollectionMode mode, final String userId) { - if (mode != ANONYMIZATION || userId == null) { - return userId; - } - MessageDigest digest; - try { - // TODO avoid lookup a new instance every time - digest = MessageDigest.getInstance("SHA-256"); - } catch (NoSuchAlgorithmException e) { - if (!SHA_MISSING_REPORTED.getAndSet(true)) { - log.error( - SEND_TELEMETRY, - "Missing SHA-256 digest, user collection in 'anon' mode cannot continue", - e); - } - return null; - } - digest.update(userId.getBytes()); - byte[] hash = digest.digest(); - if (hash.length > HASH_SIZE_BYTES) { - byte[] temp = new byte[HASH_SIZE_BYTES]; - System.arraycopy(hash, 0, temp, 0, temp.length); - hash = temp; - } - return ANON_PREFIX + toHexString(hash); - } - private static class IGAppSecEventDependencies { private static final Map, Collection>> diff --git a/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/gateway/GatewayBridgeSpecification.groovy b/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/gateway/GatewayBridgeSpecification.groovy index e5285983003..c083745173c 100644 --- a/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/gateway/GatewayBridgeSpecification.groovy +++ b/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/gateway/GatewayBridgeSpecification.groovy @@ -8,9 +8,6 @@ import com.datadog.appsec.event.data.DataBundle import com.datadog.appsec.event.data.KnownAddresses import com.datadog.appsec.report.AppSecEvent import com.datadog.appsec.report.AppSecEventWrapper -import datadog.trace.api.ProductTraceSource -import datadog.trace.api.UserIdCollectionMode -import datadog.trace.api.appsec.LoginEventCallback import datadog.trace.api.function.TriConsumer import datadog.trace.api.function.TriFunction import datadog.trace.api.gateway.BlockResponseFunction @@ -21,6 +18,7 @@ import datadog.trace.api.gateway.RequestContextSlot import datadog.trace.api.gateway.SubscriptionService import datadog.trace.api.http.StoredBodySupplier import datadog.trace.api.internal.TraceSegment +import datadog.trace.api.telemetry.LoginEvent import datadog.trace.bootstrap.instrumentation.api.AgentSpan import datadog.trace.bootstrap.instrumentation.api.URIDataAdapter import datadog.trace.bootstrap.instrumentation.api.URIDataAdapterBase @@ -31,16 +29,14 @@ import java.util.function.BiFunction import java.util.function.Function import java.util.function.Supplier -import static datadog.trace.api.UserIdCollectionMode.ANONYMIZATION -import static datadog.trace.api.UserIdCollectionMode.DISABLED -import static datadog.trace.api.UserIdCollectionMode.IDENTIFICATION -import static datadog.trace.api.UserIdCollectionMode.SDK import static datadog.trace.api.gateway.Events.EVENTS +import static datadog.trace.api.telemetry.LoginEvent.LOGIN_FAILURE +import static datadog.trace.api.telemetry.LoginEvent.LOGIN_SUCCESS +import static datadog.trace.api.telemetry.LoginEvent.SIGN_UP class GatewayBridgeSpecification extends DDSpecification { private static final String USER_ID = 'user' - private static final String ANONYMIZED_USER_ID = 'anon_04f8996da763b7a969b1028ee3007569' SubscriptionService ig = Mock() EventDispatcher eventDispatcher = Mock() @@ -105,8 +101,8 @@ class GatewayBridgeSpecification extends DDSpecification { BiFunction> requestSessionCB BiFunction> execCmdCB BiFunction> shellCmdCB - TriFunction> userCB - LoginEventCallback loginEventCB + BiFunction> userCB + TriFunction> loginEventCB void setup() { callInitAndCaptureCBs() @@ -1055,285 +1051,72 @@ class GatewayBridgeSpecification extends DDSpecification { gatewayContext.isTransient == false } - void "test onUserEvent (#mode)"() { + void "test onUserEvent"() { setup: - final expectedUser = mode == ANONYMIZATION ? ANONYMIZED_USER_ID : USER_ID eventDispatcher.getDataSubscribers(_) >> nonEmptyDsInfo when: - userCB.apply(ctx, mode, USER_ID) + userCB.apply(ctx, USER_ID) then: - if (mode == DISABLED) { - 0 * _ - } else { - 1 * traceSegment.setTagTop('usr.id', expectedUser) - if (mode != SDK) { - 1 * traceSegment.setTagTop('_dd.appsec.usr.id', expectedUser) - } - 1 * traceSegment.setTagTop('_dd.appsec.user.collection_mode', mode.fullName()) - 1 * eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, _ as GatewayContext) >> { a, b, DataBundle db, GatewayContext gw -> - assert db.get(KnownAddresses.USER_ID) == expectedUser - assert !gw.isTransient - return NoopFlow.INSTANCE - } + 1 * eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, _ as GatewayContext) >> { a, b, DataBundle db, GatewayContext gw -> + assert db.get(KnownAddresses.USER_ID) == USER_ID + assert !gw.isTransient + return NoopFlow.INSTANCE } when: - userCB.apply(ctx, mode, USER_ID) + userCB.apply(ctx, USER_ID) then: 'no call to the WAF for duplicated calls' 0 * eventDispatcher.publishDataEvent - - where: - mode << UserIdCollectionMode.values() } - void "test onSignup (#mode)"() { + void "test onSignup"() { setup: - final expectedUser = mode == ANONYMIZATION ? ANONYMIZED_USER_ID : USER_ID - final metadata = ['key1': 'value1', 'key2': 'value2'] eventDispatcher.getDataSubscribers(_) >> nonEmptyDsInfo when: - loginEventCB.apply(ctx, mode, 'users.signup', null, USER_ID, metadata) + loginEventCB.apply(ctx, SIGN_UP, USER_ID) then: - if (mode == DISABLED) { - 0 * _ - } else { - 1 * traceSegment.setTagTop('appsec.events.users.signup.usr.login', expectedUser, true) - if (mode != SDK) { - 1 * traceSegment.setTagTop('_dd.appsec.usr.login', expectedUser) - 1 * traceSegment.setTagTop('_dd.appsec.events.users.signup.auto.mode', mode.fullName(), true) - } else { - 1 * traceSegment.setTagTop('appsec.events.users.signup.usr.id', expectedUser, true) - 1 * traceSegment.setTagTop('_dd.appsec.events.users.signup.sdk', true, true) - } - 1 * traceSegment.setTagTop('appsec.events.users.signup.track', true, true) - 1 * traceSegment.setTagTop('appsec.events.users.signup', ['key1': 'value1', 'key2': 'value2'], true) - 1 * traceSegment.setTagTop('asm.keep', true) - 1 * traceSegment.setTagTop('_dd.p.ts', ProductTraceSource.ASM) - 1 * eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, _ as GatewayContext) >> { a, b, DataBundle db, GatewayContext gw -> - if (mode == SDK) { - assert db.get(KnownAddresses.USER_ID) == expectedUser - } - assert db.get(KnownAddresses.USER_LOGIN) == expectedUser - assert !gw.isTransient - return NoopFlow.INSTANCE - } + 1 * eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, _ as GatewayContext) >> { a, b, DataBundle db, GatewayContext gw -> + assert db.get(KnownAddresses.USER_LOGIN) == USER_ID + assert !gw.isTransient + return NoopFlow.INSTANCE } - - where: - mode << UserIdCollectionMode.values() } - void "test onLoginSuccess (#mode)"() { + void "test onLoginSuccess"() { setup: - final expectedUser = mode == ANONYMIZATION ? ANONYMIZED_USER_ID : USER_ID - final metadata = ['key1': 'value1', 'key2': 'value2'] eventDispatcher.getDataSubscribers(_) >> nonEmptyDsInfo when: - loginEventCB.apply(ctx, mode, 'users.login.success', null, USER_ID, metadata) + loginEventCB.apply(ctx, LOGIN_SUCCESS, USER_ID) then: - if (mode == DISABLED) { - 0 * _ - } else { - 1 * traceSegment.setTagTop('appsec.events.users.login.success.usr.login', expectedUser, true) - if (mode != SDK) { - 1 * traceSegment.setTagTop('_dd.appsec.usr.login', expectedUser) - 1 * traceSegment.setTagTop('_dd.appsec.events.users.login.success.auto.mode', mode.fullName(), true) - } else { - 1 * traceSegment.setTagTop('usr.id', expectedUser, false) - 1 * traceSegment.setTagTop('_dd.appsec.events.users.login.success.sdk', true, true) - } - 1 * traceSegment.setTagTop('appsec.events.users.login.success.track', true, true) - 1 * traceSegment.setTagTop('appsec.events.users.login.success', ['key1': 'value1', 'key2': 'value2'], true) - 1 * traceSegment.setTagTop('asm.keep', true) - 1 * traceSegment.setTagTop('_dd.p.ts', ProductTraceSource.ASM) - 1 * eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, _ as GatewayContext) >> { a, b, DataBundle db, GatewayContext gw -> - if (mode == SDK) { - assert db.get(KnownAddresses.USER_ID) == expectedUser - } - assert db.get(KnownAddresses.USER_LOGIN) == expectedUser - assert db.get(KnownAddresses.LOGIN_SUCCESS) != null - assert !gw.isTransient - return NoopFlow.INSTANCE - } + 1 * eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, _ as GatewayContext) >> { a, b, DataBundle db, GatewayContext gw -> + assert db.get(KnownAddresses.USER_LOGIN) == USER_ID + assert db.get(KnownAddresses.LOGIN_SUCCESS) != null + assert !gw.isTransient + return NoopFlow.INSTANCE } - - where: - mode << UserIdCollectionMode.values() } void "test onLoginFailure (#mode)"() { setup: - final expectedUser = mode == ANONYMIZATION ? ANONYMIZED_USER_ID : USER_ID - final metadata = ['key1': 'value1', 'key2': 'value2'] eventDispatcher.getDataSubscribers(_) >> nonEmptyDsInfo when: - loginEventCB.apply(ctx, mode, 'users.login.failure', false, USER_ID, metadata) + loginEventCB.apply(ctx, LOGIN_FAILURE, USER_ID) then: - if (mode == DISABLED) { - 0 * _ - } else { - 1 * traceSegment.setTagTop('appsec.events.users.login.failure.usr.login', expectedUser, true) - if (mode != SDK) { - 1 * traceSegment.setTagTop('_dd.appsec.usr.login', expectedUser) - 1 * traceSegment.setTagTop('_dd.appsec.events.users.login.failure.auto.mode', mode.fullName(), true) - } else { - 1 * traceSegment.setTagTop('appsec.events.users.login.failure.usr.id', expectedUser, true) - 1 * traceSegment.setTagTop('_dd.appsec.events.users.login.failure.sdk', true, true) - } - 1 * traceSegment.setTagTop('appsec.events.users.login.failure.track', true, true) - 1 * traceSegment.setTagTop('appsec.events.users.login.failure.usr.exists', false, true) - 1 * traceSegment.setTagTop('appsec.events.users.login.failure', ['key1': 'value1', 'key2': 'value2'], true) - 1 * traceSegment.setTagTop('asm.keep', true) - 1 * traceSegment.setTagTop('_dd.p.ts', ProductTraceSource.ASM) - 1 * eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, _ as GatewayContext) >> { a, b, DataBundle db, GatewayContext gw -> - if (mode == SDK) { - assert db.get(KnownAddresses.USER_ID) == expectedUser - } - assert db.get(KnownAddresses.USER_LOGIN) == expectedUser - assert db.get(KnownAddresses.LOGIN_FAILURE) != null - assert !gw.isTransient - return NoopFlow.INSTANCE - } + 1 * eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, _ as GatewayContext) >> { a, b, DataBundle db, GatewayContext gw -> + assert db.get(KnownAddresses.USER_LOGIN) == USER_ID + assert db.get(KnownAddresses.LOGIN_FAILURE) != null + assert !gw.isTransient + return NoopFlow.INSTANCE } - - where: - mode << UserIdCollectionMode.values() - } - - void "test onCustomEvent (#mode)"() { - setup: - final metadata = ['key1': 'value1', 'key2': 'value2'] - eventDispatcher.getDataSubscribers(_) >> nonEmptyDsInfo - - when: - loginEventCB.apply(ctx, SDK, 'my.event', null, null, metadata) - - then: - 1 * traceSegment.setTagTop('_dd.appsec.events.my.event.sdk', true, true) - 1 * traceSegment.setTagTop('appsec.events.my.event.track', true, true) - 1 * traceSegment.setTagTop('appsec.events.my.event', ['key1': 'value1', 'key2': 'value2'], true) - 1 * traceSegment.setTagTop('asm.keep', true) - 1 * traceSegment.setTagTop('_dd.p.ts', ProductTraceSource.ASM) - 0 * eventDispatcher.publishDataEvent - } - - void "test onUserEvent (automated login events should not overwrite SDK)"() { - setup: - final firstUser = 'first-user' - final secondUser = 'second-user' - eventDispatcher.getDataSubscribers(_) >> nonEmptyDsInfo - - when: - userCB.apply(ctx, SDK, firstUser) - - then: - 1 * traceSegment.setTagTop('usr.id', firstUser) - 1 * traceSegment.setTagTop('_dd.appsec.user.collection_mode', SDK.fullName()) - 0 * traceSegment.setTagTop('_dd.appsec.usr.id', _) - 1 * eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, _ as GatewayContext) >> NoopFlow.INSTANCE - - when: - userCB.apply(ctx, IDENTIFICATION, secondUser) - - then: 'SDK data remains untouched' - 0 * traceSegment.setTagTop('usr.id', _) - 0 * traceSegment.setTagTop('_dd.appsec.user.collection_mode', _) - 1 * traceSegment.setTagTop('_dd.appsec.usr.id', secondUser) - 0 * eventDispatcher.publishDataEvent - } - - void "test onLoginSuccess (automated login events should not overwrite SDK)"() { - setup: - final firstUser = 'user1' - final secondUser = 'user2' - eventDispatcher.getDataSubscribers(_) >> nonEmptyDsInfo - - when: - loginEventCB.apply(ctx, SDK, 'users.login.success', null, firstUser, null) - - then: - 1 * traceSegment.setTagTop('appsec.events.users.login.success.usr.login', firstUser, true) - 1 * traceSegment.setTagTop('usr.id', firstUser, false) - 1 * traceSegment.setTagTop('_dd.appsec.events.users.login.success.sdk', true, true) - 1 * traceSegment.setTagTop('_dd.appsec.user.collection_mode', 'sdk') - - 0 * traceSegment.setTagTop('_dd.appsec.usr.login', _) - 0 * traceSegment.setTagTop('_dd.appsec.events.users.login.success.auto.mode', _, _) - - 1 * eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, _ as GatewayContext) >> NoopFlow.INSTANCE - - when: - loginEventCB.apply(ctx, IDENTIFICATION, 'users.login.success', null, secondUser, null) - - then: - 0 * traceSegment.setTagTop('appsec.events.users.login.success.usr.login', _, _) - 0 * traceSegment.setTagTop('usr.id', _, _) - 0 * traceSegment.setTagTop('_dd.appsec.events.users.login.success.sdk', _, _) - 0 * traceSegment.setTagTop('_dd.appsec.user.collection_mode', _) - - 1 * traceSegment.setTagTop('_dd.appsec.usr.login', secondUser) - 1 * traceSegment.setTagTop('_dd.appsec.events.users.login.success.auto.mode', IDENTIFICATION.fullName(), true) - - 0 * eventDispatcher.publishDataEvent - } - - void "test onLoginFailure (automated login events should not overwrite SDK)"() { - setup: - final firstUser = 'user1' - final secondUser = 'user2' - eventDispatcher.getDataSubscribers(_) >> nonEmptyDsInfo - - when: - loginEventCB.apply(ctx, SDK, 'users.login.failure', true, firstUser, null) - - then: - 1 * traceSegment.setTagTop('appsec.events.users.login.failure.usr.login', firstUser, true) - 1 * traceSegment.setTagTop('_dd.appsec.events.users.login.failure.sdk', true, true) - 1 * traceSegment.setTagTop('_dd.appsec.user.collection_mode', 'sdk') - 1 * traceSegment.setTagTop('appsec.events.users.login.failure.usr.exists', true, true) - - 0 * traceSegment.setTagTop('_dd.appsec.usr.login', _) - 0 * traceSegment.setTagTop('_dd.appsec.events.users.login.failure.auto.mode', _, _) - - 1 * eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, _ as GatewayContext) >> NoopFlow.INSTANCE - - when: - loginEventCB.apply(ctx, IDENTIFICATION, 'users.login.failure', false, secondUser, null) - - then: - 0 * traceSegment.setTagTop('appsec.events.users.login.failure.usr.login', _, _) - 0 * traceSegment.setTagTop('_dd.appsec.events.users.login.failure.sdk', _, _) - 0 * traceSegment.setTagTop('_dd.appsec.user.collection_mode', _) - 0 * traceSegment.setTagTop('appsec.events.users.login.failure.usr.exists', _, _) - - 1 * traceSegment.setTagTop('_dd.appsec.usr.login', secondUser) - 1 * traceSegment.setTagTop('_dd.appsec.events.users.login.failure.auto.mode', IDENTIFICATION.fullName(), true) - - 0 * eventDispatcher.publishDataEvent - } - - void 'test onUserNotFound'() { - setup: - eventDispatcher.getDataSubscribers(_) >> nonEmptyDsInfo - - when: - loginEventCB.apply(ctx, IDENTIFICATION, 'users.login.failure', exists, null, null) - - then: - 1 * traceSegment.setTagTop('appsec.events.users.login.failure.usr.exists', exists, true) - 0 * eventDispatcher.publishDataEvent - - where: - exists << [true, false] } void 'test configuration updates should reset cached subscriptions'() { diff --git a/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/user/AppSecEventTrackerSpecification.groovy b/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/user/AppSecEventTrackerSpecification.groovy index 9872914df7e..4721e6de178 100644 --- a/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/user/AppSecEventTrackerSpecification.groovy +++ b/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/user/AppSecEventTrackerSpecification.groovy @@ -5,28 +5,37 @@ import datadog.appsec.api.blocking.BlockingContentType import datadog.appsec.api.blocking.BlockingException import datadog.trace.api.EventTracker import datadog.trace.api.GlobalTracer +import datadog.trace.api.ProductTraceSource import datadog.trace.api.UserIdCollectionMode import datadog.trace.api.appsec.AppSecEventTracker -import datadog.trace.api.appsec.LoginEventCallback import datadog.trace.api.function.TriFunction import datadog.trace.api.gateway.CallbackProvider import datadog.trace.api.gateway.Flow import datadog.trace.api.gateway.RequestContext import datadog.trace.api.gateway.RequestContextSlot import datadog.trace.api.internal.TraceSegment +import datadog.trace.api.telemetry.LoginEvent import datadog.trace.bootstrap.ActiveSubsystems import datadog.trace.bootstrap.instrumentation.api.AgentSpan import datadog.trace.bootstrap.instrumentation.api.AgentTracer.TracerAPI import datadog.trace.test.util.DDSpecification import spock.lang.Shared +import java.util.function.BiFunction + +import static datadog.trace.api.UserIdCollectionMode.ANONYMIZATION import static datadog.trace.api.UserIdCollectionMode.DISABLED +import static datadog.trace.api.UserIdCollectionMode.IDENTIFICATION import static datadog.trace.api.UserIdCollectionMode.SDK import static datadog.trace.api.gateway.Events.EVENTS +import static datadog.trace.api.telemetry.LoginEvent.LOGIN_FAILURE +import static datadog.trace.api.telemetry.LoginEvent.LOGIN_SUCCESS +import static datadog.trace.api.telemetry.LoginEvent.SIGN_UP class AppSecEventTrackerSpecification extends DDSpecification { private static final String USER_ID = 'user' + private static final String ANONYMIZED_USER_ID = 'anon_04f8996da763b7a969b1028ee3007569' @Shared private static boolean appSecActiveBefore = ActiveSubsystems.APPSEC_ACTIVE @@ -38,14 +47,14 @@ class AppSecEventTrackerSpecification extends DDSpecification { private TracerAPI tracer private AgentSpan span private CallbackProvider provider - private TriFunction> user - private LoginEventCallback loginEvent + private BiFunction> user + private TriFunction> loginEvent void setup() { traceSegment = Mock(TraceSegment) span = Stub(AgentSpan) - user = Mock(TriFunction) - loginEvent = Mock(LoginEventCallback) + user = Mock(BiFunction) + loginEvent = Mock(TriFunction) provider = Stub(CallbackProvider) { getCallback(EVENTS.user()) >> user @@ -73,19 +82,36 @@ class AppSecEventTrackerSpecification extends DDSpecification { def 'test track login success event (SDK)'() { when: - GlobalTracer.getEventTracker().trackLoginSuccessEvent('user1', ['key1': 'value1', 'key2': 'value2']) + GlobalTracer.getEventTracker().trackLoginSuccessEvent(USER_ID, ['key1': 'value1', 'key2': 'value2']) then: - 1 * loginEvent.apply(_ as RequestContext, SDK, 'users.login.success', null, 'user1', ['key1': 'value1', 'key2': 'value2']) >> NoopFlow.INSTANCE + 1 * traceSegment.setTagTop('usr.id', USER_ID) + 1 * traceSegment.setTagTop('appsec.events.users.login.success.usr.login', USER_ID) + 1 * traceSegment.setTagTop('appsec.events.users.login.success', ['key1':'value1', 'key2':'value2']) + 1 * traceSegment.setTagTop('appsec.events.users.login.success.track', true) + 1 * traceSegment.setTagTop('_dd.appsec.events.users.login.success.sdk', true) + 1 * traceSegment.setTagTop('asm.keep', true) + 1 * traceSegment.setTagTop('_dd.p.ts', ProductTraceSource.ASM) + 1 * loginEvent.apply(_ as RequestContext, LOGIN_SUCCESS, USER_ID) >> NoopFlow.INSTANCE + 1 * user.apply(_ as RequestContext, USER_ID) >> NoopFlow.INSTANCE 0 * _ } def 'test track login failure event (SDK)'() { when: - GlobalTracer.getEventTracker().trackLoginFailureEvent('user1', true, ['key1': 'value1', 'key2': 'value2']) + GlobalTracer.getEventTracker().trackLoginFailureEvent(USER_ID, true, ['key1': 'value1', 'key2': 'value2']) then: - 1 * loginEvent.apply(_ as RequestContext, SDK, 'users.login.failure', true, 'user1', ['key1': 'value1', 'key2': 'value2']) >> NoopFlow.INSTANCE + 1 * traceSegment.setTagTop('appsec.events.users.login.failure.usr.id', USER_ID) + 1 * traceSegment.setTagTop('appsec.events.users.login.failure.usr.login', USER_ID) + 1 * traceSegment.setTagTop('appsec.events.users.login.failure.usr.exists', true) + 1 * traceSegment.setTagTop('appsec.events.users.login.failure', ['key1':'value1', 'key2':'value2']) + 1 * traceSegment.setTagTop('appsec.events.users.login.failure.track', true) + 1 * traceSegment.setTagTop('_dd.appsec.events.users.login.failure.sdk', true) + 1 * traceSegment.setTagTop('asm.keep', true) + 1 * traceSegment.setTagTop('_dd.p.ts', ProductTraceSource.ASM) + 1 * loginEvent.apply(_ as RequestContext, LOGIN_FAILURE, USER_ID) >> NoopFlow.INSTANCE + 1 * user.apply(_ as RequestContext, USER_ID) >> NoopFlow.INSTANCE 0 * _ } @@ -94,7 +120,11 @@ class AppSecEventTrackerSpecification extends DDSpecification { GlobalTracer.getEventTracker().trackCustomEvent('myevent', ['key1': 'value1', 'key2': 'value2']) then: - 1 * loginEvent.apply(_ as RequestContext, SDK, 'myevent', null, null, ['key1': 'value1', 'key2': 'value2']) >> NoopFlow.INSTANCE + 1 * traceSegment.setTagTop('appsec.events.myevent', ['key1':'value1', 'key2':'value2'], true) + 1 * traceSegment.setTagTop('appsec.events.myevent.track', true, true) + 1 * traceSegment.setTagTop('_dd.appsec.events.myevent.sdk', true, true) + 1 * traceSegment.setTagTop('asm.keep', true) + 1 * traceSegment.setTagTop('_dd.p.ts', ProductTraceSource.ASM) 0 * _ } @@ -137,12 +167,31 @@ class AppSecEventTrackerSpecification extends DDSpecification { } def "test onSignup (#mode)"() { + setup: + final expectedUserId = mode == ANONYMIZATION ? ANONYMIZED_USER_ID: USER_ID + when: tracker.onSignupEvent(mode, USER_ID, ['key1': 'value1', 'key2': 'value2']) then: if (mode != DISABLED) { - 1 * loginEvent.apply(_ as RequestContext, mode, 'users.signup', null, USER_ID, ['key1': 'value1', 'key2': 'value2']) >> NoopFlow.INSTANCE + if (mode == SDK) { + 1 * traceSegment.setTagTop('appsec.events.users.signup.usr.id', USER_ID) + 1 * traceSegment.setTagTop('_dd.appsec.events.users.signup.sdk', true) + } else { + 1 * traceSegment.getTagTop('_dd.appsec.events.users.signup.sdk') >> null // no SDK event before + 1 * traceSegment.setTagTop('_dd.appsec.usr.login', expectedUserId) + 1 * traceSegment.setTagTop('_dd.appsec.events.users.signup.auto.mode', mode.fullName()) + } + 1 * traceSegment.setTagTop('appsec.events.users.signup.usr.login', expectedUserId) + 1 * traceSegment.setTagTop('appsec.events.users.signup', ['key1':'value1', 'key2':'value2']) + 1 * traceSegment.setTagTop('appsec.events.users.signup.track', true) + 1 * traceSegment.setTagTop('asm.keep', true) + 1 * traceSegment.setTagTop('_dd.p.ts', ProductTraceSource.ASM) + 1 * loginEvent.apply(_ as RequestContext, SIGN_UP, expectedUserId) >> NoopFlow.INSTANCE + if (mode == SDK) { + 1 * user.apply(_ as RequestContext, USER_ID) >> NoopFlow.INSTANCE + } } 0 * _ @@ -151,12 +200,31 @@ class AppSecEventTrackerSpecification extends DDSpecification { } def "test onLoginSuccess (#mode)"() { + setup: + final expectedUserId = mode == ANONYMIZATION ? ANONYMIZED_USER_ID: USER_ID + when: tracker.onLoginSuccessEvent(mode, USER_ID, ['key1': 'value1', 'key2': 'value2']) then: if (mode != DISABLED) { - 1 * loginEvent.apply(_ as RequestContext, mode, 'users.login.success', null, USER_ID, ['key1': 'value1', 'key2': 'value2']) >> NoopFlow.INSTANCE + if (mode == SDK) { + 1 * traceSegment.setTagTop('usr.id', USER_ID) + 1 * traceSegment.setTagTop('_dd.appsec.events.users.login.success.sdk', true) + } else { + 1 * traceSegment.getTagTop('_dd.appsec.events.users.login.success.sdk') >> null // no SDK event before + 1 * traceSegment.setTagTop('_dd.appsec.usr.login', expectedUserId) + 1 * traceSegment.setTagTop('_dd.appsec.events.users.login.success.auto.mode', mode.fullName()) + } + 1 * traceSegment.setTagTop('appsec.events.users.login.success.usr.login', expectedUserId) + 1 * traceSegment.setTagTop('appsec.events.users.login.success', ['key1':'value1', 'key2':'value2']) + 1 * traceSegment.setTagTop('appsec.events.users.login.success.track', true) + 1 * traceSegment.setTagTop('asm.keep', true) + 1 * traceSegment.setTagTop('_dd.p.ts', ProductTraceSource.ASM) + 1 * loginEvent.apply(_ as RequestContext, LOGIN_SUCCESS, expectedUserId) >> NoopFlow.INSTANCE + if (mode == SDK) { + 1 * user.apply(_ as RequestContext, USER_ID) >> NoopFlow.INSTANCE + } } 0 * _ @@ -165,12 +233,32 @@ class AppSecEventTrackerSpecification extends DDSpecification { } def "test onLoginFailed (#mode)"() { + setup: + final expectedUserId = mode == ANONYMIZATION ? ANONYMIZED_USER_ID: USER_ID + when: - tracker.onLoginFailureEvent(mode, USER_ID, null, ['key1': 'value1', 'key2': 'value2']) + tracker.onLoginFailureEvent(mode, USER_ID, true, ['key1': 'value1', 'key2': 'value2']) then: if (mode != DISABLED) { - 1 * loginEvent.apply(_ as RequestContext, mode, 'users.login.failure', null, USER_ID, ['key1': 'value1', 'key2': 'value2']) >> NoopFlow.INSTANCE + if (mode == SDK) { + 1 * traceSegment.setTagTop('appsec.events.users.login.failure.usr.id', USER_ID) + 1 * traceSegment.setTagTop('_dd.appsec.events.users.login.failure.sdk', true) + } else { + 1 * traceSegment.getTagTop('_dd.appsec.events.users.login.failure.sdk') >> null // no SDK event before + 1 * traceSegment.setTagTop('_dd.appsec.usr.login', expectedUserId) + 1 * traceSegment.setTagTop('_dd.appsec.events.users.login.failure.auto.mode', mode.fullName()) + } + 1 * traceSegment.setTagTop('appsec.events.users.login.failure.usr.login', expectedUserId) + 1 * traceSegment.setTagTop('appsec.events.users.login.failure', ['key1':'value1', 'key2':'value2']) + 1 * traceSegment.setTagTop('appsec.events.users.login.failure.usr.exists', true) + 1 * traceSegment.setTagTop('appsec.events.users.login.failure.track', true) + 1 * traceSegment.setTagTop('asm.keep', true) + 1 * traceSegment.setTagTop('_dd.p.ts', ProductTraceSource.ASM) + 1 * loginEvent.apply(_ as RequestContext, LOGIN_FAILURE, expectedUserId) >> NoopFlow.INSTANCE + if (mode == SDK) { + 1 * user.apply(_ as RequestContext, USER_ID) >> NoopFlow.INSTANCE + } } 0 * _ @@ -179,12 +267,23 @@ class AppSecEventTrackerSpecification extends DDSpecification { } def "test onUserEvent (#mode)"() { + setup: + final expectedUserId = mode == ANONYMIZATION ? ANONYMIZED_USER_ID: USER_ID + when: tracker.onUserEvent(mode, USER_ID) then: if (mode != DISABLED) { - 1 * user.apply(_ as RequestContext, mode, USER_ID) >> NoopFlow.INSTANCE + if (mode != SDK) { + 1 * traceSegment.setTagTop('_dd.appsec.usr.id', expectedUserId) + 1 * traceSegment.getTagTop('_dd.appsec.user.collection_mode') >> null // no user event before + } + 1 * traceSegment.setTagTop('_dd.appsec.user.collection_mode', mode.fullName()) + 1 * traceSegment.setTagTop('usr.id', expectedUserId) + 1 * traceSegment.setTagTop('asm.keep', true) + 1 * traceSegment.setTagTop('_dd.p.ts', ProductTraceSource.ASM) + 1 * user.apply(_ as RequestContext, expectedUserId) >> NoopFlow.INSTANCE } 0 * _ @@ -198,7 +297,12 @@ class AppSecEventTrackerSpecification extends DDSpecification { then: if (mode != DISABLED) { - 1 * loginEvent.apply(_ as RequestContext, mode, 'users.login.failure', false, null, null) >> NoopFlow.INSTANCE + if (mode != SDK) { + 1 * traceSegment.getTagTop('_dd.appsec.events.users.login.failure.sdk') >> null // no SDK event before + } + 1 * traceSegment.setTagTop('appsec.events.users.login.failure.usr.exists', false) + 1 * traceSegment.setTagTop('asm.keep', true) + 1 * traceSegment.setTagTop('_dd.p.ts', ProductTraceSource.ASM) } 0 * _ @@ -259,7 +363,7 @@ class AppSecEventTrackerSpecification extends DDSpecification { void 'test blocking on a userId'() { setup: final action = new Flow.Action.RequestBlockingAction(403, BlockingContentType.AUTO) - loginEvent.apply(_ as RequestContext, SDK, 'users.login.success', null, USER_ID, ['key1': 'value1', 'key2': 'value2']) >> new ActionFlow(action: action) + loginEvent.apply(_ as RequestContext, LOGIN_SUCCESS, USER_ID) >> new ActionFlow(action: action) when: tracker.onLoginSuccessEvent(SDK, USER_ID, ['key1': 'value1', 'key2': 'value2']) @@ -270,13 +374,55 @@ class AppSecEventTrackerSpecification extends DDSpecification { void 'should not fail on null callback'() { when: - tracker.onUserEvent(UserIdCollectionMode.IDENTIFICATION, 'test-user') + tracker.onUserEvent(IDENTIFICATION, 'test-user') then: noExceptionThrown() provider.getCallback(EVENTS.user()) >> null } + void 'test onUserEvent (automated login events should not overwrite SDK)'() { + when: + tracker.onUserEvent(IDENTIFICATION, USER_ID) + + then: 'SDK data remains untouched' + 1 * traceSegment.getTagTop('_dd.appsec.user.collection_mode') >> SDK.fullName() + 1 * traceSegment.setTagTop('_dd.appsec.usr.id', USER_ID) + 0 * _ + } + + + void 'test onLoginSuccess (automated login events should not overwrite SDK)'() { + when: + tracker.onLoginSuccessEvent(IDENTIFICATION, USER_ID, [:]) + + then: + 1 * traceSegment.getTagTop('_dd.appsec.events.users.login.success.sdk') >> true + 1 * traceSegment.setTagTop('_dd.appsec.usr.login', USER_ID) + 1 * traceSegment.setTagTop('_dd.appsec.events.users.login.success.auto.mode', IDENTIFICATION.fullName()) + 0 * _ + } + + void 'test onLoginFailure (automated login events should not overwrite SDK)'() { + when: + tracker.onLoginFailureEvent(IDENTIFICATION, USER_ID, null, [:]) + + then: + 1 * traceSegment.getTagTop('_dd.appsec.events.users.login.failure.sdk') >> true + 1 * traceSegment.setTagTop('_dd.appsec.usr.login', USER_ID) + 1 * traceSegment.setTagTop('_dd.appsec.events.users.login.failure.auto.mode', IDENTIFICATION.fullName()) + 0 * _ + } + + void 'test onUserNotFound (automated login events should not overwrite SDK)'() { + when: + tracker.onUserNotFound(IDENTIFICATION) + + then: + 1 * traceSegment.getTagTop('_dd.appsec.events.users.login.failure.sdk') >> true + 0 * _ + } + private static class ActionFlow implements Flow { private Action action diff --git a/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/user/EventTrackerAppSecDisabledForkedTest.groovy b/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/user/EventTrackerAppSecDisabledForkedTest.groovy new file mode 100644 index 00000000000..3912a1785bc --- /dev/null +++ b/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/user/EventTrackerAppSecDisabledForkedTest.groovy @@ -0,0 +1,106 @@ +package com.datadog.appsec.user + + +import datadog.trace.api.GlobalTracer +import datadog.trace.api.UserIdCollectionMode +import datadog.trace.api.appsec.AppSecEventTracker +import datadog.trace.api.gateway.RequestContextSlot +import datadog.trace.api.internal.TraceSegment +import datadog.trace.bootstrap.ActiveSubsystems +import datadog.trace.bootstrap.instrumentation.api.AgentTracer +import datadog.trace.test.util.DDSpecification + +import static datadog.trace.api.UserIdCollectionMode.IDENTIFICATION + +class EventTrackerAppSecDisabledForkedTest extends DDSpecification { + + TraceSegment traceSegment + + AppSecEventTracker tracker + + void setupSpec() { + injectSysConfig('dd.appsec.enabled', 'false') + ActiveSubsystems.APPSEC_ACTIVE = false + } + + void setup() { + tracker = new AppSecEventTracker() + GlobalTracer.setEventTracker(tracker) + + traceSegment = Mock(TraceSegment) + final tracer = Stub(AgentTracer.TracerAPI) { + getTraceSegment() >> traceSegment + getCallbackProvider(RequestContextSlot.APPSEC) >> null + } + AgentTracer.forceRegister(tracer) + } + + void 'test track login success event (SDK)'() { + when: + GlobalTracer.getEventTracker().trackLoginSuccessEvent('user', ['key1': 'value1', 'key2': 'value2']) + + then: + 1 * traceSegment.setTagTop('_dd.appsec.events.users.login.success.sdk', true) + } + + void 'test track login failure event (SDK)'() { + when: + GlobalTracer.getEventTracker().trackLoginFailureEvent('user', true, ['key1': 'value1', 'key2': 'value2']) + + then: + 1 * traceSegment.setTagTop('_dd.appsec.events.users.login.failure.sdk', true) + } + + void 'test track custom event (SDK)'() { + when: + GlobalTracer.getEventTracker().trackCustomEvent('myevent', ['key1': 'value1', 'key2': 'value2']) + + then: + 1 * traceSegment.setTagTop('_dd.appsec.events.myevent.sdk', true, true) + } + + void 'test onSignup'() { + when: + tracker.onSignupEvent(IDENTIFICATION, 'user', ['key1': 'value1', 'key2': 'value2']) + + then: + 0 * _ + } + + void 'test onLoginSuccess'() { + + when: + tracker.onLoginSuccessEvent(IDENTIFICATION, 'user', ['key1': 'value1', 'key2': 'value2']) + + then: + 0 * _ + } + + void 'test onLoginFailed'() { + when: + tracker.onLoginFailureEvent(IDENTIFICATION, 'user', true, ['key1': 'value1', 'key2': 'value2']) + + then: + 0 * _ + + where: + mode << UserIdCollectionMode.values() + } + + def 'test onUserEvent'() { + when: + tracker.onUserEvent(IDENTIFICATION, 'user') + + then: + 0 * _ + } + + def 'test onUserNotFound'() { + when: + tracker.onUserNotFound(IDENTIFICATION) + + then: + 0 * _ + } +} + diff --git a/dd-java-agent/appsec/src/testFixtures/groovy/com/datadog/appsec/AppSecHttpServerTest.groovy b/dd-java-agent/appsec/src/testFixtures/groovy/com/datadog/appsec/AppSecHttpServerTest.groovy index 6182f9e0a4a..f03ed7b0a64 100644 --- a/dd-java-agent/appsec/src/testFixtures/groovy/com/datadog/appsec/AppSecHttpServerTest.groovy +++ b/dd-java-agent/appsec/src/testFixtures/groovy/com/datadog/appsec/AppSecHttpServerTest.groovy @@ -4,6 +4,8 @@ import datadog.communication.ddagent.SharedCommunicationObjects import datadog.communication.monitor.Monitoring import datadog.trace.agent.test.base.WithHttpServer import datadog.trace.api.Config +import datadog.trace.api.GlobalTracer +import datadog.trace.api.appsec.AppSecEventTracker import datadog.trace.api.gateway.RequestContextSlot import datadog.trace.api.gateway.SubscriptionService import datadog.trace.bootstrap.instrumentation.api.AgentTracer @@ -25,6 +27,8 @@ abstract class AppSecHttpServerTest extends WithHttpServer { assert sco.configurationPoller(config) == null assert sco.monitoring instanceof Monitoring.DisabledMonitoring + GlobalTracer.setEventTracker(new AppSecEventTracker()) + AppSecSystem.start(ss, sco) } diff --git a/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/SpringSecurityUserEventDecorator.java b/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/SpringSecurityUserEventDecorator.java index 63cd1624b96..d7285e7f976 100644 --- a/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/SpringSecurityUserEventDecorator.java +++ b/dd-java-agent/instrumentation/spring-security-5/src/main/java/datadog/trace/instrumentation/springsecurity5/SpringSecurityUserEventDecorator.java @@ -3,6 +3,8 @@ import static datadog.trace.api.UserIdCollectionMode.IDENTIFICATION; import static datadog.trace.api.telemetry.LogCollector.SEND_TELEMETRY; +import datadog.trace.api.EventTracker; +import datadog.trace.api.GlobalTracer; import datadog.trace.api.UserIdCollectionMode; import datadog.trace.api.appsec.AppSecEventTracker; import datadog.trace.api.telemetry.LoginEvent; @@ -34,7 +36,7 @@ public class SpringSecurityUserEventDecorator { Collections.newSetFromMap(new ConcurrentHashMap<>()); public void onUserNotFound() { - final AppSecEventTracker tracker = AppSecEventTracker.getEventTracker(); + final AppSecEventTracker tracker = getEventTracker(); if (tracker == null) { return; } @@ -48,7 +50,7 @@ public void onSignup(UserDetails user, Throwable throwable) { return; } - final AppSecEventTracker tracker = AppSecEventTracker.getEventTracker(); + final AppSecEventTracker tracker = getEventTracker(); if (tracker == null) { return; } @@ -75,7 +77,7 @@ public void onLogin(Authentication authentication, Throwable throwable, Authenti return; } - final AppSecEventTracker tracker = AppSecEventTracker.getEventTracker(); + final AppSecEventTracker tracker = getEventTracker(); if (tracker == null) { return; } @@ -127,7 +129,7 @@ public void onUser(final Authentication authentication) { return; } - final AppSecEventTracker tracker = AppSecEventTracker.getEventTracker(); + final AppSecEventTracker tracker = getEventTracker(); if (tracker == null) { return; } @@ -181,4 +183,9 @@ private static boolean missingUsername(final String username, final LoginEvent e } return false; } + + private static AppSecEventTracker getEventTracker() { + final EventTracker tracker = GlobalTracer.getEventTracker(); + return tracker instanceof AppSecEventTracker ? (AppSecEventTracker) tracker : null; + } } diff --git a/internal-api/src/main/java/datadog/trace/api/appsec/AppSecEventTracker.java b/internal-api/src/main/java/datadog/trace/api/appsec/AppSecEventTracker.java index 9e2a49527d7..2fed75c22cb 100644 --- a/internal-api/src/main/java/datadog/trace/api/appsec/AppSecEventTracker.java +++ b/internal-api/src/main/java/datadog/trace/api/appsec/AppSecEventTracker.java @@ -1,12 +1,18 @@ package datadog.trace.api.appsec; +import static datadog.trace.api.UserIdCollectionMode.ANONYMIZATION; import static datadog.trace.api.UserIdCollectionMode.DISABLED; import static datadog.trace.api.UserIdCollectionMode.SDK; import static datadog.trace.api.gateway.Events.EVENTS; +import static datadog.trace.api.telemetry.LoginEvent.LOGIN_FAILURE; +import static datadog.trace.api.telemetry.LoginEvent.LOGIN_SUCCESS; +import static datadog.trace.api.telemetry.LoginEvent.SIGN_UP; +import static datadog.trace.util.Strings.toHexString; import datadog.appsec.api.blocking.BlockingException; import datadog.trace.api.EventTracker; import datadog.trace.api.GlobalTracer; +import datadog.trace.api.ProductTraceSource; import datadog.trace.api.UserIdCollectionMode; import datadog.trace.api.gateway.BlockResponseFunction; import datadog.trace.api.gateway.CallbackProvider; @@ -14,23 +20,27 @@ import datadog.trace.api.gateway.Flow; import datadog.trace.api.gateway.RequestContext; import datadog.trace.api.gateway.RequestContextSlot; +import datadog.trace.api.internal.TraceSegment; import datadog.trace.bootstrap.ActiveSubsystems; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.AgentTracer; +import datadog.trace.bootstrap.instrumentation.api.Tags; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.Map; import java.util.function.BiFunction; public class AppSecEventTracker extends EventTracker { - private static AppSecEventTracker INSTANCE; + private static final int HASH_SIZE_BYTES = 16; // 128 bits + private static final String ANON_PREFIX = "anon_"; - public static AppSecEventTracker getEventTracker() { - return INSTANCE; - } + private static final String LOGIN_SUCCESS_TAG = "users.login.success"; + private static final String LOGIN_FAILURE_TAG = "users.login.failure"; + private static final String SIGNUP_TAG = "users.signup"; - public static void setEventTracker(final AppSecEventTracker tracker) { - INSTANCE = tracker; - GlobalTracer.setEventTracker(tracker == null ? EventTracker.NO_EVENT_TRACKER : tracker); + public static void install() { + GlobalTracer.setEventTracker(new AppSecEventTracker()); } @Override @@ -62,16 +72,47 @@ public void onUserNotFound(final UserIdCollectionMode mode) { if (!isEnabled(mode)) { return; } - dispatch( - EVENTS.loginEvent(), - (ctx, callback) -> callback.apply(ctx, mode, "users.login.failure", false, null, null)); + final AgentTracer.TracerAPI tracer = tracer(); + if (tracer == null) { + return; + } + final TraceSegment segment = tracer.getTraceSegment(); + if (segment == null) { + return; + } + if (isNewLoginEvent(mode, segment, LOGIN_FAILURE_TAG)) { + segment.setTagTop("appsec.events.users.login.failure.usr.exists", false); + segment.setTagTop(Tags.ASM_KEEP, true); + segment.setTagTop(Tags.PROPAGATED_TRACE_SOURCE, ProductTraceSource.ASM); + } } public void onUserEvent(final UserIdCollectionMode mode, final String userId) { if (!isEnabled(mode)) { return; } - dispatch(EVENTS.user(), (ctx, cb) -> cb.apply(ctx, mode, userId)); + final AgentTracer.TracerAPI tracer = tracer(); + if (tracer == null) { + return; + } + final TraceSegment segment = tracer.getTraceSegment(); + if (segment == null) { + return; + } + final String finalUserId = anonymizeUser(mode, userId); + if (finalUserId == null) { + return; + } + if (mode != SDK) { + segment.setTagTop("_dd.appsec.usr.id", finalUserId); + } + if (isNewUser(mode, segment)) { + segment.setTagTop("usr.id", finalUserId); + segment.setTagTop("_dd.appsec.user.collection_mode", mode.fullName()); + segment.setTagTop(Tags.ASM_KEEP, true); + segment.setTagTop(Tags.PROPAGATED_TRACE_SOURCE, ProductTraceSource.ASM); + dispatch(tracer, EVENTS.user(), (ctx, cb) -> cb.apply(ctx, finalUserId)); + } } public void onSignupEvent( @@ -79,9 +120,43 @@ public void onSignupEvent( if (!isEnabled(mode)) { return; } - dispatch( - EVENTS.loginEvent(), - (ctx, callback) -> callback.apply(ctx, mode, "users.signup", null, userId, metadata)); + final AgentTracer.TracerAPI tracer = tracer(); + if (tracer == null) { + return; + } + final TraceSegment segment = tracer.getTraceSegment(); + if (segment == null) { + return; + } + final String finalUserId = anonymizeUser(mode, userId); + if (finalUserId == null) { + return; + } + + if (mode == SDK) { + // TODO update SDK separating usr.login / usr.id + segment.setTagTop("appsec.events.users.signup.usr.id", finalUserId); + segment.setTagTop("_dd.appsec.events.users.signup.sdk", true); + } else { + segment.setTagTop("_dd.appsec.usr.login", finalUserId); + segment.setTagTop("_dd.appsec.events.users.signup.auto.mode", mode.fullName()); + } + if (isNewLoginEvent(mode, segment, SIGNUP_TAG)) { + segment.setTagTop("appsec.events.users.signup.usr.login", finalUserId); + if (metadata != null && !metadata.isEmpty()) { + segment.setTagTop("appsec.events.users.signup", metadata); + } + segment.setTagTop("appsec.events.users.signup.track", true); + segment.setTagTop(Tags.ASM_KEEP, true); + segment.setTagTop(Tags.PROPAGATED_TRACE_SOURCE, ProductTraceSource.ASM); + dispatch( + tracer, + EVENTS.loginEvent(), + (ctx, callback) -> callback.apply(ctx, SIGN_UP, finalUserId)); + if (mode == SDK) { + dispatch(tracer, EVENTS.user(), (ctx, callback) -> callback.apply(ctx, finalUserId)); + } + } } public void onLoginSuccessEvent( @@ -89,9 +164,42 @@ public void onLoginSuccessEvent( if (!isEnabled(mode)) { return; } - dispatch( - EVENTS.loginEvent(), - (ctx, cb) -> cb.apply(ctx, mode, "users.login.success", null, userId, metadata)); + final AgentTracer.TracerAPI tracer = tracer(); + if (tracer == null) { + return; + } + final TraceSegment segment = tracer.getTraceSegment(); + if (segment == null) { + return; + } + final String finalUserId = anonymizeUser(mode, userId); + if (finalUserId == null) { + return; + } + if (mode == SDK) { + // TODO update SDK separating usr.login / usr.id + segment.setTagTop("usr.id", finalUserId); + segment.setTagTop("_dd.appsec.events.users.login.success.sdk", true); + } else { + segment.setTagTop("_dd.appsec.usr.login", finalUserId); + segment.setTagTop("_dd.appsec.events.users.login.success.auto.mode", mode.fullName()); + } + if (isNewLoginEvent(mode, segment, LOGIN_SUCCESS_TAG)) { + segment.setTagTop("appsec.events.users.login.success.usr.login", finalUserId); + if (metadata != null && !metadata.isEmpty()) { + segment.setTagTop("appsec.events.users.login.success", metadata); + } + segment.setTagTop("appsec.events.users.login.success.track", true); + segment.setTagTop(Tags.ASM_KEEP, true); + segment.setTagTop(Tags.PROPAGATED_TRACE_SOURCE, ProductTraceSource.ASM); + dispatch( + tracer, + EVENTS.loginEvent(), + (ctx, callback) -> callback.apply(ctx, LOGIN_SUCCESS, finalUserId)); + if (mode == SDK) { + dispatch(tracer, EVENTS.user(), (ctx, callback) -> callback.apply(ctx, finalUserId)); + } + } } public void onLoginFailureEvent( @@ -102,9 +210,46 @@ public void onLoginFailureEvent( if (!isEnabled(mode)) { return; } - dispatch( - EVENTS.loginEvent(), - (ctx, cb) -> cb.apply(ctx, mode, "users.login.failure", exists, userId, metadata)); + final AgentTracer.TracerAPI tracer = tracer(); + if (tracer == null) { + return; + } + final TraceSegment segment = tracer.getTraceSegment(); + if (segment == null) { + return; + } + final String finalUserId = anonymizeUser(mode, userId); + if (finalUserId == null) { + return; + } + + if (mode == SDK) { + // TODO update SDK separating usr.login / usr.id + segment.setTagTop("appsec.events.users.login.failure.usr.id", finalUserId); + segment.setTagTop("_dd.appsec.events.users.login.failure.sdk", true); + } else { + segment.setTagTop("_dd.appsec.usr.login", finalUserId); + segment.setTagTop("_dd.appsec.events.users.login.failure.auto.mode", mode.fullName()); + } + if (isNewLoginEvent(mode, segment, LOGIN_FAILURE_TAG)) { + segment.setTagTop("appsec.events.users.login.failure.usr.login", finalUserId); + if (metadata != null && !metadata.isEmpty()) { + segment.setTagTop("appsec.events.users.login.failure", metadata); + } + if (exists != null) { + segment.setTagTop("appsec.events.users.login.failure.usr.exists", exists); + } + segment.setTagTop("appsec.events.users.login.failure.track", true); + segment.setTagTop(Tags.ASM_KEEP, true); + segment.setTagTop(Tags.PROPAGATED_TRACE_SOURCE, ProductTraceSource.ASM); + dispatch( + tracer, + EVENTS.loginEvent(), + (ctx, callback) -> callback.apply(ctx, LOGIN_FAILURE, finalUserId)); + if (mode == SDK) { + dispatch(tracer, EVENTS.user(), (ctx, callback) -> callback.apply(ctx, finalUserId)); + } + } } public void onCustomEvent( @@ -112,13 +257,47 @@ public void onCustomEvent( if (!isEnabled(mode)) { return; } - dispatch( - EVENTS.loginEvent(), (ctx, cb) -> cb.apply(ctx, mode, eventName, null, null, metadata)); + final AgentTracer.TracerAPI tracer = tracer(); + if (tracer == null) { + return; + } + final TraceSegment segment = tracer.getTraceSegment(); + if (segment == null) { + return; + } + if (mode == SDK) { + segment.setTagTop("_dd.appsec.events." + eventName + ".sdk", true, true); + } + if (isNewLoginEvent(mode, segment, eventName)) { + if (metadata != null && !metadata.isEmpty()) { + segment.setTagTop("appsec.events." + eventName, metadata, true); + } + segment.setTagTop("appsec.events." + eventName + ".track", true, true); + segment.setTagTop(Tags.ASM_KEEP, true); + segment.setTagTop(Tags.PROPAGATED_TRACE_SOURCE, ProductTraceSource.ASM); + } + } + + private boolean isNewLoginEvent( + final UserIdCollectionMode mode, final TraceSegment segment, final String event) { + if (mode == SDK) { + return true; + } + return segment.getTagTop("_dd.appsec.events." + event + ".sdk") == null; + } + + private boolean isNewUser(final UserIdCollectionMode mode, final TraceSegment segment) { + if (mode == SDK) { + return true; + } + final Object value = segment.getTagTop("_dd.appsec.user.collection_mode"); + return value == null || !"sdk".equalsIgnoreCase(value.toString()); } private void dispatch( - final EventType event, final BiFunction> consumer) { - final AgentTracer.TracerAPI tracer = tracer(); + final AgentTracer.TracerAPI tracer, + final EventType event, + final BiFunction> consumer) { if (tracer == null) { return; } @@ -157,8 +336,29 @@ private void dispatch( } } + protected static String anonymizeUser(final UserIdCollectionMode mode, final String userId) { + if (mode != ANONYMIZATION || userId == null) { + return userId; + } + MessageDigest digest; + try { + // TODO avoid lookup a new instance every time + digest = MessageDigest.getInstance("SHA-256"); + } catch (NoSuchAlgorithmException e) { + return null; + } + digest.update(userId.getBytes()); + byte[] hash = digest.digest(); + if (hash.length > HASH_SIZE_BYTES) { + byte[] temp = new byte[HASH_SIZE_BYTES]; + System.arraycopy(hash, 0, temp, 0, temp.length); + hash = temp; + } + return ANON_PREFIX + toHexString(hash); + } + protected boolean isEnabled(final UserIdCollectionMode mode) { - return ActiveSubsystems.APPSEC_ACTIVE && mode != DISABLED; + return mode == SDK || (ActiveSubsystems.APPSEC_ACTIVE && mode != DISABLED); } // Extract this to allow for easier testing diff --git a/internal-api/src/main/java/datadog/trace/api/appsec/LoginEventCallback.java b/internal-api/src/main/java/datadog/trace/api/appsec/LoginEventCallback.java deleted file mode 100644 index 11e12103904..00000000000 --- a/internal-api/src/main/java/datadog/trace/api/appsec/LoginEventCallback.java +++ /dev/null @@ -1,17 +0,0 @@ -package datadog.trace.api.appsec; - -import datadog.trace.api.UserIdCollectionMode; -import datadog.trace.api.gateway.Flow; -import datadog.trace.api.gateway.RequestContext; -import java.util.Map; - -public interface LoginEventCallback { - - Flow apply( - RequestContext context, - UserIdCollectionMode mode, - String eventName, - Boolean exists, - String user, - Map metadata); -} diff --git a/internal-api/src/main/java/datadog/trace/api/gateway/Events.java b/internal-api/src/main/java/datadog/trace/api/gateway/Events.java index a9195ec5510..d840cad01c3 100644 --- a/internal-api/src/main/java/datadog/trace/api/gateway/Events.java +++ b/internal-api/src/main/java/datadog/trace/api/gateway/Events.java @@ -1,10 +1,9 @@ package datadog.trace.api.gateway; -import datadog.trace.api.UserIdCollectionMode; -import datadog.trace.api.appsec.LoginEventCallback; import datadog.trace.api.function.TriConsumer; import datadog.trace.api.function.TriFunction; import datadog.trace.api.http.StoredBodySupplier; +import datadog.trace.api.telemetry.LoginEvent; import datadog.trace.bootstrap.instrumentation.api.URIDataAdapter; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; @@ -279,8 +278,8 @@ public EventType>> requestSession( /** Triggered in every authenticated request to the application */ @SuppressWarnings("unchecked") - public EventType>> user() { - return (EventType>>) USER; + public EventType>> user() { + return (EventType>>) USER; } static final int LOGIN_EVENT_ID = 23; @@ -288,10 +287,9 @@ public EventType("login.event", LOGIN_EVENT_ID); - /** Triggered when the SDK sends a custom event */ @SuppressWarnings("unchecked") - public EventType loginEvent() { - return (EventType) LOGIN_EVENT; + public EventType>> loginEvent() { + return (EventType>>) LOGIN_EVENT; } static final int EXEC_CMD_ID = 24; diff --git a/internal-api/src/main/java/datadog/trace/api/gateway/InstrumentationGateway.java b/internal-api/src/main/java/datadog/trace/api/gateway/InstrumentationGateway.java index 72a690596d0..cd5219f1dfc 100644 --- a/internal-api/src/main/java/datadog/trace/api/gateway/InstrumentationGateway.java +++ b/internal-api/src/main/java/datadog/trace/api/gateway/InstrumentationGateway.java @@ -28,11 +28,10 @@ import static datadog.trace.api.gateway.Events.SHELL_CMD_ID; import static datadog.trace.api.gateway.Events.USER_ID; -import datadog.trace.api.UserIdCollectionMode; -import datadog.trace.api.appsec.LoginEventCallback; import datadog.trace.api.function.TriConsumer; import datadog.trace.api.function.TriFunction; import datadog.trace.api.http.StoredBodySupplier; +import datadog.trace.api.telemetry.LoginEvent; import datadog.trace.bootstrap.instrumentation.api.URIDataAdapter; import java.util.Map; import java.util.concurrent.atomic.AtomicReferenceArray; @@ -388,14 +387,12 @@ public void accept(RequestContext ctx, String arg) { }; case USER_ID: return (C) - new TriFunction>() { + new BiFunction>() { @Override - public Flow apply( - RequestContext ctx, UserIdCollectionMode mode, String userId) { + public Flow apply(RequestContext ctx, String userId) { try { - return ((TriFunction>) - callback) - .apply(ctx, mode, userId); + return ((BiFunction>) callback) + .apply(ctx, userId); } catch (Throwable t) { log.warn("Callback for {} threw.", eventType, t); return Flow.ResultFlow.empty(); @@ -404,19 +401,13 @@ public Flow apply( }; case LOGIN_EVENT_ID: return (C) - new LoginEventCallback() { + new TriFunction>() { @Override - public Flow apply( - RequestContext ctx, - UserIdCollectionMode mode, - String eventName, - Boolean exists, - String user, - Map metadata) { + public Flow apply(RequestContext ctx, LoginEvent event, String user) { try { - return ((LoginEventCallback) callback) - .apply(ctx, mode, eventName, exists, user, metadata); + return ((TriFunction>) callback) + .apply(ctx, event, user); } catch (Throwable t) { log.warn("Callback for {} threw.", eventType, t); return Flow.ResultFlow.empty(); diff --git a/internal-api/src/test/java/datadog/trace/api/gateway/InstrumentationGatewayTest.java b/internal-api/src/test/java/datadog/trace/api/gateway/InstrumentationGatewayTest.java index 85e88df9600..8f2840d4308 100644 --- a/internal-api/src/test/java/datadog/trace/api/gateway/InstrumentationGatewayTest.java +++ b/internal-api/src/test/java/datadog/trace/api/gateway/InstrumentationGatewayTest.java @@ -4,7 +4,6 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import datadog.appsec.api.blocking.BlockingContentType; -import datadog.trace.api.appsec.LoginEventCallback; import datadog.trace.api.function.TriConsumer; import datadog.trace.api.function.TriFunction; import datadog.trace.api.http.StoredBodySupplier; @@ -215,9 +214,9 @@ public void testNormalCalls() { ss.registerCallback(events.fileLoaded(), callback); cbp.getCallback(events.fileLoaded()).apply(null, null); ss.registerCallback(events.user(), callback); - cbp.getCallback(events.user()).apply(null, null, null); - ss.registerCallback(events.loginEvent(), callback.asLoginEventCallback()); - cbp.getCallback(events.loginEvent()).apply(null, null, null, null, null, null); + cbp.getCallback(events.user()).apply(null, null); + ss.registerCallback(events.loginEvent(), callback); + cbp.getCallback(events.loginEvent()).apply(null, null, null); ss.registerCallback(events.requestSession(), callback); cbp.getCallback(events.requestSession()).apply(null, null); ss.registerCallback(events.execCmd(), callback); @@ -285,9 +284,9 @@ public void testThrowableBlocking() { ss.registerCallback(events.fileLoaded(), throwback); cbp.getCallback(events.fileLoaded()).apply(null, null); ss.registerCallback(events.user(), throwback); - cbp.getCallback(events.user()).apply(null, null, null); - ss.registerCallback(events.loginEvent(), throwback.asLoginEventCallback()); - cbp.getCallback(events.loginEvent()).apply(null, null, null, null, null, null); + cbp.getCallback(events.user()).apply(null, null); + ss.registerCallback(events.loginEvent(), throwback); + cbp.getCallback(events.loginEvent()).apply(null, null, null); ss.registerCallback(events.requestSession(), throwback); cbp.getCallback(events.requestSession()).apply(null, null); ss.registerCallback(events.execCmd(), throwback); @@ -507,13 +506,6 @@ public Flow apply(RequestContext requestContext, T t, T t2) { count++; return flow; } - - public LoginEventCallback asLoginEventCallback() { - return (context, mode, eventName, exists, user, metadata) -> { - count++; - return flow; - }; - } } private static class Throwback @@ -583,13 +575,6 @@ public BiFunction> asRequestBodyD }; } - public LoginEventCallback asLoginEventCallback() { - return (context, mode, eventName, exists, user, metadata) -> { - count++; - throw new IllegalArgumentException(); - }; - } - public int getCount() { return count; } From b7656bd58e76f89413ab67524113a9dbf154f64e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20=C3=81lvarez=20=C3=81lvarez?= Date: Thu, 13 Mar 2025 15:58:28 +0100 Subject: [PATCH 32/98] Update system-tests to c208feb5b40cca543670870b9601509d6a69c65e (#8550) --- .circleci/config.continue.yml.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.continue.yml.j2 b/.circleci/config.continue.yml.j2 index 03c6b555812..efa74f11135 100644 --- a/.circleci/config.continue.yml.j2 +++ b/.circleci/config.continue.yml.j2 @@ -36,7 +36,7 @@ instrumentation_modules: &instrumentation_modules "dd-java-agent/instrumentation debugger_modules: &debugger_modules "dd-java-agent/agent-debugger|dd-java-agent/agent-bootstrap|dd-java-agent/agent-builder|internal-api|communication|dd-trace-core" profiling_modules: &profiling_modules "dd-java-agent/agent-profiling" -default_system_tests_commit: &default_system_tests_commit 5aee0ed598fd984344cf0da0048b27bdb2eb4da1 +default_system_tests_commit: &default_system_tests_commit c208feb5b40cca543670870b9601509d6a69c65e parameters: nightly: From 6eb11aa62b35c7e5d68f9b7440279eb709338a33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20=C3=81lvarez=20=C3=81lvarez?= Date: Thu, 13 Mar 2025 16:49:08 +0100 Subject: [PATCH 33/98] Add missing address for signup event (#8469) --- .../java/com/datadog/appsec/event/data/KnownAddresses.java | 5 +++++ .../main/java/com/datadog/appsec/gateway/GatewayBridge.java | 1 + .../appsec/event/data/KnownAddressesSpecification.groovy | 3 ++- .../datadog/appsec/gateway/GatewayBridgeSpecification.groovy | 1 + 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/event/data/KnownAddresses.java b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/event/data/KnownAddresses.java index 7ae351434e5..d88c2fb0311 100644 --- a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/event/data/KnownAddresses.java +++ b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/event/data/KnownAddresses.java @@ -133,6 +133,9 @@ public interface KnownAddresses { /** Login success business event */ Address LOGIN_SUCCESS = new Address<>("server.business_logic.users.login.success"); + /** Signup business event */ + Address SIGN_UP = new Address<>("server.business_logic.users.signup"); + /** The Exec command being executed */ Address EXEC_CMD = new Address<>("server.sys.exec.cmd"); @@ -215,6 +218,8 @@ static Address forName(String name) { return LOGIN_SUCCESS; case "server.business_logic.users.login.failure": return LOGIN_FAILURE; + case "server.business_logic.users.signup": + return SIGN_UP; case "server.sys.exec.cmd": return EXEC_CMD; case "server.sys.shell.cmd": diff --git a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/gateway/GatewayBridge.java b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/gateway/GatewayBridge.java index 7d6440932ba..54665d12ca9 100644 --- a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/gateway/GatewayBridge.java +++ b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/gateway/GatewayBridge.java @@ -77,6 +77,7 @@ public class GatewayBridge { static { EVENT_MAPPINGS.put(LoginEvent.LOGIN_SUCCESS, KnownAddresses.LOGIN_SUCCESS); EVENT_MAPPINGS.put(LoginEvent.LOGIN_FAILURE, KnownAddresses.LOGIN_FAILURE); + EVENT_MAPPINGS.put(LoginEvent.SIGN_UP, KnownAddresses.SIGN_UP); } private static final String METASTRUCT_EXPLOIT = "exploit"; diff --git a/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/event/data/KnownAddressesSpecification.groovy b/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/event/data/KnownAddressesSpecification.groovy index 87e21067c6a..49a6a449f3b 100644 --- a/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/event/data/KnownAddressesSpecification.groovy +++ b/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/event/data/KnownAddressesSpecification.groovy @@ -40,6 +40,7 @@ class KnownAddressesSpecification extends Specification { 'usr.session_id', 'server.business_logic.users.login.failure', 'server.business_logic.users.login.success', + 'server.business_logic.users.signup', 'server.io.net.url', 'server.io.fs.file', 'server.sys.exec.cmd', @@ -50,7 +51,7 @@ class KnownAddressesSpecification extends Specification { void 'number of known addresses is expected number'() { expect: - Address.instanceCount() == 38 + Address.instanceCount() == 39 KnownAddresses.WAF_CONTEXT_PROCESSOR.serial == Address.instanceCount() - 1 } } diff --git a/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/gateway/GatewayBridgeSpecification.groovy b/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/gateway/GatewayBridgeSpecification.groovy index c083745173c..c13156d461b 100644 --- a/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/gateway/GatewayBridgeSpecification.groovy +++ b/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/gateway/GatewayBridgeSpecification.groovy @@ -1082,6 +1082,7 @@ class GatewayBridgeSpecification extends DDSpecification { then: 1 * eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, _ as GatewayContext) >> { a, b, DataBundle db, GatewayContext gw -> assert db.get(KnownAddresses.USER_LOGIN) == USER_ID + assert db.get(KnownAddresses.SIGN_UP) != null assert !gw.isTransient return NoopFlow.INSTANCE } From 0a8bc736ce36355a707fcc775e93fcb8cf4d8c5e Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Thu, 13 Mar 2025 16:27:14 +0000 Subject: [PATCH 34/98] Remove unnecessary calls to setAsyncPropagationEnabled (#8551) --- .../instrumentation/java/concurrent/AdviceUtils.java | 2 -- .../test/groovy/AkkaExecutorInstrumentationTest.groovy | 5 ----- .../TraceContinuedFutureCallback.java | 4 ---- .../apachehttpclient5/TraceContinuedFutureCallback.java | 4 ---- .../src/test/groovy/CompletableFutureTest.groovy | 2 -- .../src/test/groovy/VirtualThreadTest.groovy | 3 --- .../groovy/executor/ExecutorInstrumentationTest.groovy | 6 ------ .../executor/NettyExecutorInstrumentationTest.groovy | 3 --- .../test/groovy/executor/RejectedExecutionTest.groovy | 4 ---- .../test/groovy/JettyExecutorInstrumentationTest.groovy | 2 -- .../src/test/groovy/OpenTelemetryTest.groovy | 3 --- .../api-0.31/src/test/groovy/OpenTracing31Test.groovy | 1 - .../api-0.32/src/test/groovy/OpenTracing32Test.groovy | 1 - .../instrumentation/play23/RequestCompleteCallback.java | 2 -- .../instrumentation/play24/RequestCompleteCallback.java | 2 -- .../instrumentation/play26/RequestCompleteCallback.java | 2 -- .../instrumentation/playws1/AsyncHandlerWrapper.java | 3 --- .../instrumentation/playws21/AsyncHandlerWrapper.java | 3 --- .../instrumentation/playws2/AsyncHandlerWrapper.java | 3 --- .../test/groovy/ScalaExecutorInstrumentationTest.groovy | 4 ---- .../trace/instrumentation/servlet2/Servlet2Advice.java | 2 -- .../springscheduling/SpannedMethodInvocation.java | 2 -- .../trace/core/PendingTraceStrictWriteTest.groovy | 4 ---- .../groovy/datadog/trace/core/PendingTraceTest.groovy | 3 --- .../trace/core/scopemanager/ScopeManagerTest.groovy | 9 --------- 25 files changed, 79 deletions(-) diff --git a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/java/concurrent/AdviceUtils.java b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/java/concurrent/AdviceUtils.java index c3376dcaa18..c347de48aae 100644 --- a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/java/concurrent/AdviceUtils.java +++ b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/java/concurrent/AdviceUtils.java @@ -2,7 +2,6 @@ import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activeSpan; import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.isAsyncPropagationEnabled; -import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.setAsyncPropagationEnabled; import datadog.trace.bootstrap.ContextStore; import datadog.trace.bootstrap.instrumentation.api.AgentScope; @@ -29,7 +28,6 @@ public static AgentScope startTaskScope(State state) { final AgentScope.Continuation continuation = state.getAndResetContinuation(); if (continuation != null) { final AgentScope scope = continuation.activate(); - setAsyncPropagationEnabled(true); // important - stop timing after the scope has been activated so the time in the queue can // be attributed to the correct context without duplicating the propagated information state.stopTiming(); diff --git a/dd-java-agent/instrumentation/akka-concurrent/src/test/groovy/AkkaExecutorInstrumentationTest.groovy b/dd-java-agent/instrumentation/akka-concurrent/src/test/groovy/AkkaExecutorInstrumentationTest.groovy index 13bfaa7b9fe..e7dcbb02efd 100644 --- a/dd-java-agent/instrumentation/akka-concurrent/src/test/groovy/AkkaExecutorInstrumentationTest.groovy +++ b/dd-java-agent/instrumentation/akka-concurrent/src/test/groovy/AkkaExecutorInstrumentationTest.groovy @@ -16,8 +16,6 @@ import java.util.concurrent.RejectedExecutionException import java.util.concurrent.ThreadPoolExecutor import java.util.concurrent.TimeUnit -import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.setAsyncPropagationEnabled - /** * Test executor instrumentation for Akka specific classes. * This is to large extent a copy of ExecutorInstrumentationTest. @@ -46,7 +44,6 @@ class AkkaExecutorInstrumentationTest extends AgentTestRunner { @Override @Trace(operationName = "parent") void run() { - setAsyncPropagationEnabled(true) // this child will have a span m(pool, new AkkaAsyncChild()) // this child won't @@ -102,7 +99,6 @@ class AkkaExecutorInstrumentationTest extends AgentTestRunner { @Override @Trace(operationName = "parent") void run() { - setAsyncPropagationEnabled(true) // this child will have a span dispatcher.execute(new AkkaAsyncChild()) // this child won't @@ -133,7 +129,6 @@ class AkkaExecutorInstrumentationTest extends AgentTestRunner { @Override @Trace(operationName = "parent") void run() { - setAsyncPropagationEnabled(true) try { for (int i = 0; i < 20; ++i) { // Our current instrumentation instrumentation does not behave very well diff --git a/dd-java-agent/instrumentation/apache-httpasyncclient-4/src/main/java/datadog/trace/instrumentation/apachehttpasyncclient/TraceContinuedFutureCallback.java b/dd-java-agent/instrumentation/apache-httpasyncclient-4/src/main/java/datadog/trace/instrumentation/apachehttpasyncclient/TraceContinuedFutureCallback.java index e38c048e436..5217f109822 100644 --- a/dd-java-agent/instrumentation/apache-httpasyncclient-4/src/main/java/datadog/trace/instrumentation/apachehttpasyncclient/TraceContinuedFutureCallback.java +++ b/dd-java-agent/instrumentation/apache-httpasyncclient-4/src/main/java/datadog/trace/instrumentation/apachehttpasyncclient/TraceContinuedFutureCallback.java @@ -1,7 +1,6 @@ package datadog.trace.instrumentation.apachehttpasyncclient; import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.noopContinuation; -import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.setAsyncPropagationEnabled; import static datadog.trace.instrumentation.apachehttpasyncclient.ApacheHttpAsyncClientDecorator.DECORATE; import datadog.trace.bootstrap.instrumentation.api.AgentScope; @@ -37,7 +36,6 @@ public void completed(final T result) { completeDelegate(result); } else { try (final AgentScope scope = parentContinuation.activate()) { - setAsyncPropagationEnabled(true); completeDelegate(result); } } @@ -54,7 +52,6 @@ public void failed(final Exception ex) { failDelegate(ex); } else { try (final AgentScope scope = parentContinuation.activate()) { - setAsyncPropagationEnabled(true); failDelegate(ex); } } @@ -70,7 +67,6 @@ public void cancelled() { cancelDelegate(); } else { try (final AgentScope scope = parentContinuation.activate()) { - setAsyncPropagationEnabled(true); cancelDelegate(); } } diff --git a/dd-java-agent/instrumentation/apache-httpclient-5/src/main/java/datadog/trace/instrumentation/apachehttpclient5/TraceContinuedFutureCallback.java b/dd-java-agent/instrumentation/apache-httpclient-5/src/main/java/datadog/trace/instrumentation/apachehttpclient5/TraceContinuedFutureCallback.java index f9491b3797f..d283b9c7ca5 100644 --- a/dd-java-agent/instrumentation/apache-httpclient-5/src/main/java/datadog/trace/instrumentation/apachehttpclient5/TraceContinuedFutureCallback.java +++ b/dd-java-agent/instrumentation/apache-httpclient-5/src/main/java/datadog/trace/instrumentation/apachehttpclient5/TraceContinuedFutureCallback.java @@ -1,7 +1,6 @@ package datadog.trace.instrumentation.apachehttpclient5; import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.noopContinuation; -import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.setAsyncPropagationEnabled; import static datadog.trace.instrumentation.apachehttpclient5.ApacheHttpClientDecorator.DECORATE; import datadog.trace.bootstrap.instrumentation.api.AgentScope; @@ -40,7 +39,6 @@ public void completed(final T result) { completeDelegate(result); } else { try (final AgentScope scope = parentContinuation.activate()) { - setAsyncPropagationEnabled(true); completeDelegate(result); } } @@ -57,7 +55,6 @@ public void failed(final Exception ex) { failDelegate(ex); } else { try (final AgentScope scope = parentContinuation.activate()) { - setAsyncPropagationEnabled(true); failDelegate(ex); } } @@ -73,7 +70,6 @@ public void cancelled() { cancelDelegate(); } else { try (final AgentScope scope = parentContinuation.activate()) { - setAsyncPropagationEnabled(true); cancelDelegate(); } } diff --git a/dd-java-agent/instrumentation/java-concurrent/java-completablefuture/src/test/groovy/CompletableFutureTest.groovy b/dd-java-agent/instrumentation/java-concurrent/java-completablefuture/src/test/groovy/CompletableFutureTest.groovy index 8a9fef5ba9b..0bc84a10f68 100644 --- a/dd-java-agent/instrumentation/java-concurrent/java-completablefuture/src/test/groovy/CompletableFutureTest.groovy +++ b/dd-java-agent/instrumentation/java-concurrent/java-completablefuture/src/test/groovy/CompletableFutureTest.groovy @@ -11,7 +11,6 @@ import java.util.function.Supplier import static datadog.trace.agent.test.utils.TraceUtils.basicSpan import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace -import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.setAsyncPropagationEnabled /** * Note: ideally this should live with the rest of ExecutorInstrumentationTest, @@ -45,7 +44,6 @@ class CompletableFutureTest extends AgentTestRunner { @Trace(operationName = "parent") CompletableFuture get() { try { - setAsyncPropagationEnabled(true) return CompletableFuture.supplyAsync(supplier, pool) .thenCompose({ s -> CompletableFuture.supplyAsync(new AppendingSupplier(s), differentPool) }) .thenApply(function) diff --git a/dd-java-agent/instrumentation/java-concurrent/java-concurrent-21/src/test/groovy/VirtualThreadTest.groovy b/dd-java-agent/instrumentation/java-concurrent/java-concurrent-21/src/test/groovy/VirtualThreadTest.groovy index 5af16c14857..ccd652dfc81 100644 --- a/dd-java-agent/instrumentation/java-concurrent/java-concurrent-21/src/test/groovy/VirtualThreadTest.groovy +++ b/dd-java-agent/instrumentation/java-concurrent/java-concurrent-21/src/test/groovy/VirtualThreadTest.groovy @@ -8,8 +8,6 @@ import java.util.concurrent.ExecutorCompletionService import java.util.concurrent.Executors import java.util.concurrent.TimeUnit -import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.setAsyncPropagationEnabled - class VirtualThreadTest extends AgentTestRunner { @Shared def executeRunnable = { e, c -> e.execute((Runnable) c) } @@ -37,7 +35,6 @@ class VirtualThreadTest extends AgentTestRunner { @Override @Trace(operationName = "parent") void run() { - setAsyncPropagationEnabled(true) // this child will have a span m(pool, new JavaAsyncChild()) // this child won't diff --git a/dd-java-agent/instrumentation/java-concurrent/src/test/groovy/executor/ExecutorInstrumentationTest.groovy b/dd-java-agent/instrumentation/java-concurrent/src/test/groovy/executor/ExecutorInstrumentationTest.groovy index 097576b0a89..3bf19d6d862 100644 --- a/dd-java-agent/instrumentation/java-concurrent/src/test/groovy/executor/ExecutorInstrumentationTest.groovy +++ b/dd-java-agent/instrumentation/java-concurrent/src/test/groovy/executor/ExecutorInstrumentationTest.groovy @@ -26,7 +26,6 @@ import java.util.concurrent.ScheduledThreadPoolExecutor import java.util.concurrent.ThreadPoolExecutor import java.util.concurrent.TimeUnit -import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.setAsyncPropagationEnabled import static org.junit.Assume.assumeTrue abstract class ExecutorInstrumentationTest extends AgentTestRunner { @@ -82,7 +81,6 @@ abstract class ExecutorInstrumentationTest extends AgentTestRunner { @Override @Trace(operationName = "parent") void run() { - setAsyncPropagationEnabled(true) // this child will have a span m(pool, new JavaAsyncChild()) // this child won't @@ -256,7 +254,6 @@ abstract class ExecutorInstrumentationTest extends AgentTestRunner { @Override @Trace(operationName = "parent") void run() { - setAsyncPropagationEnabled(true) def future = m(pool, task) sleep(500) future.cancel(true) @@ -317,7 +314,6 @@ abstract class ExecutorInstrumentationTest extends AgentTestRunner { @Override @Trace(operationName = "parent") void run() { - setAsyncPropagationEnabled(true) // this child will have a span pool.execute(new JavaAsyncChild()) // this child won't @@ -368,7 +364,6 @@ abstract class ExecutorInstrumentationTest extends AgentTestRunner { @Override @Trace(operationName = "parent") void run() { - setAsyncPropagationEnabled(true) m(pool, w(child)) } }.run() @@ -406,7 +401,6 @@ abstract class ExecutorInstrumentationTest extends AgentTestRunner { @Override @Trace(operationName = "parent") void run() { - setAsyncPropagationEnabled(true) try { for (int i = 0; i < 20; ++i) { final JavaAsyncChild child = new JavaAsyncChild(false, true) diff --git a/dd-java-agent/instrumentation/java-concurrent/src/test/groovy/executor/NettyExecutorInstrumentationTest.groovy b/dd-java-agent/instrumentation/java-concurrent/src/test/groovy/executor/NettyExecutorInstrumentationTest.groovy index c19ee144802..229448626e6 100644 --- a/dd-java-agent/instrumentation/java-concurrent/src/test/groovy/executor/NettyExecutorInstrumentationTest.groovy +++ b/dd-java-agent/instrumentation/java-concurrent/src/test/groovy/executor/NettyExecutorInstrumentationTest.groovy @@ -17,7 +17,6 @@ import java.util.concurrent.Future import java.util.concurrent.RejectedExecutionException import java.util.concurrent.TimeUnit -import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.setAsyncPropagationEnabled import static org.junit.Assume.assumeTrue class NettyExecutorInstrumentationTest extends AgentTestRunner { @@ -65,7 +64,6 @@ class NettyExecutorInstrumentationTest extends AgentTestRunner { @Override @Trace(operationName = "parent") void run() { - setAsyncPropagationEnabled(true) // this child will have a span m(pool, new JavaAsyncChild()) // this child won't @@ -213,7 +211,6 @@ class NettyExecutorInstrumentationTest extends AgentTestRunner { @Override @Trace(operationName = "parent") void run() { - setAsyncPropagationEnabled(true) try { for (int i = 0; i < 20; ++i) { final JavaAsyncChild child = new JavaAsyncChild(false, true) diff --git a/dd-java-agent/instrumentation/java-concurrent/src/test/groovy/executor/RejectedExecutionTest.groovy b/dd-java-agent/instrumentation/java-concurrent/src/test/groovy/executor/RejectedExecutionTest.groovy index dbe34a6eace..74b62a4c364 100644 --- a/dd-java-agent/instrumentation/java-concurrent/src/test/groovy/executor/RejectedExecutionTest.groovy +++ b/dd-java-agent/instrumentation/java-concurrent/src/test/groovy/executor/RejectedExecutionTest.groovy @@ -21,7 +21,6 @@ import java.util.concurrent.ThreadPoolExecutor import java.util.concurrent.TimeUnit import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace -import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.setAsyncPropagationEnabled class RejectedExecutionTest extends AgentTestRunner { @@ -193,7 +192,6 @@ class RejectedExecutionTest extends AgentTestRunner { when: runUnderTrace("parent") { - setAsyncPropagationEnabled(true) // must be rejected because the queue will be full until some // time after the first task is released executor.submit((Runnable) new JavaAsyncChild(true, false)) @@ -237,7 +235,6 @@ class RejectedExecutionTest extends AgentTestRunner { return { runUnderTrace("parent") { - setAsyncPropagationEnabled(true) pool.submit({}) } } @@ -261,7 +258,6 @@ class RejectedExecutionTest extends AgentTestRunner { return { runUnderTrace("parent") { - setAsyncPropagationEnabled(true) // must be rejected because the queue will be full until some // time after the first task is released def testTask = new JavaAsyncChild(true, false) diff --git a/dd-java-agent/instrumentation/jetty-util/src/test/groovy/JettyExecutorInstrumentationTest.groovy b/dd-java-agent/instrumentation/jetty-util/src/test/groovy/JettyExecutorInstrumentationTest.groovy index 0739cc949cc..93c5143873b 100644 --- a/dd-java-agent/instrumentation/jetty-util/src/test/groovy/JettyExecutorInstrumentationTest.groovy +++ b/dd-java-agent/instrumentation/jetty-util/src/test/groovy/JettyExecutorInstrumentationTest.groovy @@ -10,7 +10,6 @@ import java.util.concurrent.Callable import java.util.concurrent.ExecutorService import java.util.concurrent.Executors -import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.setAsyncPropagationEnabled import static org.junit.Assume.assumeTrue class JettyExecutorInstrumentationTest extends AgentTestRunner { @@ -46,7 +45,6 @@ class JettyExecutorInstrumentationTest extends AgentTestRunner { @Override @Trace(operationName = "parent") void run() { - setAsyncPropagationEnabled(true) // this child will have a span m(pool, new JavaAsyncChild()) // this child won't diff --git a/dd-java-agent/instrumentation/opentelemetry/opentelemetry-0.3/src/test/groovy/OpenTelemetryTest.groovy b/dd-java-agent/instrumentation/opentelemetry/opentelemetry-0.3/src/test/groovy/OpenTelemetryTest.groovy index 73265f565dd..8e6e50527e8 100644 --- a/dd-java-agent/instrumentation/opentelemetry/opentelemetry-0.3/src/test/groovy/OpenTelemetryTest.groovy +++ b/dd-java-agent/instrumentation/opentelemetry/opentelemetry-0.3/src/test/groovy/OpenTelemetryTest.groovy @@ -19,8 +19,6 @@ import io.opentelemetry.trace.Status import io.opentelemetry.trace.TracingContextUtils import spock.lang.Subject -import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.setAsyncPropagationEnabled - class OpenTelemetryTest extends AgentTestRunner { @Subject def tracer = OpenTelemetry.tracerProvider.get("test-inst") @@ -234,7 +232,6 @@ class OpenTelemetryTest extends AgentTestRunner { setup: def span = tracer.spanBuilder("some name").startSpan() TraceScope scope = tracer.withSpan(span) - setAsyncPropagationEnabled(true) expect: tracer.currentSpan.delegate == span.delegate diff --git a/dd-java-agent/instrumentation/opentracing/api-0.31/src/test/groovy/OpenTracing31Test.groovy b/dd-java-agent/instrumentation/opentracing/api-0.31/src/test/groovy/OpenTracing31Test.groovy index bfa1f5fe9c8..4671338e56f 100644 --- a/dd-java-agent/instrumentation/opentracing/api-0.31/src/test/groovy/OpenTracing31Test.groovy +++ b/dd-java-agent/instrumentation/opentracing/api-0.31/src/test/groovy/OpenTracing31Test.groovy @@ -219,7 +219,6 @@ class OpenTracing31Test extends AgentTestRunner { setup: def span = tracer.buildSpan("some name").start() TraceScope scope = tracer.scopeManager().activate(span, false) - setAsyncPropagationEnabled(true) expect: tracer.activeSpan().delegate == span.delegate diff --git a/dd-java-agent/instrumentation/opentracing/api-0.32/src/test/groovy/OpenTracing32Test.groovy b/dd-java-agent/instrumentation/opentracing/api-0.32/src/test/groovy/OpenTracing32Test.groovy index 432a44ade2c..bb815ca9153 100644 --- a/dd-java-agent/instrumentation/opentracing/api-0.32/src/test/groovy/OpenTracing32Test.groovy +++ b/dd-java-agent/instrumentation/opentracing/api-0.32/src/test/groovy/OpenTracing32Test.groovy @@ -234,7 +234,6 @@ class OpenTracing32Test extends AgentTestRunner { setup: def span = tracer.buildSpan("some name").start() TraceScope scope = tracer.scopeManager().activate(span, false) - setAsyncPropagationEnabled(true) expect: tracer.activeSpan().delegate == span.delegate diff --git a/dd-java-agent/instrumentation/play-2.3/src/main/java/datadog/trace/instrumentation/play23/RequestCompleteCallback.java b/dd-java-agent/instrumentation/play-2.3/src/main/java/datadog/trace/instrumentation/play23/RequestCompleteCallback.java index 2433837ba51..68b56de4ddb 100644 --- a/dd-java-agent/instrumentation/play-2.3/src/main/java/datadog/trace/instrumentation/play23/RequestCompleteCallback.java +++ b/dd-java-agent/instrumentation/play-2.3/src/main/java/datadog/trace/instrumentation/play23/RequestCompleteCallback.java @@ -1,6 +1,5 @@ package datadog.trace.instrumentation.play23; -import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.setAsyncPropagationEnabled; import static datadog.trace.instrumentation.play23.PlayHttpServerDecorator.DECORATE; import static datadog.trace.instrumentation.play23.PlayHttpServerDecorator.REPORT_HTTP_STATUS; @@ -30,7 +29,6 @@ public Object apply(final Try result) { } } DECORATE.beforeFinish(span); - setAsyncPropagationEnabled(false); } catch (final Throwable t) { log.debug("error in play instrumentation", t); } finally { diff --git a/dd-java-agent/instrumentation/play-2.4/src/main/java/datadog/trace/instrumentation/play24/RequestCompleteCallback.java b/dd-java-agent/instrumentation/play-2.4/src/main/java/datadog/trace/instrumentation/play24/RequestCompleteCallback.java index 4ec90a2b1c9..7841c6c4977 100644 --- a/dd-java-agent/instrumentation/play-2.4/src/main/java/datadog/trace/instrumentation/play24/RequestCompleteCallback.java +++ b/dd-java-agent/instrumentation/play-2.4/src/main/java/datadog/trace/instrumentation/play24/RequestCompleteCallback.java @@ -1,6 +1,5 @@ package datadog.trace.instrumentation.play24; -import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.setAsyncPropagationEnabled; import static datadog.trace.instrumentation.play24.PlayHttpServerDecorator.DECORATE; import static datadog.trace.instrumentation.play24.PlayHttpServerDecorator.REPORT_HTTP_STATUS; @@ -29,7 +28,6 @@ public Object apply(final Try result) { } } DECORATE.beforeFinish(span); - setAsyncPropagationEnabled(false); } catch (final Throwable t) { log.debug("error in play instrumentation", t); } finally { diff --git a/dd-java-agent/instrumentation/play-2.6/src/main/java/datadog/trace/instrumentation/play26/RequestCompleteCallback.java b/dd-java-agent/instrumentation/play-2.6/src/main/java/datadog/trace/instrumentation/play26/RequestCompleteCallback.java index 2558071bf37..2c3ccc82fee 100644 --- a/dd-java-agent/instrumentation/play-2.6/src/main/java/datadog/trace/instrumentation/play26/RequestCompleteCallback.java +++ b/dd-java-agent/instrumentation/play-2.6/src/main/java/datadog/trace/instrumentation/play26/RequestCompleteCallback.java @@ -1,6 +1,5 @@ package datadog.trace.instrumentation.play26; -import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.setAsyncPropagationEnabled; import static datadog.trace.instrumentation.play26.PlayHttpServerDecorator.DECORATE; import static datadog.trace.instrumentation.play26.PlayHttpServerDecorator.REPORT_HTTP_STATUS; @@ -31,7 +30,6 @@ public Object apply(final Try result) { } } DECORATE.beforeFinish(span); - setAsyncPropagationEnabled(false); } catch (final Throwable t) { log.debug("error in play instrumentation", t); } finally { diff --git a/dd-java-agent/instrumentation/play-ws-1/src/main/java/datadog/trace/instrumentation/playws1/AsyncHandlerWrapper.java b/dd-java-agent/instrumentation/play-ws-1/src/main/java/datadog/trace/instrumentation/playws1/AsyncHandlerWrapper.java index f2069730d4a..27502d6d1e4 100644 --- a/dd-java-agent/instrumentation/play-ws-1/src/main/java/datadog/trace/instrumentation/playws1/AsyncHandlerWrapper.java +++ b/dd-java-agent/instrumentation/play-ws-1/src/main/java/datadog/trace/instrumentation/playws1/AsyncHandlerWrapper.java @@ -1,7 +1,6 @@ package datadog.trace.instrumentation.playws1; import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.captureSpan; -import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.setAsyncPropagationEnabled; import static datadog.trace.instrumentation.playws.PlayWSClientDecorator.DECORATE; import datadog.trace.bootstrap.instrumentation.api.AgentScope; @@ -55,7 +54,6 @@ public Object onCompleted() throws Exception { if (continuation != null) { try (final AgentScope scope = continuation.activate()) { - setAsyncPropagationEnabled(true); return delegate.onCompleted(); } } else { @@ -71,7 +69,6 @@ public void onThrowable(final Throwable throwable) { if (continuation != null) { try (final AgentScope scope = continuation.activate()) { - setAsyncPropagationEnabled(true); delegate.onThrowable(throwable); } } else { diff --git a/dd-java-agent/instrumentation/play-ws-2.1/src/main/java/datadog/trace/instrumentation/playws21/AsyncHandlerWrapper.java b/dd-java-agent/instrumentation/play-ws-2.1/src/main/java/datadog/trace/instrumentation/playws21/AsyncHandlerWrapper.java index a2cc9ca949c..b442f327c0b 100644 --- a/dd-java-agent/instrumentation/play-ws-2.1/src/main/java/datadog/trace/instrumentation/playws21/AsyncHandlerWrapper.java +++ b/dd-java-agent/instrumentation/play-ws-2.1/src/main/java/datadog/trace/instrumentation/playws21/AsyncHandlerWrapper.java @@ -1,7 +1,6 @@ package datadog.trace.instrumentation.playws21; import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.captureSpan; -import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.setAsyncPropagationEnabled; import static datadog.trace.instrumentation.playws.PlayWSClientDecorator.DECORATE; import datadog.trace.bootstrap.instrumentation.api.AgentScope; @@ -60,7 +59,6 @@ public Object onCompleted() throws Exception { if (continuation != null) { try (final AgentScope scope = continuation.activate()) { - setAsyncPropagationEnabled(true); return delegate.onCompleted(); } } else { @@ -76,7 +74,6 @@ public void onThrowable(final Throwable throwable) { if (continuation != null) { try (final AgentScope scope = continuation.activate()) { - setAsyncPropagationEnabled(true); delegate.onThrowable(throwable); } } else { diff --git a/dd-java-agent/instrumentation/play-ws-2/src/main/java/datadog/trace/instrumentation/playws2/AsyncHandlerWrapper.java b/dd-java-agent/instrumentation/play-ws-2/src/main/java/datadog/trace/instrumentation/playws2/AsyncHandlerWrapper.java index 1aef9e3b264..3572424749e 100644 --- a/dd-java-agent/instrumentation/play-ws-2/src/main/java/datadog/trace/instrumentation/playws2/AsyncHandlerWrapper.java +++ b/dd-java-agent/instrumentation/play-ws-2/src/main/java/datadog/trace/instrumentation/playws2/AsyncHandlerWrapper.java @@ -1,7 +1,6 @@ package datadog.trace.instrumentation.playws2; import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.captureSpan; -import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.setAsyncPropagationEnabled; import static datadog.trace.instrumentation.playws.PlayWSClientDecorator.DECORATE; import datadog.trace.bootstrap.instrumentation.api.AgentScope; @@ -59,7 +58,6 @@ public Object onCompleted() throws Exception { if (continuation != null) { try (final AgentScope scope = continuation.activate()) { - setAsyncPropagationEnabled(true); return delegate.onCompleted(); } } else { @@ -75,7 +73,6 @@ public void onThrowable(final Throwable throwable) { if (continuation != null) { try (final AgentScope scope = continuation.activate()) { - setAsyncPropagationEnabled(true); delegate.onThrowable(throwable); } } else { diff --git a/dd-java-agent/instrumentation/scala-concurrent/src/test/groovy/ScalaExecutorInstrumentationTest.groovy b/dd-java-agent/instrumentation/scala-concurrent/src/test/groovy/ScalaExecutorInstrumentationTest.groovy index a5a88157224..b26d8450823 100644 --- a/dd-java-agent/instrumentation/scala-concurrent/src/test/groovy/ScalaExecutorInstrumentationTest.groovy +++ b/dd-java-agent/instrumentation/scala-concurrent/src/test/groovy/ScalaExecutorInstrumentationTest.groovy @@ -13,8 +13,6 @@ import java.util.concurrent.RejectedExecutionException import java.util.concurrent.ThreadPoolExecutor import java.util.concurrent.TimeUnit -import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.setAsyncPropagationEnabled - /** * Test executor instrumentation for Scala specific classes. * This is to large extent a copy of ExecutorInstrumentationTest. @@ -43,7 +41,6 @@ class ScalaExecutorInstrumentationTest extends AgentTestRunner { @Override @Trace(operationName = "parent") void run() { - setAsyncPropagationEnabled(true) // this child will have a span m(pool, new ScalaAsyncChild()) // this child won't @@ -94,7 +91,6 @@ class ScalaExecutorInstrumentationTest extends AgentTestRunner { @Override @Trace(operationName = "parent") void run() { - setAsyncPropagationEnabled(true) try { for (int i = 0; i < 20; ++i) { // Our current instrumentation instrumentation does not behave very well diff --git a/dd-java-agent/instrumentation/servlet/request-2/src/main/java/datadog/trace/instrumentation/servlet2/Servlet2Advice.java b/dd-java-agent/instrumentation/servlet/request-2/src/main/java/datadog/trace/instrumentation/servlet2/Servlet2Advice.java index 84d85e8447f..27797f8ba8f 100644 --- a/dd-java-agent/instrumentation/servlet/request-2/src/main/java/datadog/trace/instrumentation/servlet2/Servlet2Advice.java +++ b/dd-java-agent/instrumentation/servlet/request-2/src/main/java/datadog/trace/instrumentation/servlet2/Servlet2Advice.java @@ -1,7 +1,6 @@ package datadog.trace.instrumentation.servlet2; import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activateSpan; -import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.setAsyncPropagationEnabled; import static datadog.trace.bootstrap.instrumentation.decorator.HttpServerDecorator.DD_SPAN_ATTRIBUTE; import static datadog.trace.instrumentation.servlet2.Servlet2Decorator.DECORATE; @@ -119,7 +118,6 @@ public static void stopSpan( } DECORATE.beforeFinish(span); - setAsyncPropagationEnabled(false); scope.close(); span.finish(); } diff --git a/dd-java-agent/instrumentation/spring-scheduling-3.1/src/main/java/datadog/trace/instrumentation/springscheduling/SpannedMethodInvocation.java b/dd-java-agent/instrumentation/spring-scheduling-3.1/src/main/java/datadog/trace/instrumentation/springscheduling/SpannedMethodInvocation.java index 0200eba5439..26c81fdf74d 100644 --- a/dd-java-agent/instrumentation/spring-scheduling-3.1/src/main/java/datadog/trace/instrumentation/springscheduling/SpannedMethodInvocation.java +++ b/dd-java-agent/instrumentation/spring-scheduling-3.1/src/main/java/datadog/trace/instrumentation/springscheduling/SpannedMethodInvocation.java @@ -2,7 +2,6 @@ import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activateSpan; import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.noopContinuation; -import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.setAsyncPropagationEnabled; import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.startSpan; import static datadog.trace.instrumentation.springscheduling.SpringSchedulingDecorator.DECORATE; @@ -44,7 +43,6 @@ public Object proceed() throws Throwable { private Object invokeWithContinuation(CharSequence spanName) throws Throwable { try (AgentScope scope = continuation.activate()) { - setAsyncPropagationEnabled(true); return invokeWithSpan(spanName); } } diff --git a/dd-trace-core/src/test/groovy/datadog/trace/core/PendingTraceStrictWriteTest.groovy b/dd-trace-core/src/test/groovy/datadog/trace/core/PendingTraceStrictWriteTest.groovy index f0ae901551f..13850ab95ef 100644 --- a/dd-trace-core/src/test/groovy/datadog/trace/core/PendingTraceStrictWriteTest.groovy +++ b/dd-trace-core/src/test/groovy/datadog/trace/core/PendingTraceStrictWriteTest.groovy @@ -1,13 +1,10 @@ package datadog.trace.core -import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.setAsyncPropagationEnabled - class PendingTraceStrictWriteTest extends PendingTraceTestBase { def "trace is not reported until unfinished continuation is closed"() { when: def scope = tracer.activateSpan(rootSpan) - setAsyncPropagationEnabled(true) def continuation = tracer.captureActiveSpan() scope.close() rootSpan.finish() @@ -39,7 +36,6 @@ class PendingTraceStrictWriteTest extends PendingTraceTestBase { def "negative reference count throws an exception"() { when: def scope = tracer.activateSpan(rootSpan) - setAsyncPropagationEnabled(true) def continuation = tracer.captureActiveSpan() scope.close() rootSpan.finish() diff --git a/dd-trace-core/src/test/groovy/datadog/trace/core/PendingTraceTest.groovy b/dd-trace-core/src/test/groovy/datadog/trace/core/PendingTraceTest.groovy index 51b144f3c84..f182585b79e 100644 --- a/dd-trace-core/src/test/groovy/datadog/trace/core/PendingTraceTest.groovy +++ b/dd-trace-core/src/test/groovy/datadog/trace/core/PendingTraceTest.groovy @@ -10,8 +10,6 @@ import spock.lang.Timeout import java.util.concurrent.TimeUnit -import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.setAsyncPropagationEnabled - class PendingTraceTest extends PendingTraceTestBase { @Override @@ -51,7 +49,6 @@ class PendingTraceTest extends PendingTraceTestBase { def "trace is still reported when unfinished continuation discarded"() { when: def scope = tracer.activateSpan(rootSpan) - setAsyncPropagationEnabled(true) tracer.captureActiveSpan() scope.close() rootSpan.finish() diff --git a/dd-trace-core/src/test/groovy/datadog/trace/core/scopemanager/ScopeManagerTest.groovy b/dd-trace-core/src/test/groovy/datadog/trace/core/scopemanager/ScopeManagerTest.groovy index 4f0f8dfe3a3..819783d2ae7 100644 --- a/dd-trace-core/src/test/groovy/datadog/trace/core/scopemanager/ScopeManagerTest.groovy +++ b/dd-trace-core/src/test/groovy/datadog/trace/core/scopemanager/ScopeManagerTest.groovy @@ -275,7 +275,6 @@ class ScopeManagerTest extends DDCoreSpecification { when: def span = tracer.buildSpan("test", "test").start() def scope = tracer.activateSpan(span) - tracer.setAsyncPropagationEnabled(true) def continuation = tracer.captureActiveSpan() then: @@ -293,7 +292,6 @@ class ScopeManagerTest extends DDCoreSpecification { when: def span = tracer.buildSpan("test", "test").start() def scopeRef = new AtomicReference(tracer.activateSpan(span)) - tracer.setAsyncPropagationEnabled(true) def continuation = tracer.captureActiveSpan() then: @@ -321,7 +319,6 @@ class ScopeManagerTest extends DDCoreSpecification { when: def span = tracer.buildSpan("test", "test").start() def scope = tracer.activateSpan(span) - tracer.setAsyncPropagationEnabled(true) def continuation = tracer.captureActiveSpan() then: @@ -354,7 +351,6 @@ class ScopeManagerTest extends DDCoreSpecification { def parentScope = tracer.activateSpan(parentSpan) def childSpan = tracer.buildSpan("test", "child").start() def childScope = tracer.activateSpan(childSpan) - tracer.setAsyncPropagationEnabled(true) def continuation = tracer.captureActiveSpan() childScope.close() @@ -408,7 +404,6 @@ class ScopeManagerTest extends DDCoreSpecification { when: "creating and activating a continuation" def span = tracer.buildSpan("test", "test").start() def scope = tracer.activateSpan(span) - tracer.setAsyncPropagationEnabled(true) def continuation = tracer.captureActiveSpan() scope.close() span.finish() @@ -694,7 +689,6 @@ class ScopeManagerTest extends DDCoreSpecification { when: def span = tracer.buildSpan("test", "test").start() def scope = tracer.activateSpan(span) - tracer.setAsyncPropagationEnabled(true) def continuation = tracer.captureActiveSpan() scope.close() span.finish() @@ -777,7 +771,6 @@ class ScopeManagerTest extends DDCoreSpecification { when: def span = tracer.buildSpan("test", "test").start() def scope = tracer.activateSpan(span) - tracer.setAsyncPropagationEnabled(true) def continuation = tracer.captureActiveSpan() scope.close() span.finish() @@ -804,7 +797,6 @@ class ScopeManagerTest extends DDCoreSpecification { when: "completing another async scope lifecycle" def span2 = tracer.buildSpan("test", "test").start() def scope2 = tracer.activateSpan(span2) - tracer.setAsyncPropagationEnabled(true) def continuation2 = tracer.captureActiveSpan() then: @@ -839,7 +831,6 @@ class ScopeManagerTest extends DDCoreSpecification { def span = tracer.buildSpan("test", "test").start() def start = System.nanoTime() def scope = (ContinuableScope) tracer.activateSpan(span) - tracer.setAsyncPropagationEnabled(true) continuation = tracer.captureActiveSpan() scope.close() span.finish() From 26c11f47969fcac85e4a57840e2fff5cc784e97e Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Thu, 13 Mar 2025 18:19:57 +0000 Subject: [PATCH 35/98] Be consistent when deciding when to do async propagation (#8555) i.e. we should have a non-null, valid span and the async propagation flag should be set (also remove some unused variables in the executor advice) --- .../instrumentation/java/concurrent/AdviceUtils.java | 2 +- .../concurrent/ExecutorInstrumentationUtils.java | 12 ++++-------- .../guava10/ListenableFutureInstrumentation.java | 11 ++++------- .../executor/JavaExecutorInstrumentation.java | 10 +++------- .../trace/instrumentation/scala/PromiseHelper.java | 2 +- 5 files changed, 13 insertions(+), 24 deletions(-) diff --git a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/java/concurrent/AdviceUtils.java b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/java/concurrent/AdviceUtils.java index c347de48aae..b6d4ebe4f6b 100644 --- a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/java/concurrent/AdviceUtils.java +++ b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/java/concurrent/AdviceUtils.java @@ -52,7 +52,7 @@ public static void cancelTask(ContextStore contextStore, final T t public static void capture(ContextStore contextStore, T task) { AgentSpan span = activeSpan(); - if (span != null && isAsyncPropagationEnabled()) { + if (span != null && span.isValid() && isAsyncPropagationEnabled()) { State state = contextStore.get(task); if (null == state) { state = State.FACTORY.create(); diff --git a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/java/concurrent/ExecutorInstrumentationUtils.java b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/java/concurrent/ExecutorInstrumentationUtils.java index 9b89e6c55c7..e6fa74b1d70 100644 --- a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/java/concurrent/ExecutorInstrumentationUtils.java +++ b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/java/concurrent/ExecutorInstrumentationUtils.java @@ -1,12 +1,10 @@ package datadog.trace.bootstrap.instrumentation.java.concurrent; -import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activeSpan; import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.isAsyncPropagationEnabled; import static datadog.trace.bootstrap.instrumentation.java.concurrent.ExcludeFilter.ExcludeType; import datadog.trace.bootstrap.ContextStore; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; -import java.util.concurrent.Executor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -19,17 +17,17 @@ public final class ExecutorInstrumentationUtils { * Checks if given task should get state attached. * * @param task task object - * @param executor executor this task was scheduled on + * @param span active span * @return true iff given task object should be wrapped */ - public static boolean shouldAttachStateToTask(final Object task, final Executor executor) { + public static boolean shouldAttachStateToTask(final Object task, final AgentSpan span) { if (task == null) { return false; } if (ExcludeFilter.exclude(ExcludeType.EXECUTOR, task)) { return false; } - return activeSpan() != null && isAsyncPropagationEnabled(); + return span != null && span.isValid() && isAsyncPropagationEnabled(); } /** @@ -57,12 +55,10 @@ public static State setupState( /** * Clean up after job submission method has exited. * - * @param executor the current executor * @param state task instrumentation state * @param throwable throwable that may have been thrown */ - public static void cleanUpOnMethodExit( - final Executor executor, final State state, final Throwable throwable) { + public static void cleanUpOnMethodExit(final State state, final Throwable throwable) { if (null != state && null != throwable) { /* Note: this may potentially close somebody else's continuation if we didn't set it diff --git a/dd-java-agent/instrumentation/guava-10/src/main/java/datadog/trace/instrumentation/guava10/ListenableFutureInstrumentation.java b/dd-java-agent/instrumentation/guava-10/src/main/java/datadog/trace/instrumentation/guava10/ListenableFutureInstrumentation.java index 8c2f8633ed4..b19d52591a2 100644 --- a/dd-java-agent/instrumentation/guava-10/src/main/java/datadog/trace/instrumentation/guava10/ListenableFutureInstrumentation.java +++ b/dd-java-agent/instrumentation/guava-10/src/main/java/datadog/trace/instrumentation/guava10/ListenableFutureInstrumentation.java @@ -54,14 +54,13 @@ public void methodAdvice(MethodTransformer transformer) { public static class AddListenerAdvice { @Advice.OnMethodEnter(suppress = Throwable.class) public static State addListenerEnter( - @Advice.Argument(value = 0, readOnly = false) Runnable task, - @Advice.Argument(1) final Executor executor) { + @Advice.Argument(value = 0, readOnly = false) Runnable task) { final AgentSpan span = activeSpan(); if (null != span) { final Runnable newTask = RunnableWrapper.wrapIfNeeded(task); // It is important to check potentially wrapped task if we can instrument task in this // executor. Some executors do not support wrapped tasks. - if (ExecutorInstrumentationUtils.shouldAttachStateToTask(newTask, executor)) { + if (ExecutorInstrumentationUtils.shouldAttachStateToTask(newTask, span)) { task = newTask; final ContextStore contextStore = InstrumentationContext.get(Runnable.class, State.class); @@ -73,10 +72,8 @@ public static State addListenerEnter( @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void addListenerExit( - @Advice.Argument(1) final Executor executor, - @Advice.Enter final State state, - @Advice.Thrown final Throwable throwable) { - ExecutorInstrumentationUtils.cleanUpOnMethodExit(executor, state, throwable); + @Advice.Enter final State state, @Advice.Thrown final Throwable throwable) { + ExecutorInstrumentationUtils.cleanUpOnMethodExit(state, throwable); } private static void muzzleCheck(final AbstractFuture future) { diff --git a/dd-java-agent/instrumentation/java-concurrent/src/main/java/datadog/trace/instrumentation/java/concurrent/executor/JavaExecutorInstrumentation.java b/dd-java-agent/instrumentation/java-concurrent/src/main/java/datadog/trace/instrumentation/java/concurrent/executor/JavaExecutorInstrumentation.java index 5de5c588d7e..4634c23dc9a 100644 --- a/dd-java-agent/instrumentation/java-concurrent/src/main/java/datadog/trace/instrumentation/java/concurrent/executor/JavaExecutorInstrumentation.java +++ b/dd-java-agent/instrumentation/java-concurrent/src/main/java/datadog/trace/instrumentation/java/concurrent/executor/JavaExecutorInstrumentation.java @@ -15,7 +15,6 @@ import datadog.trace.bootstrap.instrumentation.java.concurrent.State; import java.util.Collections; import java.util.Map; -import java.util.concurrent.Executor; import java.util.concurrent.RunnableFuture; import net.bytebuddy.asm.Advice; @@ -38,7 +37,6 @@ public static class SetExecuteRunnableStateAdvice { @Advice.OnMethodEnter(suppress = Throwable.class) public static State enterJobSubmit( - @Advice.This final Executor executor, @Advice.Argument(value = 0, readOnly = false) Runnable task) { if (task instanceof RunnableFuture) { return null; @@ -51,7 +49,7 @@ public static State enterJobSubmit( final Runnable newTask = RunnableWrapper.wrapIfNeeded(task); // It is important to check potentially wrapped task if we can instrument task in this // executor. Some executors do not support wrapped tasks. - if (ExecutorInstrumentationUtils.shouldAttachStateToTask(newTask, executor)) { + if (ExecutorInstrumentationUtils.shouldAttachStateToTask(newTask, span)) { task = newTask; final ContextStore contextStore = InstrumentationContext.get(Runnable.class, State.class); @@ -63,10 +61,8 @@ public static State enterJobSubmit( @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void exitJobSubmit( - @Advice.This final Executor executor, - @Advice.Enter final State state, - @Advice.Thrown final Throwable throwable) { - ExecutorInstrumentationUtils.cleanUpOnMethodExit(executor, state, throwable); + @Advice.Enter final State state, @Advice.Thrown final Throwable throwable) { + ExecutorInstrumentationUtils.cleanUpOnMethodExit(state, throwable); } } } diff --git a/dd-java-agent/instrumentation/scala-promise/src/main/java/datadog/trace/instrumentation/scala/PromiseHelper.java b/dd-java-agent/instrumentation/scala-promise/src/main/java/datadog/trace/instrumentation/scala/PromiseHelper.java index 72ea093f509..60b3e4a3216 100644 --- a/dd-java-agent/instrumentation/scala-promise/src/main/java/datadog/trace/instrumentation/scala/PromiseHelper.java +++ b/dd-java-agent/instrumentation/scala-promise/src/main/java/datadog/trace/instrumentation/scala/PromiseHelper.java @@ -29,7 +29,7 @@ public class PromiseHelper { */ public static AgentSpan getSpan() { final AgentSpan span = activeSpan(); - if (null != span && isAsyncPropagationEnabled()) { + if (null != span && span.isValid() && isAsyncPropagationEnabled()) { return span; } return null; From 3c4876cfb6c3115976291179dc12f70a0e91a178 Mon Sep 17 00:00:00 2001 From: mhlidd Date: Thu, 13 Mar 2025 15:38:39 -0400 Subject: [PATCH 36/98] Add new parser for `DD_TAGS` and prioritizing `DD_SERVICE` (#8296) * testing * cleanup * first iteration on parser * initial working parsing for DD_TAGS * cleanup part 1 * cleanup pt 2 * adding traceTagsParser as separate parser due to different rule * dd_service override * reverting irrelevant changes * cleanup * reverting irrelevant changes * cleanup again * adding edge cases tests and creating specific tags mergedtags function * updating comment for clarity and removing irrelevant args * cleanup * updating DD_TAGS to belong under breaking change flag --- .../main/java/datadog/trace/api/Config.java | 9 ++- .../config/provider/ConfigConverter.java | 70 +++++++++++++++++++ .../config/provider/ConfigProvider.java | 23 ++++++ .../datadog/trace/api/ConfigTest.groovy | 52 ++++++++++++-- .../provider/ConfigConverterTest.groovy | 34 +++++++++ 5 files changed, 182 insertions(+), 6 deletions(-) diff --git a/internal-api/src/main/java/datadog/trace/api/Config.java b/internal-api/src/main/java/datadog/trace/api/Config.java index 240c3b41790..599e96c5cfd 100644 --- a/internal-api/src/main/java/datadog/trace/api/Config.java +++ b/internal-api/src/main/java/datadog/trace/api/Config.java @@ -775,7 +775,14 @@ private Config(final ConfigProvider configProvider, final InstrumenterConfig ins { final Map tags = new HashMap<>(configProvider.getMergedMap(GLOBAL_TAGS)); - tags.putAll(configProvider.getMergedMap(TRACE_TAGS, TAGS)); + if (experimentalFeaturesEnabled.contains("DD_TAGS")) { + tags.putAll(configProvider.getMergedTagsMap(TRACE_TAGS, TAGS)); + } else { + tags.putAll(configProvider.getMergedMap(TRACE_TAGS, TAGS)); + } + if (serviceNameSetByUser) { // prioritize service name set by DD_SERVICE over DD_TAGS config + tags.remove("service"); + } this.tags = getMapWithPropertiesDefinedByEnvironment(tags, ENV, VERSION); } diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/ConfigConverter.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/ConfigConverter.java index 1bd9422087f..98d4af50d3c 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/ConfigConverter.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/ConfigConverter.java @@ -84,6 +84,19 @@ static Map parseMap( return map; } + @Nonnull + static Map parseTraceTagsMap( + final String str, final char keyValueSeparator, final List argSeparators) { + // If we ever want to have default values besides an empty map, this will need to change. + String trimmed = Strings.trim(str); + if (trimmed.isEmpty()) { + return Collections.emptyMap(); + } + Map map = new HashMap<>(); + loadTraceTagsMap(map, trimmed, keyValueSeparator, argSeparators); + return map; + } + /** * This parses a mixed map that can have both key value pairs, and also keys only, that will get * values on the form "defaultPrefix.key". For keys without a value, the corresponding value will @@ -201,6 +214,63 @@ private static void loadMap( } } + private static void loadTraceTagsMap( + Map map, + String str, + char keyValueSeparator, + final List argSeparators) { + int start = 0; + int splitter = str.indexOf(keyValueSeparator, start); + char argSeparator = '\0'; + int argSeparatorInd = -1; + + // Given a list of separators ordered by priority, find the first (highest priority) separator + // that appears in the string and store its value and first occurrence in the string + for (Character sep : argSeparators) { + argSeparatorInd = str.indexOf(sep); + if (argSeparatorInd != -1) { + argSeparator = sep; + break; + } + } + while (start < str.length()) { + int nextSplitter = + argSeparatorInd == -1 + ? -1 + : str.indexOf( + keyValueSeparator, + argSeparatorInd + 1); // next splitter after the next argSeparator + int nextArgSeparator = + argSeparatorInd == -1 ? -1 : str.indexOf(argSeparator, argSeparatorInd + 1); + int end = argSeparatorInd == -1 ? str.length() : argSeparatorInd; + + if (start >= end) { // the character is only the delimiter + start = end + 1; + splitter = nextSplitter; + argSeparatorInd = nextArgSeparator; + continue; + } + + String key, value; + if (splitter >= end + || splitter + == -1) { // only key, no value; either due end of string or substring not having + // splitter + key = str.substring(start, end).trim(); + value = ""; + } else { + key = str.substring(start, splitter).trim(); + value = str.substring(splitter + 1, end).trim(); + } + if (!key.isEmpty()) { + map.put(key, value); + } + splitter = nextSplitter; + argSeparatorInd = nextArgSeparator; + start = end + 1; + } + } + private static void loadMapWithOptionalMapping( Map map, String str, diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/ConfigProvider.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/ConfigProvider.java index 90e43cd30ab..0a2715dd11a 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/ConfigProvider.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/ConfigProvider.java @@ -9,6 +9,7 @@ import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; +import java.util.Arrays; import java.util.BitSet; import java.util.HashMap; import java.util.HashSet; @@ -263,6 +264,28 @@ public Map getMergedMap(String key, String... aliases) { return merged; } + public Map getMergedTagsMap(String key, String... aliases) { + Map merged = new HashMap<>(); + ConfigOrigin origin = ConfigOrigin.DEFAULT; + // System properties take precedence over env + // prior art: + // https://docs.spring.io/spring-boot/docs/1.5.6.RELEASE/reference/html/boot-features-external-config.html + // We reverse iterate to allow overrides + for (int i = sources.length - 1; 0 <= i; i--) { + String value = sources[i].get(key, aliases); + Map parsedMap = + ConfigConverter.parseTraceTagsMap(value, ':', Arrays.asList(',', ' ')); + if (!parsedMap.isEmpty()) { + origin = sources[i].origin(); + } + merged.putAll(parsedMap); + } + if (collectConfig) { + ConfigCollector.get().put(key, merged, origin); + } + return merged; + } + public Map getOrderedMap(String key) { LinkedHashMap merged = new LinkedHashMap<>(); ConfigOrigin origin = ConfigOrigin.DEFAULT; diff --git a/internal-api/src/test/groovy/datadog/trace/api/ConfigTest.groovy b/internal-api/src/test/groovy/datadog/trace/api/ConfigTest.groovy index 1e661867875..f9594ab1165 100644 --- a/internal-api/src/test/groovy/datadog/trace/api/ConfigTest.groovy +++ b/internal-api/src/test/groovy/datadog/trace/api/ConfigTest.groovy @@ -1795,6 +1795,19 @@ class ConfigTest extends DDSpecification { 'service.version': 'my-svc-vers'] } + def "service name prioritizes values from DD_SERVICE over tags"() { + setup: + System.setProperty(PREFIX + TAGS, "service:service-name-from-tags") + System.setProperty(PREFIX + SERVICE, "service-name-from-dd-service") + + when: + def config = new Config() + + then: + config.serviceName == "service-name-from-dd-service" + !config.mergedSpanTags.containsKey("service") + } + def "DD_SERVICE precedence over 'dd.service.name' java property is set; 'dd.service' overwrites DD_SERVICE"() { setup: environmentVariables.set(DD_SERVICE_NAME_ENV, "dd-service-name-env-var") @@ -1808,7 +1821,7 @@ class ConfigTest extends DDSpecification { then: config.serviceName == "dd-service-java-prop" - config.mergedSpanTags == [service: 'service-tag-in-dd-trace-global-tags-java-property', 'service.version': 'my-svc-vers'] + config.mergedSpanTags == ['service.version': 'my-svc-vers'] config.mergedJmxTags == [(RUNTIME_ID_TAG) : config.getRuntimeId(), (SERVICE_TAG): config.serviceName, 'service.version': 'my-svc-vers'] } @@ -1824,7 +1837,7 @@ class ConfigTest extends DDSpecification { then: config.serviceName == "dd-service-env-var" - config.mergedSpanTags == [service: 'service-tag-in-dd-trace-global-tags-java-property', 'service.version': 'my-svc-vers'] + config.mergedSpanTags == ['service.version': 'my-svc-vers'] config.mergedJmxTags == [(RUNTIME_ID_TAG) : config.getRuntimeId(), (SERVICE_TAG): config.serviceName, 'service.version': 'my-svc-vers'] } @@ -1840,12 +1853,12 @@ class ConfigTest extends DDSpecification { then: config.serviceName == "dd-service-java-prop" - config.mergedSpanTags == [service: 'service-tag-in-dd-trace-global-tags-java-property', 'service.version': 'my-svc-vers'] + config.mergedSpanTags == ['service.version': 'my-svc-vers'] config.mergedJmxTags == [(RUNTIME_ID_TAG) : config.getRuntimeId(), (SERVICE_TAG): config.serviceName, 'service.version': 'my-svc-vers'] } - def "set servicenaem by DD_SERVICE"() { + def "set servicename by DD_SERVICE"() { setup: environmentVariables.set("DD_SERVICE", "dd-service-env-var") System.setProperty(PREFIX + GLOBAL_TAGS, "service:service-tag-in-dd-trace-global-tags-java-property,service.version:my-svc-vers") @@ -1856,7 +1869,7 @@ class ConfigTest extends DDSpecification { then: config.serviceName == "dd-service-env-var" - config.mergedSpanTags == [service: 'service-tag-in-dd-trace-global-tags-java-property', 'service.version': 'my-svc-vers'] + config.mergedSpanTags == ['service.version': 'my-svc-vers'] config.mergedJmxTags == [(RUNTIME_ID_TAG) : config.getRuntimeId(), (SERVICE_TAG): config.serviceName, 'service.version': 'my-svc-vers'] } @@ -1876,6 +1889,35 @@ class ConfigTest extends DDSpecification { [serviceProperty, serviceName] << [[SERVICE, SERVICE_NAME], [DEFAULT_SERVICE_NAME, "my-service"]].combinations() } + def "verify behavior of features under DD_TRACE_EXPERIMENTAL_FEATURES_ENABLED"() { + setup: + environmentVariables.set("DD_TRACE_EXPERIMENTAL_FEATURES_ENABLED", "DD_TAGS") + environmentVariables.set("DD_TAGS", "env:test,aKey:aVal bKey:bVal cKey:") + + when: + def config = new Config() + + then: + config.experimentalFeaturesEnabled == ["DD_TAGS"].toSet() + + //verify expected behavior enabled under feature flag + config.globalTags == [env: "test", aKey: "aVal bKey:bVal cKey:"] + } + + def "verify behavior of 'breaking change' configs when not under DD_TRACE_EXPERIMENTAL_FEATURES_ENABLED"() { + setup: + environmentVariables.set("DD_TAGS", "env:test,aKey:aVal bKey:bVal cKey:") + + when: + def config = new Config() + + then: + config.experimentalFeaturesEnabled == [].toSet() + + //verify expected behavior when not enabled under feature flag + config.globalTags == [env:"test", aKey:"aVal", bKey:"bVal"] + } + def "detect if agent is configured using default values"() { setup: if (host != null) { diff --git a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/ConfigConverterTest.groovy b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/ConfigConverterTest.groovy index 36abcf887f8..14a0c2f6ae1 100644 --- a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/ConfigConverterTest.groovy +++ b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/ConfigConverterTest.groovy @@ -99,6 +99,40 @@ class ConfigConverterTest extends DDSpecification { // spotless:on } + def "parsing map #mapString with List of arg separators for with key value separator #separator"() { + //testing parsing for DD_TAGS + setup: + def separatorList = [',' as char, ' ' as char] + + when: + def result = ConfigConverter.parseTraceTagsMap(mapString, separator as char, separatorList as List) + + then: + result == expected + + where: + // spotless:off + mapString | separator | expected + "key1:value1,key2:value2" | ':' | [key1: "value1", key2: "value2"] + "key1:value1 key2:value2" | ':' | [key1: "value1", key2: "value2"] + "env:test aKey:aVal bKey:bVal cKey:" | ':' | [env: "test", aKey: "aVal", bKey: "bVal", cKey:""] + "env:test,aKey:aVal,bKey:bVal,cKey:" | ':' | [env: "test", aKey: "aVal", bKey: "bVal", cKey:""] + "env:test,aKey:aVal bKey:bVal cKey:" | ':' | [env: "test", aKey: "aVal bKey:bVal cKey:"] + "env:test bKey :bVal dKey: dVal cKey:" | ':' | [env: "test", bKey: "", dKey: "", dVal: "", cKey: ""] + 'env :test, aKey : aVal bKey:bVal cKey:' | ':' | [env: "test", aKey : "aVal bKey:bVal cKey:"] + "env:keyWithA:Semicolon bKey:bVal cKey" | ':' | [env: "keyWithA:Semicolon", bKey: "bVal", cKey: ""] + "env:keyWith: , , Lots:Of:Semicolons " | ':' | [env: "keyWith:", Lots: "Of:Semicolons"] + "a:b,c,d" | ':' | [a: "b", c: "", d: ""] + "a,1" | ':' | [a: "", "1": ""] + "a:b:c:d" | ':' | [a: "b:c:d"] + //edge cases + "noDelimiters" | ':' | [noDelimiters: ""] + " " | ':' | [:] + ",,,,,,,,,,,," | ':' | [:] + ", , , , , , " | ':' | [:] + // spotless:on + } + def "test parseMapWithOptionalMappings"() { when: def result = ConfigConverter.parseMapWithOptionalMappings(mapString, "test", "", lowercaseKeys) From 518cd4a6c90c7f178e695a470a19a0e84d413a7f Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Thu, 13 Mar 2025 20:33:24 +0000 Subject: [PATCH 37/98] Async propagation is on by default, so HystrixThreadPoolInstrumentation is no longer required to temporarily enable it (#8556) --- .../HystrixThreadPoolInstrumentation.java | 52 ------------------- .../src/test/groovy/HystrixTest.groovy | 2 - 2 files changed, 54 deletions(-) delete mode 100644 dd-java-agent/instrumentation/hystrix-1.4/src/main/java/datadog/trace/instrumentation/hystrix/HystrixThreadPoolInstrumentation.java diff --git a/dd-java-agent/instrumentation/hystrix-1.4/src/main/java/datadog/trace/instrumentation/hystrix/HystrixThreadPoolInstrumentation.java b/dd-java-agent/instrumentation/hystrix-1.4/src/main/java/datadog/trace/instrumentation/hystrix/HystrixThreadPoolInstrumentation.java deleted file mode 100644 index 8dc653cba8a..00000000000 --- a/dd-java-agent/instrumentation/hystrix-1.4/src/main/java/datadog/trace/instrumentation/hystrix/HystrixThreadPoolInstrumentation.java +++ /dev/null @@ -1,52 +0,0 @@ -package datadog.trace.instrumentation.hystrix; - -import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named; -import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.isAsyncPropagationEnabled; -import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.setAsyncPropagationEnabled; -import static net.bytebuddy.matcher.ElementMatchers.isMethod; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; - -import com.google.auto.service.AutoService; -import datadog.trace.agent.tooling.Instrumenter; -import datadog.trace.agent.tooling.InstrumenterModule; -import net.bytebuddy.asm.Advice; - -@AutoService(InstrumenterModule.class) -public class HystrixThreadPoolInstrumentation extends InstrumenterModule.Tracing - implements Instrumenter.ForSingleType, Instrumenter.HasMethodAdvice { - - public HystrixThreadPoolInstrumentation() { - super("hystrix"); - } - - @Override - public String instrumentedType() { - return "com.netflix.hystrix.strategy.concurrency.HystrixContextScheduler$ThreadPoolWorker"; - } - - @Override - public void methodAdvice(MethodTransformer transformer) { - transformer.applyAdvice( - isMethod().and(named("schedule")).and(takesArguments(1)), - HystrixThreadPoolInstrumentation.class.getName() + "$EnableAsyncAdvice"); - } - - public static class EnableAsyncAdvice { - - @Advice.OnMethodEnter(suppress = Throwable.class) - public static boolean enableAsyncTracking() { - if (!isAsyncPropagationEnabled()) { - setAsyncPropagationEnabled(true); - return true; - } - return false; - } - - @Advice.OnMethodExit(suppress = Throwable.class) - public static void disableAsyncTracking(@Advice.Enter final boolean wasEnabled) { - if (wasEnabled) { - setAsyncPropagationEnabled(false); - } - } - } -} diff --git a/dd-java-agent/instrumentation/hystrix-1.4/src/test/groovy/HystrixTest.groovy b/dd-java-agent/instrumentation/hystrix-1.4/src/test/groovy/HystrixTest.groovy index c08036bb6d1..795a3303659 100644 --- a/dd-java-agent/instrumentation/hystrix-1.4/src/test/groovy/HystrixTest.groovy +++ b/dd-java-agent/instrumentation/hystrix-1.4/src/test/groovy/HystrixTest.groovy @@ -35,7 +35,6 @@ class HystrixTest extends HystrixTestRunner { } } expect: - TRANSFORMED_CLASSES_NAMES.contains("com.netflix.hystrix.strategy.concurrency.HystrixContextScheduler\$ThreadPoolWorker") TRANSFORMED_CLASSES_NAMES.contains("HystrixTest\$1") result == "Hello!" @@ -114,7 +113,6 @@ class HystrixTest extends HystrixTestRunner { } } expect: - TRANSFORMED_CLASSES_NAMES.contains("com.netflix.hystrix.strategy.concurrency.HystrixContextScheduler\$ThreadPoolWorker") TRANSFORMED_CLASSES_NAMES.contains("HystrixTest\$2") result == "Fallback!" From 8f2d28b94a99a78c6dce8c72d4d832edb2bb4b7b Mon Sep 17 00:00:00 2001 From: Andrea Marziali Date: Fri, 14 Mar 2025 11:07:11 +0100 Subject: [PATCH 38/98] Ensure shaded helpers have unique names (#8559) --- .../main/java/datadog/trace/agent/tooling/AdviceShader.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/AdviceShader.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/AdviceShader.java index 0ad3fb1da34..5443e9af7af 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/AdviceShader.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/AdviceShader.java @@ -65,7 +65,10 @@ public byte[] shadeClass(byte[] bytecode) { public String uniqueHelper(String dottedName) { int packageEnd = dottedName.lastIndexOf('.'); if (packageEnd > 0) { - return dottedName.substring(0, packageEnd + 1) + "shaded" + dottedName.substring(packageEnd); + return dottedName.substring(0, packageEnd + 1) + + "shaded" + + relocations.hashCode() + + dottedName.substring(packageEnd); } return dottedName; } From 90c7cbed3c5fbfecc58133edba9888baa8d06a84 Mon Sep 17 00:00:00 2001 From: Roberto Montero <108007532+robertomonteromiguel@users.noreply.github.com> Date: Fri, 14 Mar 2025 13:08:12 +0100 Subject: [PATCH 39/98] ssi tests one-pipeline (#8558) --- .gitlab-ci.yml | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index da8ffd29fc2..b027da64e23 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -456,22 +456,9 @@ requirements_json_test: package-oci: needs: [ build ] -onboarding_tests_installer: - parallel: - matrix: - - ONBOARDING_FILTER_WEBLOG: [test-app-java, test-app-java-container, test-app-java-alpine] - SCENARIO: [ SIMPLE_INSTALLER_AUTO_INJECTION, SIMPLE_AUTO_INJECTION_PROFILING ] - -onboarding_tests_k8s_injection: - parallel: - matrix: - - WEBLOG_VARIANT: [dd-lib-java-init-test-app] - SCENARIO: [K8S_LIB_INJECTION, K8S_LIB_INJECTION_UDS, K8S_LIB_INJECTION_NO_AC, K8S_LIB_INJECTION_NO_AC_UDS, K8S_LIB_INJECTION_PROFILING_DISABLED, K8S_LIB_INJECTION_PROFILING_ENABLED, K8S_LIB_INJECTION_PROFILING_OVERRIDE] - K8S_CLUSTER_VERSION: ['7.56.2', '7.57.0', '7.59.0'] - - - WEBLOG_VARIANT: [dd-djm-spark-test-app] - SCENARIO: [K8S_LIB_INJECTION_SPARK_DJM] - K8S_CLUSTER_VERSION: ['7.57.0', '7.59.0'] +configure_system_tests: + variables: + SYSTEM_TESTS_SCENARIOS_GROUPS: "simple_onboarding,simple_onboarding_profiling,docker-ssi,lib-injection" create_key: stage: generate-signing-key From d06699d400a2aa9f821aacb1e2c277b58babc455 Mon Sep 17 00:00:00 2001 From: Bruce Bujon Date: Fri, 14 Mar 2025 13:21:12 +0100 Subject: [PATCH 40/98] Fix ForkJoinPool.execute() instrumentation on Java 21+ (#8560) * fix(java-concurrent): Fix FJP instrumentation on Java 21+ * feat(java-concurrent): Add smoke tests for Java 21+ concurrent API --- .../StructuredTaskScopeInstrumentation.java | 18 +---- .../concurrent/java-21/build.gradle | 48 +++++++++++++ .../smoketest/concurrent/ConcurrentApp.java | 28 ++++++++ .../concurrent/FibonacciCalculator.java | 0 .../VirtualThreadExecuteCalculator.java | 54 +++++++++++++++ .../VirtualThreadInvokeAllCalculator.java | 50 ++++++++++++++ .../VirtualThreadInvokeAnyCalculator.java | 46 +++++++++++++ ...VirtualThreadSubmitCallableCalculator.java | 47 +++++++++++++ ...VirtualThreadSubmitRunnableCalculator.java | 54 +++++++++++++++ .../concurrent/AbstractConcurrentTest.groovy | 69 +++++++++++++++++++ .../concurrent/VirtualThreadTest.groovy | 61 ++++++++++++++++ .../concurrent/{ => java-8}/build.gradle | 13 +--- .../smoketest/concurrent/ConcurrentApp.java | 6 +- .../concurrent/DemoExecutorService.java | 0 .../DemoForkJoinPoolExternalClient.java | 56 +++++++++++++++ .../concurrent/DemoForkJoinPoolTask.java} | 13 ++-- .../concurrent/FibonacciCalculator.java | 10 +++ .../concurrent}/AbstractDemoTest.groovy | 4 +- .../DemoExecutorServiceTest.groovy | 2 +- .../DemoForkJoinPoolExternalClientTest.groovy | 12 ++++ .../DemoForkJoinPoolTaskTest.groovy | 12 ++++ .../DemoMultipleConcurrenciesTest.groovy | 6 +- .../datadog/smoketest/DemoForkJoinTest.groovy | 12 ---- settings.gradle | 3 +- 24 files changed, 570 insertions(+), 54 deletions(-) create mode 100644 dd-smoke-tests/concurrent/java-21/build.gradle create mode 100644 dd-smoke-tests/concurrent/java-21/src/main/java/datadog/smoketest/concurrent/ConcurrentApp.java rename dd-smoke-tests/concurrent/{ => java-21}/src/main/java/datadog/smoketest/concurrent/FibonacciCalculator.java (100%) create mode 100644 dd-smoke-tests/concurrent/java-21/src/main/java/datadog/smoketest/concurrent/VirtualThreadExecuteCalculator.java create mode 100644 dd-smoke-tests/concurrent/java-21/src/main/java/datadog/smoketest/concurrent/VirtualThreadInvokeAllCalculator.java create mode 100644 dd-smoke-tests/concurrent/java-21/src/main/java/datadog/smoketest/concurrent/VirtualThreadInvokeAnyCalculator.java create mode 100644 dd-smoke-tests/concurrent/java-21/src/main/java/datadog/smoketest/concurrent/VirtualThreadSubmitCallableCalculator.java create mode 100644 dd-smoke-tests/concurrent/java-21/src/main/java/datadog/smoketest/concurrent/VirtualThreadSubmitRunnableCalculator.java create mode 100644 dd-smoke-tests/concurrent/java-21/src/test/groovy/datadog/smoketest/concurrent/AbstractConcurrentTest.groovy create mode 100644 dd-smoke-tests/concurrent/java-21/src/test/groovy/datadog/smoketest/concurrent/VirtualThreadTest.groovy rename dd-smoke-tests/concurrent/{ => java-8}/build.gradle (54%) rename dd-smoke-tests/concurrent/{ => java-8}/src/main/java/datadog/smoketest/concurrent/ConcurrentApp.java (78%) rename dd-smoke-tests/concurrent/{ => java-8}/src/main/java/datadog/smoketest/concurrent/DemoExecutorService.java (100%) create mode 100644 dd-smoke-tests/concurrent/java-8/src/main/java/datadog/smoketest/concurrent/DemoForkJoinPoolExternalClient.java rename dd-smoke-tests/concurrent/{src/main/java/datadog/smoketest/concurrent/DemoForkJoin.java => java-8/src/main/java/datadog/smoketest/concurrent/DemoForkJoinPoolTask.java} (70%) create mode 100644 dd-smoke-tests/concurrent/java-8/src/main/java/datadog/smoketest/concurrent/FibonacciCalculator.java rename dd-smoke-tests/concurrent/{src/test/groovy/datadog/smoketest => java-8/src/test/groovy/datadog/smoketest/concurrent}/AbstractDemoTest.groovy (96%) rename dd-smoke-tests/concurrent/{src/test/groovy/datadog/smoketest => java-8/src/test/groovy/datadog/smoketest/concurrent}/DemoExecutorServiceTest.groovy (87%) create mode 100644 dd-smoke-tests/concurrent/java-8/src/test/groovy/datadog/smoketest/concurrent/DemoForkJoinPoolExternalClientTest.groovy create mode 100644 dd-smoke-tests/concurrent/java-8/src/test/groovy/datadog/smoketest/concurrent/DemoForkJoinPoolTaskTest.groovy rename dd-smoke-tests/concurrent/{src/test/groovy/datadog/smoketest => java-8/src/test/groovy/datadog/smoketest/concurrent}/DemoMultipleConcurrenciesTest.groovy (60%) delete mode 100644 dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/DemoForkJoinTest.groovy diff --git a/dd-java-agent/instrumentation/java-concurrent/java-concurrent-21/src/main/java/datadog/trace/instrumentation/java/concurrent/structuredconcurrency/StructuredTaskScopeInstrumentation.java b/dd-java-agent/instrumentation/java-concurrent/java-concurrent-21/src/main/java/datadog/trace/instrumentation/java/concurrent/structuredconcurrency/StructuredTaskScopeInstrumentation.java index 4bb5c8f4bf9..5a9787f0b40 100644 --- a/dd-java-agent/instrumentation/java-concurrent/java-concurrent-21/src/main/java/datadog/trace/instrumentation/java/concurrent/structuredconcurrency/StructuredTaskScopeInstrumentation.java +++ b/dd-java-agent/instrumentation/java-concurrent/java-concurrent-21/src/main/java/datadog/trace/instrumentation/java/concurrent/structuredconcurrency/StructuredTaskScopeInstrumentation.java @@ -1,21 +1,16 @@ package datadog.trace.instrumentation.java.concurrent.structuredconcurrency; import static datadog.trace.bootstrap.instrumentation.java.concurrent.AdviceUtils.capture; -import static datadog.trace.bootstrap.instrumentation.java.concurrent.ExcludeFilter.ExcludeType.FORK_JOIN_TASK; -import static java.util.Collections.singleton; import static java.util.Collections.singletonMap; import static net.bytebuddy.matcher.ElementMatchers.isConstructor; import com.google.auto.service.AutoService; -import datadog.trace.agent.tooling.ExcludeFilterProvider; import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.InstrumenterModule; import datadog.trace.api.Platform; import datadog.trace.bootstrap.ContextStore; import datadog.trace.bootstrap.InstrumentationContext; -import datadog.trace.bootstrap.instrumentation.java.concurrent.ExcludeFilter; import datadog.trace.bootstrap.instrumentation.java.concurrent.State; -import java.util.Collection; import java.util.Map; import net.bytebuddy.asm.Advice; @@ -27,10 +22,7 @@ @SuppressWarnings("unused") @AutoService(InstrumenterModule.class) public class StructuredTaskScopeInstrumentation extends InstrumenterModule.Tracing - implements Instrumenter.ForBootstrap, - Instrumenter.ForSingleType, - Instrumenter.HasMethodAdvice, - ExcludeFilterProvider { + implements Instrumenter.ForBootstrap, Instrumenter.ForSingleType, Instrumenter.HasMethodAdvice { public StructuredTaskScopeInstrumentation() { super("java_concurrent", "structured_task_scope"); @@ -57,14 +49,6 @@ public void methodAdvice(MethodTransformer transformer) { transformer.applyAdvice(isConstructor(), getClass().getName() + "$ConstructorAdvice"); } - @Override - public Map> excludedClasses() { - // Prevent the ForkJoinPool instrumentation to enable the task scope too early on the carrier - // thread rather than on the expected running thread, which is virtual by default. - return singletonMap( - FORK_JOIN_TASK, singleton("java.util.concurrent.ForkJoinTask$RunnableExecuteAction")); - } - public static final class ConstructorAdvice { @Advice.OnMethodExit public static void captureScope( diff --git a/dd-smoke-tests/concurrent/java-21/build.gradle b/dd-smoke-tests/concurrent/java-21/build.gradle new file mode 100644 index 00000000000..147758d8b89 --- /dev/null +++ b/dd-smoke-tests/concurrent/java-21/build.gradle @@ -0,0 +1,48 @@ +plugins { + id 'application' + id 'com.github.johnrengelman.shadow' +} + +ext { + minJavaVersionForTests = JavaVersion.VERSION_21 +} + +apply from: "$rootDir/gradle/java.gradle" + +description = 'JDK 21 Concurrent Integration Tests' + +java { + toolchain { + languageVersion = JavaLanguageVersion.of(21) + } +} +tasks.withType(JavaCompile).configureEach { + setJavaVersion(it, 21) + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 +} + +// Disable plugin tasks that do not support Java 21: +// * forbiddenApis is missing classes +// * spotless as the google-java-format version does not support Java 21 and can't be changed once applied +// * spotbugs failed to read class using newer bytecode versions +forbiddenApisMain { + failOnMissingClasses = false +} +['spotlessApply', 'spotlessCheck', 'spotlessJava', 'spotbugsMain'].each { + tasks.named(it).configure { enabled = false } +} + +application { + mainClassName = 'datadog.smoketest.concurrent.ConcurrentApp' +} + +dependencies { + implementation group: 'io.opentelemetry.instrumentation', name: 'opentelemetry-instrumentation-annotations', version: '2.13.3' + testImplementation project(':dd-smoke-tests') +} + +tasks.withType(Test).configureEach { + dependsOn "shadowJar" + jvmArgs "-Ddatadog.smoketest.shadowJar.path=${tasks.shadowJar.archiveFile.get()}" +} diff --git a/dd-smoke-tests/concurrent/java-21/src/main/java/datadog/smoketest/concurrent/ConcurrentApp.java b/dd-smoke-tests/concurrent/java-21/src/main/java/datadog/smoketest/concurrent/ConcurrentApp.java new file mode 100644 index 00000000000..aa58e12286d --- /dev/null +++ b/dd-smoke-tests/concurrent/java-21/src/main/java/datadog/smoketest/concurrent/ConcurrentApp.java @@ -0,0 +1,28 @@ +package datadog.smoketest.concurrent; + +import io.opentelemetry.instrumentation.annotations.WithSpan; +import java.util.concurrent.ExecutionException; + +public class ConcurrentApp { + @WithSpan("main") + public static void main(String[] args) { + for (String arg : args) { + try (FibonacciCalculator calc = getCalculator(arg)) { + calc.computeFibonacci(10); + } catch (ExecutionException | InterruptedException e) { + throw new RuntimeException("Failed to compute fibonacci number.", e); + } + } + } + + private static FibonacciCalculator getCalculator(String name) { + return switch (name) { + case "virtualThreadExecute" -> new VirtualThreadExecuteCalculator(); + case "virtualThreadSubmitRunnable" -> new VirtualThreadSubmitRunnableCalculator(); + case "virtualThreadSubmitCallable" -> new VirtualThreadSubmitCallableCalculator(); + case "virtualThreadInvokeAll" -> new VirtualThreadInvokeAllCalculator(); + case "virtualThreadInvokeAny" -> new VirtualThreadInvokeAnyCalculator(); + default -> throw new RuntimeException("Unknown Fibonacci calculator: " + name); + }; + } +} diff --git a/dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/FibonacciCalculator.java b/dd-smoke-tests/concurrent/java-21/src/main/java/datadog/smoketest/concurrent/FibonacciCalculator.java similarity index 100% rename from dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/FibonacciCalculator.java rename to dd-smoke-tests/concurrent/java-21/src/main/java/datadog/smoketest/concurrent/FibonacciCalculator.java diff --git a/dd-smoke-tests/concurrent/java-21/src/main/java/datadog/smoketest/concurrent/VirtualThreadExecuteCalculator.java b/dd-smoke-tests/concurrent/java-21/src/main/java/datadog/smoketest/concurrent/VirtualThreadExecuteCalculator.java new file mode 100644 index 00000000000..119c227f782 --- /dev/null +++ b/dd-smoke-tests/concurrent/java-21/src/main/java/datadog/smoketest/concurrent/VirtualThreadExecuteCalculator.java @@ -0,0 +1,54 @@ +package datadog.smoketest.concurrent; + +import io.opentelemetry.instrumentation.annotations.WithSpan; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class VirtualThreadExecuteCalculator implements FibonacciCalculator { + private final ExecutorService executor; + + public VirtualThreadExecuteCalculator() { + this.executor = Executors.newVirtualThreadPerTaskExecutor(); + } + + @Override + public long computeFibonacci(int n) throws ExecutionException, InterruptedException { + FibonacciExecuteTask task = new FibonacciExecuteTask(n); + this.executor.execute(task); + return task.result.get(); + } + + public class FibonacciExecuteTask implements Runnable { + private final long n; + private final CompletableFuture result; + + public FibonacciExecuteTask(long n) { + this.n = n; + this.result = new CompletableFuture<>(); + } + + @WithSpan("compute") + public void run() { + if (this.n <= 1) { + this.result.complete(this.n); + return; + } + FibonacciExecuteTask task1 = new FibonacciExecuteTask(this.n - 1); + FibonacciExecuteTask task2 = new FibonacciExecuteTask(this.n - 2); + executor.execute(task1); + executor.execute(task2); + try { + this.result.complete(task1.result.get() + task2.result.get()); + } catch (InterruptedException | ExecutionException e) { + this.result.completeExceptionally(e); + } + } + } + + @Override + public void close() { + this.executor.shutdown(); + } +} diff --git a/dd-smoke-tests/concurrent/java-21/src/main/java/datadog/smoketest/concurrent/VirtualThreadInvokeAllCalculator.java b/dd-smoke-tests/concurrent/java-21/src/main/java/datadog/smoketest/concurrent/VirtualThreadInvokeAllCalculator.java new file mode 100644 index 00000000000..4c8407326eb --- /dev/null +++ b/dd-smoke-tests/concurrent/java-21/src/main/java/datadog/smoketest/concurrent/VirtualThreadInvokeAllCalculator.java @@ -0,0 +1,50 @@ +package datadog.smoketest.concurrent; + +import static java.util.Set.of; + +import io.opentelemetry.instrumentation.annotations.WithSpan; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +public class VirtualThreadInvokeAllCalculator implements FibonacciCalculator { + private final ExecutorService executor; + + public VirtualThreadInvokeAllCalculator() { + this.executor = Executors.newVirtualThreadPerTaskExecutor(); + } + + @Override + public long computeFibonacci(int n) throws ExecutionException, InterruptedException { + FibonacciSubmitTask task = new FibonacciSubmitTask(n); + return this.executor.invokeAll(of(task)).getFirst().get(); + } + + public class FibonacciSubmitTask implements Callable { + private final long n; + + public FibonacciSubmitTask(long n) { + this.n = n; + } + + @WithSpan("compute") + public Long call() throws ExecutionException, InterruptedException { + if (this.n <= 1) { + return this.n; + } + FibonacciSubmitTask task1 = new FibonacciSubmitTask(this.n - 1); + FibonacciSubmitTask task2 = new FibonacciSubmitTask(this.n - 2); + List> futures = executor.invokeAll(List.of(task1, task2)); + return futures.getFirst().get() + futures.getLast().get(); + } + } + + @Override + public void close() { + this.executor.shutdown(); + } +} diff --git a/dd-smoke-tests/concurrent/java-21/src/main/java/datadog/smoketest/concurrent/VirtualThreadInvokeAnyCalculator.java b/dd-smoke-tests/concurrent/java-21/src/main/java/datadog/smoketest/concurrent/VirtualThreadInvokeAnyCalculator.java new file mode 100644 index 00000000000..c7b9205e273 --- /dev/null +++ b/dd-smoke-tests/concurrent/java-21/src/main/java/datadog/smoketest/concurrent/VirtualThreadInvokeAnyCalculator.java @@ -0,0 +1,46 @@ +package datadog.smoketest.concurrent; + +import static java.util.Set.of; + +import io.opentelemetry.instrumentation.annotations.WithSpan; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class VirtualThreadInvokeAnyCalculator implements FibonacciCalculator { + private final ExecutorService executor; + + public VirtualThreadInvokeAnyCalculator() { + this.executor = Executors.newVirtualThreadPerTaskExecutor(); + } + + @Override + public long computeFibonacci(int n) throws ExecutionException, InterruptedException { + FibonacciSubmitTask task = new FibonacciSubmitTask(n); + return this.executor.invokeAny(of(task)); + } + + public class FibonacciSubmitTask implements Callable { + private final long n; + + public FibonacciSubmitTask(long n) { + this.n = n; + } + + @WithSpan("compute") + public Long call() throws ExecutionException, InterruptedException { + if (this.n <= 1) { + return this.n; + } + FibonacciSubmitTask task1 = new FibonacciSubmitTask(this.n - 1); + FibonacciSubmitTask task2 = new FibonacciSubmitTask(this.n - 2); + return executor.invokeAny(of(task1)) + executor.invokeAny(of(task2)); + } + } + + @Override + public void close() { + this.executor.shutdown(); + } +} diff --git a/dd-smoke-tests/concurrent/java-21/src/main/java/datadog/smoketest/concurrent/VirtualThreadSubmitCallableCalculator.java b/dd-smoke-tests/concurrent/java-21/src/main/java/datadog/smoketest/concurrent/VirtualThreadSubmitCallableCalculator.java new file mode 100644 index 00000000000..6281287b413 --- /dev/null +++ b/dd-smoke-tests/concurrent/java-21/src/main/java/datadog/smoketest/concurrent/VirtualThreadSubmitCallableCalculator.java @@ -0,0 +1,47 @@ +package datadog.smoketest.concurrent; + +import io.opentelemetry.instrumentation.annotations.WithSpan; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +public class VirtualThreadSubmitCallableCalculator implements FibonacciCalculator { + private final ExecutorService executor; + + public VirtualThreadSubmitCallableCalculator() { + this.executor = Executors.newVirtualThreadPerTaskExecutor(); + } + + @Override + public long computeFibonacci(int n) throws ExecutionException, InterruptedException { + FibonacciSubmitTask task = new FibonacciSubmitTask(n); + return this.executor.submit(task).get(); + } + + public class FibonacciSubmitTask implements Callable { + private final long n; + + public FibonacciSubmitTask(long n) { + this.n = n; + } + + @WithSpan("compute") + public Long call() throws ExecutionException, InterruptedException { + if (this.n <= 1) { + return this.n; + } + FibonacciSubmitTask task1 = new FibonacciSubmitTask(this.n - 1); + FibonacciSubmitTask task2 = new FibonacciSubmitTask(this.n - 2); + Future future1 = executor.submit(task1); + Future future2 = executor.submit(task2); + return future1.get() + future2.get(); + } + } + + @Override + public void close() { + this.executor.shutdown(); + } +} diff --git a/dd-smoke-tests/concurrent/java-21/src/main/java/datadog/smoketest/concurrent/VirtualThreadSubmitRunnableCalculator.java b/dd-smoke-tests/concurrent/java-21/src/main/java/datadog/smoketest/concurrent/VirtualThreadSubmitRunnableCalculator.java new file mode 100644 index 00000000000..d1a0940b4d7 --- /dev/null +++ b/dd-smoke-tests/concurrent/java-21/src/main/java/datadog/smoketest/concurrent/VirtualThreadSubmitRunnableCalculator.java @@ -0,0 +1,54 @@ +package datadog.smoketest.concurrent; + +import io.opentelemetry.instrumentation.annotations.WithSpan; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class VirtualThreadSubmitRunnableCalculator implements FibonacciCalculator { + private final ExecutorService executor; + + public VirtualThreadSubmitRunnableCalculator() { + this.executor = Executors.newVirtualThreadPerTaskExecutor(); + } + + @Override + public long computeFibonacci(int n) throws ExecutionException, InterruptedException { + FibonacciSubmitTask task = new FibonacciSubmitTask(n); + this.executor.execute(task); + return task.result.get(); + } + + public class FibonacciSubmitTask implements Runnable { + private final long n; + private final CompletableFuture result; + + public FibonacciSubmitTask(long n) { + this.n = n; + this.result = new CompletableFuture<>(); + } + + @WithSpan("compute") + public void run() { + if (this.n <= 1) { + this.result.complete(this.n); + return; + } + FibonacciSubmitTask task1 = new FibonacciSubmitTask(this.n - 1); + FibonacciSubmitTask task2 = new FibonacciSubmitTask(this.n - 2); + executor.submit(task1); + executor.submit(task2); + try { + this.result.complete(task1.result.get() + task2.result.get()); + } catch (InterruptedException | ExecutionException e) { + this.result.completeExceptionally(e); + } + } + } + + @Override + public void close() { + this.executor.shutdown(); + } +} diff --git a/dd-smoke-tests/concurrent/java-21/src/test/groovy/datadog/smoketest/concurrent/AbstractConcurrentTest.groovy b/dd-smoke-tests/concurrent/java-21/src/test/groovy/datadog/smoketest/concurrent/AbstractConcurrentTest.groovy new file mode 100644 index 00000000000..b6e8b9d1b61 --- /dev/null +++ b/dd-smoke-tests/concurrent/java-21/src/test/groovy/datadog/smoketest/concurrent/AbstractConcurrentTest.groovy @@ -0,0 +1,69 @@ +package datadog.smoketest.concurrent + +import datadog.smoketest.AbstractSmokeTest +import datadog.trace.test.agent.decoder.DecodedTrace + +import java.util.function.Function + +import static java.util.concurrent.TimeUnit.SECONDS + +abstract class AbstractConcurrentTest extends AbstractSmokeTest { + protected static final int TIMEOUT_SECS = 10 + protected abstract List getTestArguments() + + @Override + ProcessBuilder createProcessBuilder() { + def jarPath = System.getProperty("datadog.smoketest.shadowJar.path") + def command = new ArrayList() + command.add(javaPath()) + command.addAll(defaultJavaProperties) + command.add("-Ddd.trace.otel.enabled=true") + command.addAll(["-jar", jarPath]) + command.addAll(getTestArguments()) + + ProcessBuilder processBuilder = new ProcessBuilder(command) + processBuilder.directory(new File(buildDirectory)) + } + + @Override + Closure decodedTracesCallback() { + return {} // force traces decoding + } + + protected static Function checkTrace() { + return { + trace -> + // Check for 'main' span + def mainSpan = trace.spans.find { it.name == 'main' } + if (!mainSpan) { + return false + } + // Check that there are only 'main' and 'compute' spans + def otherSpans = trace.spans.findAll { it.name != 'main' && it.name != 'compute' } + if (!otherSpans.isEmpty()) { + return false + } + // Check that every 'compute' span is in the same trace and is either a child of the 'main' span or another 'compute' span + def computeSpans = trace.spans.findAll { it.name == 'compute' } + if (computeSpans.isEmpty()) { + return false + } + return computeSpans.every { + if (it.traceId != mainSpan.traceId) { + return false + } + if (it.parentId != mainSpan.spanId && trace.spans.find(s -> s.spanId == it.parentId).name != 'compute') { + return false + } + return true + } + } + } + + protected void receivedCorrectTrace() { + waitForTrace(defaultPoll, checkTrace()) + assert traceCount.get() == 1 + assert testedProcess.waitFor(TIMEOUT_SECS, SECONDS) + assert testedProcess.exitValue() == 0 + } +} diff --git a/dd-smoke-tests/concurrent/java-21/src/test/groovy/datadog/smoketest/concurrent/VirtualThreadTest.groovy b/dd-smoke-tests/concurrent/java-21/src/test/groovy/datadog/smoketest/concurrent/VirtualThreadTest.groovy new file mode 100644 index 00000000000..a3903ba9dc8 --- /dev/null +++ b/dd-smoke-tests/concurrent/java-21/src/test/groovy/datadog/smoketest/concurrent/VirtualThreadTest.groovy @@ -0,0 +1,61 @@ +package datadog.smoketest.concurrent + +class VirtualThreadExecuteTest extends AbstractConcurrentTest { + @Override + protected List getTestArguments() { + return ['virtualThreadExecute'] + } + + def 'test VirtualThread execute runnable'() { + expect: + receivedCorrectTrace() + } +} + +class VirtualThreadInvokeAllTest extends AbstractConcurrentTest { + @Override + protected List getTestArguments() { + return ['virtualThreadInvokeAll'] + } + + def 'test VirtualThread invokeAll callable'() { + expect: + receivedCorrectTrace() + } +} + +class VirtualThreadInvokeAnyTest extends AbstractConcurrentTest { + @Override + protected List getTestArguments() { + return ['virtualThreadInvokeAny'] + } + + def 'test VirtualThread invoke any callable'() { + expect: + receivedCorrectTrace() + } +} + +class VirtualThreadSubmitRunnableTest extends AbstractConcurrentTest { + @Override + protected List getTestArguments() { + return ['virtualThreadSubmitRunnable'] + } + + def 'test VirtualThread submit runnable'() { + expect: + receivedCorrectTrace() + } +} + +class VirtualThreadSubmitCallableTest extends AbstractConcurrentTest { + @Override + protected List getTestArguments() { + return ['virtualThreadSubmitCallable'] + } + + def 'test VirtualThread submit callable'() { + expect: + receivedCorrectTrace() + } +} diff --git a/dd-smoke-tests/concurrent/build.gradle b/dd-smoke-tests/concurrent/java-8/build.gradle similarity index 54% rename from dd-smoke-tests/concurrent/build.gradle rename to dd-smoke-tests/concurrent/java-8/build.gradle index b95668127e6..2afc5b0a712 100644 --- a/dd-smoke-tests/concurrent/build.gradle +++ b/dd-smoke-tests/concurrent/java-8/build.gradle @@ -1,32 +1,23 @@ plugins { - id 'java' id 'application' id 'com.github.johnrengelman.shadow' } apply from: "$rootDir/gradle/java.gradle" -description = 'Concurrent Integration Tests.' +description = 'JDK 8 Concurrent Integration Tests' application { mainClassName = 'datadog.smoketest.concurrent.ConcurrentApp' } dependencies { - implementation('io.opentelemetry.instrumentation:opentelemetry-instrumentation-annotations:2.13.1') - implementation project(':dd-trace-api') + implementation group: 'io.opentelemetry.instrumentation', name: 'opentelemetry-instrumentation-annotations', version: '2.13.3' testImplementation project(':dd-smoke-tests') - - testImplementation platform('org.junit:junit-bom:5.10.0') - testImplementation 'org.junit.jupiter:junit-jupiter' } -test { - useJUnitPlatform() -} tasks.withType(Test).configureEach { dependsOn "shadowJar" - jvmArgs "-Ddatadog.smoketest.shadowJar.path=${tasks.shadowJar.archiveFile.get()}" } diff --git a/dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/ConcurrentApp.java b/dd-smoke-tests/concurrent/java-8/src/main/java/datadog/smoketest/concurrent/ConcurrentApp.java similarity index 78% rename from dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/ConcurrentApp.java rename to dd-smoke-tests/concurrent/java-8/src/main/java/datadog/smoketest/concurrent/ConcurrentApp.java index c17d84a8887..c54fb188db3 100644 --- a/dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/ConcurrentApp.java +++ b/dd-smoke-tests/concurrent/java-8/src/main/java/datadog/smoketest/concurrent/ConcurrentApp.java @@ -19,8 +19,10 @@ public static void main(String[] args) { private static FibonacciCalculator getCalculator(String name) { if (name.equalsIgnoreCase("executorService")) { return new DemoExecutorService(); - } else if (name.equalsIgnoreCase("forkJoin")) { - return new DemoForkJoin(); + } else if (name.equalsIgnoreCase("forkJoinPoolTask")) { + return new DemoForkJoinPoolTask(); + } else if (name.equalsIgnoreCase("forkJoinPoolExternalClient")) { + return new DemoForkJoinPoolExternalClient(); } throw new IllegalArgumentException("Unknown calculator: " + name); } diff --git a/dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/DemoExecutorService.java b/dd-smoke-tests/concurrent/java-8/src/main/java/datadog/smoketest/concurrent/DemoExecutorService.java similarity index 100% rename from dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/DemoExecutorService.java rename to dd-smoke-tests/concurrent/java-8/src/main/java/datadog/smoketest/concurrent/DemoExecutorService.java diff --git a/dd-smoke-tests/concurrent/java-8/src/main/java/datadog/smoketest/concurrent/DemoForkJoinPoolExternalClient.java b/dd-smoke-tests/concurrent/java-8/src/main/java/datadog/smoketest/concurrent/DemoForkJoinPoolExternalClient.java new file mode 100644 index 00000000000..873ac885b48 --- /dev/null +++ b/dd-smoke-tests/concurrent/java-8/src/main/java/datadog/smoketest/concurrent/DemoForkJoinPoolExternalClient.java @@ -0,0 +1,56 @@ +package datadog.smoketest.concurrent; + +import io.opentelemetry.instrumentation.annotations.WithSpan; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ForkJoinPool; + +/** Test ForkJoinPool using the external client API. */ +public class DemoForkJoinPoolExternalClient implements FibonacciCalculator { + private final ForkJoinPool forkJoinPool; + + public DemoForkJoinPoolExternalClient() { + this.forkJoinPool = new ForkJoinPool(); + } + + @Override + public long computeFibonacci(int n) throws ExecutionException, InterruptedException { + FibonacciTask task = new FibonacciTask(n); + this.forkJoinPool.execute(task); + return task.result.get(); + } + + private class FibonacciTask implements Runnable { + private final int n; + private final CompletableFuture result; + + public FibonacciTask(int n) { + this.n = n; + this.result = new CompletableFuture<>(); + } + + @WithSpan("compute") + @Override + public void run() { + if (this.n <= 1) { + this.result.complete((long) this.n); + return; + } + FibonacciTask taskOne = new FibonacciTask(this.n - 1); + forkJoinPool.execute(taskOne); + FibonacciTask taskTwo = new FibonacciTask(this.n - 2); + forkJoinPool.submit(taskTwo); + + try { + this.result.complete(taskOne.result.get() + taskTwo.result.get()); + } catch (InterruptedException | ExecutionException e) { + this.result.completeExceptionally(e); + } + } + } + + @Override + public void close() { + forkJoinPool.shutdown(); + } +} diff --git a/dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/DemoForkJoin.java b/dd-smoke-tests/concurrent/java-8/src/main/java/datadog/smoketest/concurrent/DemoForkJoinPoolTask.java similarity index 70% rename from dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/DemoForkJoin.java rename to dd-smoke-tests/concurrent/java-8/src/main/java/datadog/smoketest/concurrent/DemoForkJoinPoolTask.java index dd77f86f324..486e3e308bd 100644 --- a/dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/DemoForkJoin.java +++ b/dd-smoke-tests/concurrent/java-8/src/main/java/datadog/smoketest/concurrent/DemoForkJoinPoolTask.java @@ -4,19 +4,20 @@ import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveTask; -public class DemoForkJoin implements FibonacciCalculator { +/** Test ForkJoinPool using the FJP task API. */ +public class DemoForkJoinPoolTask implements FibonacciCalculator { private final ForkJoinPool forkJoinPool; - public DemoForkJoin() { + public DemoForkJoinPoolTask() { forkJoinPool = new ForkJoinPool(); } @Override public long computeFibonacci(int n) { - return forkJoinPool.invoke(new FibonacciTask(n)); + return new FibonacciTask(n).invoke(); } - private class FibonacciTask extends RecursiveTask { + private static class FibonacciTask extends RecursiveTask { private final int n; public FibonacciTask(int n) { @@ -26,8 +27,8 @@ public FibonacciTask(int n) { @WithSpan("compute") @Override protected Long compute() { - if (n <= 1) { - return (long) n; + if (this.n <= 1) { + return (long) this.n; } FibonacciTask taskOne = new FibonacciTask(n - 1); taskOne.fork(); diff --git a/dd-smoke-tests/concurrent/java-8/src/main/java/datadog/smoketest/concurrent/FibonacciCalculator.java b/dd-smoke-tests/concurrent/java-8/src/main/java/datadog/smoketest/concurrent/FibonacciCalculator.java new file mode 100644 index 00000000000..73974d7b135 --- /dev/null +++ b/dd-smoke-tests/concurrent/java-8/src/main/java/datadog/smoketest/concurrent/FibonacciCalculator.java @@ -0,0 +1,10 @@ +package datadog.smoketest.concurrent; + +import java.util.concurrent.ExecutionException; + +public interface FibonacciCalculator extends AutoCloseable { + long computeFibonacci(int n) throws ExecutionException, InterruptedException; + + @Override + void close(); +} diff --git a/dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/AbstractDemoTest.groovy b/dd-smoke-tests/concurrent/java-8/src/test/groovy/datadog/smoketest/concurrent/AbstractDemoTest.groovy similarity index 96% rename from dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/AbstractDemoTest.groovy rename to dd-smoke-tests/concurrent/java-8/src/test/groovy/datadog/smoketest/concurrent/AbstractDemoTest.groovy index 1628d0459df..dbe05774867 100644 --- a/dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/AbstractDemoTest.groovy +++ b/dd-smoke-tests/concurrent/java-8/src/test/groovy/datadog/smoketest/concurrent/AbstractDemoTest.groovy @@ -1,4 +1,6 @@ -package datadog.smoketest +package datadog.smoketest.concurrent + +import datadog.smoketest.AbstractSmokeTest import static java.util.concurrent.TimeUnit.SECONDS import datadog.trace.test.agent.decoder.DecodedTrace diff --git a/dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/DemoExecutorServiceTest.groovy b/dd-smoke-tests/concurrent/java-8/src/test/groovy/datadog/smoketest/concurrent/DemoExecutorServiceTest.groovy similarity index 87% rename from dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/DemoExecutorServiceTest.groovy rename to dd-smoke-tests/concurrent/java-8/src/test/groovy/datadog/smoketest/concurrent/DemoExecutorServiceTest.groovy index b99891b89bb..f27ad653f32 100644 --- a/dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/DemoExecutorServiceTest.groovy +++ b/dd-smoke-tests/concurrent/java-8/src/test/groovy/datadog/smoketest/concurrent/DemoExecutorServiceTest.groovy @@ -1,4 +1,4 @@ -package datadog.smoketest +package datadog.smoketest.concurrent class DemoExecutorServiceTest extends AbstractDemoTest { protected List getTestArguments() { diff --git a/dd-smoke-tests/concurrent/java-8/src/test/groovy/datadog/smoketest/concurrent/DemoForkJoinPoolExternalClientTest.groovy b/dd-smoke-tests/concurrent/java-8/src/test/groovy/datadog/smoketest/concurrent/DemoForkJoinPoolExternalClientTest.groovy new file mode 100644 index 00000000000..173d502d941 --- /dev/null +++ b/dd-smoke-tests/concurrent/java-8/src/test/groovy/datadog/smoketest/concurrent/DemoForkJoinPoolExternalClientTest.groovy @@ -0,0 +1,12 @@ +package datadog.smoketest.concurrent + +class DemoForkJoinPoolExternalClientTest extends AbstractDemoTest { + protected List getTestArguments() { + return ["forkJoinPoolExternalClient"] + } + + def 'receive one correct trace when using ForkJoinPool external client API'() { + expect: + receivedCorrectTrace() + } +} diff --git a/dd-smoke-tests/concurrent/java-8/src/test/groovy/datadog/smoketest/concurrent/DemoForkJoinPoolTaskTest.groovy b/dd-smoke-tests/concurrent/java-8/src/test/groovy/datadog/smoketest/concurrent/DemoForkJoinPoolTaskTest.groovy new file mode 100644 index 00000000000..d1c5618551f --- /dev/null +++ b/dd-smoke-tests/concurrent/java-8/src/test/groovy/datadog/smoketest/concurrent/DemoForkJoinPoolTaskTest.groovy @@ -0,0 +1,12 @@ +package datadog.smoketest.concurrent + +class DemoForkJoinPoolTaskTest extends AbstractDemoTest { + protected List getTestArguments() { + return ["forkJoinPoolTask"] + } + + def 'receive one correct trace when using ForkJoinPool task API'() { + expect: + receivedCorrectTrace() + } +} diff --git a/dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/DemoMultipleConcurrenciesTest.groovy b/dd-smoke-tests/concurrent/java-8/src/test/groovy/datadog/smoketest/concurrent/DemoMultipleConcurrenciesTest.groovy similarity index 60% rename from dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/DemoMultipleConcurrenciesTest.groovy rename to dd-smoke-tests/concurrent/java-8/src/test/groovy/datadog/smoketest/concurrent/DemoMultipleConcurrenciesTest.groovy index 06ec5dc67b2..ce374c66a60 100644 --- a/dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/DemoMultipleConcurrenciesTest.groovy +++ b/dd-smoke-tests/concurrent/java-8/src/test/groovy/datadog/smoketest/concurrent/DemoMultipleConcurrenciesTest.groovy @@ -1,11 +1,11 @@ -package datadog.smoketest +package datadog.smoketest.concurrent class DemoMultipleConcurrenciesTest extends AbstractDemoTest { protected List getTestArguments() { - return ["executorService", "forkJoin"] + return ["executorService", "forkJoinPoolTask"] } - def 'receive one correct trace when using multiple concurrency strategies (ExecutorService and ForkJoin)'() { + def 'receive one correct trace when using multiple concurrency strategies (ExecutorService and ForkJoinPool task API)'() { expect: receivedCorrectTrace() } diff --git a/dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/DemoForkJoinTest.groovy b/dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/DemoForkJoinTest.groovy deleted file mode 100644 index 00994a6ef4f..00000000000 --- a/dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/DemoForkJoinTest.groovy +++ /dev/null @@ -1,12 +0,0 @@ -package datadog.smoketest - -class DemoForkJoinTest extends AbstractDemoTest { - protected List getTestArguments() { - return ["forkJoin"] - } - - def 'receive one correct trace when using ForkJoin'() { - expect: - receivedCorrectTrace() - } -} diff --git a/settings.gradle b/settings.gradle index 11c65fef6dd..8b759eb4499 100644 --- a/settings.gradle +++ b/settings.gradle @@ -98,7 +98,8 @@ include ':dd-smoke-tests:apm-tracing-disabled' include ':dd-smoke-tests:armeria-grpc' include ':dd-smoke-tests:backend-mock' include ':dd-smoke-tests:cli' -include ':dd-smoke-tests:concurrent' +include ':dd-smoke-tests:concurrent:java-8' +include ':dd-smoke-tests:concurrent:java-21' include ':dd-smoke-tests:crashtracking' include ':dd-smoke-tests:custom-systemloader' include ':dd-smoke-tests:dynamic-config' From 12fe6321e84db8683c5af139ecf9c8d0d1879833 Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Fri, 14 Mar 2025 13:56:36 +0000 Subject: [PATCH 41/98] Simplify activateSpan API to not include async propagation flag (#8557) These remaining cases were no-op spans which are already not propagated --- .../concurrent/AkkaActorCellInstrumentation.java | 2 +- .../akka/concurrent/AkkaMailboxInstrumentation.java | 2 +- .../concurrent/PekkoActorCellInstrumentation.java | 2 +- .../concurrent/PekkoMailboxInstrumentation.java | 2 +- .../src/main/java/datadog/trace/core/CoreTracer.java | 10 +++------- .../bootstrap/instrumentation/api/AgentTracer.java | 12 +++--------- 6 files changed, 10 insertions(+), 20 deletions(-) diff --git a/dd-java-agent/instrumentation/akka-concurrent/src/main/java/datadog/trace/instrumentation/akka/concurrent/AkkaActorCellInstrumentation.java b/dd-java-agent/instrumentation/akka-concurrent/src/main/java/datadog/trace/instrumentation/akka/concurrent/AkkaActorCellInstrumentation.java index db55e7ceddb..25edf7bcbc2 100644 --- a/dd-java-agent/instrumentation/akka-concurrent/src/main/java/datadog/trace/instrumentation/akka/concurrent/AkkaActorCellInstrumentation.java +++ b/dd-java-agent/instrumentation/akka-concurrent/src/main/java/datadog/trace/instrumentation/akka/concurrent/AkkaActorCellInstrumentation.java @@ -81,7 +81,7 @@ public static void enter( return; } // Create an active scope with a noop span, and clean all the way to the previous scope - activateSpan(noopSpan(), false); + activateSpan(noopSpan()); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) diff --git a/dd-java-agent/instrumentation/akka-concurrent/src/main/java/datadog/trace/instrumentation/akka/concurrent/AkkaMailboxInstrumentation.java b/dd-java-agent/instrumentation/akka-concurrent/src/main/java/datadog/trace/instrumentation/akka/concurrent/AkkaMailboxInstrumentation.java index 4b6e6b8355a..c20d8d2e021 100644 --- a/dd-java-agent/instrumentation/akka-concurrent/src/main/java/datadog/trace/instrumentation/akka/concurrent/AkkaMailboxInstrumentation.java +++ b/dd-java-agent/instrumentation/akka-concurrent/src/main/java/datadog/trace/instrumentation/akka/concurrent/AkkaMailboxInstrumentation.java @@ -75,7 +75,7 @@ public static void enter() { return; } // Create an active scope with a noop span, and clean all the way to the previous scope - activateSpan(noopSpan(), false); + activateSpan(noopSpan()); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) diff --git a/dd-java-agent/instrumentation/pekko-concurrent/src/main/java/datadog/trace/instrumentation/pekko/concurrent/PekkoActorCellInstrumentation.java b/dd-java-agent/instrumentation/pekko-concurrent/src/main/java/datadog/trace/instrumentation/pekko/concurrent/PekkoActorCellInstrumentation.java index 9f242c70b3b..c5d21d91d9e 100644 --- a/dd-java-agent/instrumentation/pekko-concurrent/src/main/java/datadog/trace/instrumentation/pekko/concurrent/PekkoActorCellInstrumentation.java +++ b/dd-java-agent/instrumentation/pekko-concurrent/src/main/java/datadog/trace/instrumentation/pekko/concurrent/PekkoActorCellInstrumentation.java @@ -81,7 +81,7 @@ public static void enter( return; } // Create an active scope with a noop span, and clean all the way to the previous scope - activateSpan(noopSpan(), false); + activateSpan(noopSpan()); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) diff --git a/dd-java-agent/instrumentation/pekko-concurrent/src/main/java/datadog/trace/instrumentation/pekko/concurrent/PekkoMailboxInstrumentation.java b/dd-java-agent/instrumentation/pekko-concurrent/src/main/java/datadog/trace/instrumentation/pekko/concurrent/PekkoMailboxInstrumentation.java index bf8772e5a9f..a881c22fb07 100644 --- a/dd-java-agent/instrumentation/pekko-concurrent/src/main/java/datadog/trace/instrumentation/pekko/concurrent/PekkoMailboxInstrumentation.java +++ b/dd-java-agent/instrumentation/pekko-concurrent/src/main/java/datadog/trace/instrumentation/pekko/concurrent/PekkoMailboxInstrumentation.java @@ -76,7 +76,7 @@ public static void enter() { return; } // Create an active scope with a noop span, and clean all the way to the previous scope - activateSpan(noopSpan(), false); + activateSpan(noopSpan()); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) diff --git a/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java b/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java index 320610bdd60..9a5dc7dc603 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java @@ -906,18 +906,14 @@ public AgentSpan startSpan( .start(); } - public AgentScope activateSpan(final AgentSpan span) { - return activateSpan(span, DEFAULT_ASYNC_PROPAGATING); - } - @Override - public AgentScope activateSpan(AgentSpan span, boolean isAsyncPropagating) { - return scopeManager.activate(span, ScopeSource.INSTRUMENTATION, isAsyncPropagating); + public AgentScope activateSpan(AgentSpan span) { + return scopeManager.activate(span, ScopeSource.INSTRUMENTATION, DEFAULT_ASYNC_PROPAGATING); } @Override public AgentScope activateManualSpan(final AgentSpan span) { - return scopeManager.activate(span, ScopeSource.MANUAL); + return scopeManager.activate(span, ScopeSource.MANUAL /* inherit async propagation flag */); } @Override diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTracer.java b/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTracer.java index 17ee75761f7..aaeafaca395 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTracer.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTracer.java @@ -1,7 +1,5 @@ package datadog.trace.bootstrap.instrumentation.api; -import static datadog.trace.api.ConfigDefaults.DEFAULT_ASYNC_PROPAGATING; - import datadog.trace.api.ConfigDefaults; import datadog.trace.api.DDTraceId; import datadog.trace.api.EndpointCheckpointer; @@ -86,11 +84,7 @@ public static AgentSpan startSpan( } public static AgentScope activateSpan(final AgentSpan span) { - return get().activateSpan(span, DEFAULT_ASYNC_PROPAGATING); - } - - public static AgentScope activateSpan(final AgentSpan span, final boolean isAsyncPropagating) { - return get().activateSpan(span, isAsyncPropagating); + return get().activateSpan(span); } /** @@ -339,7 +333,7 @@ AgentSpan startSpan( long startTimeMicros); /** Activate a span from inside auto-instrumentation. */ - AgentScope activateSpan(AgentSpan span, boolean isAsyncPropagating); + AgentScope activateSpan(AgentSpan span); /** Activate a span from outside auto-instrumentation, i.e. a manual or custom span. */ AgentScope activateManualSpan(AgentSpan span); @@ -480,7 +474,7 @@ public AgentSpan startSpan( } @Override - public AgentScope activateSpan(final AgentSpan span, final boolean isAsyncPropagating) { + public AgentScope activateSpan(final AgentSpan span) { return NoopScope.INSTANCE; } From 7475368c15bde0340702d54ef3783a8a7deea9d5 Mon Sep 17 00:00:00 2001 From: Laplie Anderson Date: Fri, 14 Mar 2025 11:27:59 -0400 Subject: [PATCH 42/98] Use internal artifact proxy for Gitlab jobs (#8554) * Use internal proxy for maven artifacts in Gitlab * fix proxy url --- .gitlab-ci.yml | 7 +++---- gradle/repositories.gradle | 5 +++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b027da64e23..267fe3347d3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -23,6 +23,7 @@ variables: DEPENDENCY_CACHE_POLICY: pull BUILD_CACHE_POLICY: pull GRADLE_VERSION: "8.4" # must match gradle-wrapper.properties + MAVEN_REPOSITORY_PROXY: "https://artifactual.us1.prod.dog/repository/maven-central/" JAVA_BUILD_IMAGE_VERSION: "v25.01" REPO_NOTIFICATION_CHANNEL: "#apm-java-escalations" PROFILE_TESTS: @@ -74,7 +75,7 @@ default: policy: $BUILD_CACHE_POLICY before_script: - export GRADLE_USER_HOME=`pwd`/.gradle - - export GRADLE_ARGS=" --build-cache --stacktrace --no-daemon --parallel --max-workers=$GRADLE_WORKERS" + - export GRADLE_ARGS=" --build-cache --stacktrace --no-daemon --parallel --max-workers=$GRADLE_WORKERS -PmavenRepositoryProxy=$MAVEN_REPOSITORY_PROXY" - *normalize_node_index # for weird reasons, gradle will always "chmod 700" the .gradle folder # with Gitlab caching, .gradle is always owned by root and thus gradle's chmod invocation fails @@ -199,10 +200,8 @@ muzzle: needs: [ build ] stage: tests parallel: 8 - rules: - - when: never variables: - BUILD_CACHE_TYPE: test + BUILD_CACHE_TYPE: lib script: - export SKIP_BUILDSCAN="true" - ./gradlew writeMuzzleTasksToFile $GRADLE_ARGS diff --git a/gradle/repositories.gradle b/gradle/repositories.gradle index 2b25aae70a0..0b0a3e7ecd8 100644 --- a/gradle/repositories.gradle +++ b/gradle/repositories.gradle @@ -1,4 +1,9 @@ repositories { + if (project.rootProject.hasProperty("mavenRepositoryProxy")) { + maven { + url project.rootProject.property("mavenRepositoryProxy") + } + } mavenLocal() mavenCentral() // add sonatype repository for snapshot dependencies From f6469404a55a35b2f5a4b89c919f0ae8bffeb02c Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Fri, 14 Mar 2025 15:44:45 +0000 Subject: [PATCH 43/98] Remove ScopeSource enum (#8565) --- .../src/test/groovy/TypeConverterTest.groovy | 5 ++-- .../src/test/groovy/TypeConverterTest.groovy | 5 ++-- .../src/test/groovy/TypeConverterTest.groovy | 5 ++-- .../java/datadog/trace/core/CoreTracer.java | 8 +++--- .../trace/core/monitor/HealthMetrics.java | 2 +- .../core/monitor/TracerHealthMetrics.java | 5 ++-- .../core/scopemanager/ContinuableScope.java | 11 +++++--- .../scopemanager/ContinuableScopeManager.java | 25 +++++++++++-------- .../trace/core/scopemanager/ScopeStack.java | 7 +++--- .../trace/core/PendingTraceBufferTest.groovy | 5 ++-- .../core/monitor/HealthMetricsTest.groovy | 9 +++---- .../scopemanager/ScopeManagerDepthTest.groovy | 5 ++-- .../core/scopemanager/ScopeManagerTest.groovy | 15 ++++++----- .../opentracing/TypeConverterTest.groovy | 5 ++-- .../instrumentation/api/ScopeSource.java | 17 ------------- 15 files changed, 56 insertions(+), 73 deletions(-) delete mode 100644 internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/ScopeSource.java diff --git a/dd-java-agent/instrumentation/opentelemetry/opentelemetry-0.3/src/test/groovy/TypeConverterTest.groovy b/dd-java-agent/instrumentation/opentelemetry/opentelemetry-0.3/src/test/groovy/TypeConverterTest.groovy index 657d79cb67d..7bc4b64953b 100644 --- a/dd-java-agent/instrumentation/opentelemetry/opentelemetry-0.3/src/test/groovy/TypeConverterTest.groovy +++ b/dd-java-agent/instrumentation/opentelemetry/opentelemetry-0.3/src/test/groovy/TypeConverterTest.groovy @@ -3,7 +3,6 @@ import datadog.trace.api.DDSpanId import datadog.trace.api.DDTraceId import datadog.trace.api.sampling.PrioritySampling import datadog.trace.api.datastreams.NoopPathwayContext -import datadog.trace.bootstrap.instrumentation.api.ScopeSource import datadog.trace.core.DDSpan import datadog.trace.core.DDSpanContext import datadog.trace.core.PendingTrace @@ -52,8 +51,8 @@ class TypeConverterTest extends AgentTestRunner { def context = createTestSpanContext() def span1 = new DDSpan("test", 0, context, null) def span2 = new DDSpan("test", 0, context, null) - def scope1 = scopeManager.activate(span1, ScopeSource.MANUAL) - def scope2 = scopeManager.activate(span2, ScopeSource.MANUAL) + def scope1 = scopeManager.activateManualSpan(span1) + def scope2 = scopeManager.activateManualSpan(span2) expect: // return the same wrapper for the same scope typeConverter.toScope(scope1) is typeConverter.toScope(scope1) diff --git a/dd-java-agent/instrumentation/opentracing/api-0.31/src/test/groovy/TypeConverterTest.groovy b/dd-java-agent/instrumentation/opentracing/api-0.31/src/test/groovy/TypeConverterTest.groovy index 3728010d4ee..be34e94442a 100644 --- a/dd-java-agent/instrumentation/opentracing/api-0.31/src/test/groovy/TypeConverterTest.groovy +++ b/dd-java-agent/instrumentation/opentracing/api-0.31/src/test/groovy/TypeConverterTest.groovy @@ -3,7 +3,6 @@ import datadog.trace.api.DDSpanId import datadog.trace.api.DDTraceId import datadog.trace.api.sampling.PrioritySampling import datadog.trace.api.datastreams.NoopPathwayContext -import datadog.trace.bootstrap.instrumentation.api.ScopeSource import datadog.trace.core.DDSpan import datadog.trace.core.DDSpanContext import datadog.trace.core.PendingTrace @@ -57,8 +56,8 @@ class TypeConverterTest extends AgentTestRunner { def context = createTestSpanContext() def span1 = new DDSpan("test", 0, context, null) def span2 = new DDSpan("test", 0, context, null) - def scope1 = scopeManager.activate(span1, ScopeSource.MANUAL) - def scope2 = scopeManager.activate(span2, ScopeSource.MANUAL) + def scope1 = scopeManager.activateManualSpan(span1) + def scope2 = scopeManager.activateManualSpan(span2) expect: // return the same wrapper for the same scope typeConverter.toScope(scope1, true) is typeConverter.toScope(scope1, true) diff --git a/dd-java-agent/instrumentation/opentracing/api-0.32/src/test/groovy/TypeConverterTest.groovy b/dd-java-agent/instrumentation/opentracing/api-0.32/src/test/groovy/TypeConverterTest.groovy index ca3c4eaff49..c1855eb4657 100644 --- a/dd-java-agent/instrumentation/opentracing/api-0.32/src/test/groovy/TypeConverterTest.groovy +++ b/dd-java-agent/instrumentation/opentracing/api-0.32/src/test/groovy/TypeConverterTest.groovy @@ -3,7 +3,6 @@ import datadog.trace.api.DDSpanId import datadog.trace.api.DDTraceId import datadog.trace.api.sampling.PrioritySampling import datadog.trace.api.datastreams.NoopPathwayContext -import datadog.trace.bootstrap.instrumentation.api.ScopeSource import datadog.trace.core.DDSpan import datadog.trace.core.DDSpanContext import datadog.trace.core.PendingTrace @@ -57,8 +56,8 @@ class TypeConverterTest extends AgentTestRunner { def context = createTestSpanContext() def span1 = new DDSpan("test", 0, context, null) def span2 = new DDSpan("test", 0, context, null) - def scope1 = scopeManager.activate(span1, ScopeSource.MANUAL) - def scope2 = scopeManager.activate(span2, ScopeSource.MANUAL) + def scope1 = scopeManager.activateManualSpan(span1) + def scope2 = scopeManager.activateManualSpan(span2) expect: // return the same wrapper for the same scope typeConverter.toScope(scope1, true) is typeConverter.toScope(scope1, true) diff --git a/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java b/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java index 9a5dc7dc603..217b4d1a5b0 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java @@ -1,7 +1,6 @@ package datadog.trace.core; import static datadog.communication.monitor.DDAgentStatsDClientManager.statsDClientManager; -import static datadog.trace.api.ConfigDefaults.DEFAULT_ASYNC_PROPAGATING; import static datadog.trace.api.DDTags.DJM_ENABLED; import static datadog.trace.api.DDTags.DSM_ENABLED; import static datadog.trace.api.DDTags.PROFILING_CONTEXT_ENGINE; @@ -61,7 +60,6 @@ import datadog.trace.bootstrap.instrumentation.api.AgentTracer; import datadog.trace.bootstrap.instrumentation.api.BlackHoleSpan; import datadog.trace.bootstrap.instrumentation.api.ProfilingContextIntegration; -import datadog.trace.bootstrap.instrumentation.api.ScopeSource; import datadog.trace.bootstrap.instrumentation.api.ScopeState; import datadog.trace.bootstrap.instrumentation.api.TagContext; import datadog.trace.civisibility.interceptor.CiVisibilityApmProtocolInterceptor; @@ -908,12 +906,12 @@ public AgentSpan startSpan( @Override public AgentScope activateSpan(AgentSpan span) { - return scopeManager.activate(span, ScopeSource.INSTRUMENTATION, DEFAULT_ASYNC_PROPAGATING); + return scopeManager.activateSpan(span); } @Override public AgentScope activateManualSpan(final AgentSpan span) { - return scopeManager.activate(span, ScopeSource.MANUAL /* inherit async propagation flag */); + return scopeManager.activateManualSpan(span); } @Override @@ -923,7 +921,7 @@ public AgentScope.Continuation captureActiveSpan() { @Override public AgentScope.Continuation captureSpan(final AgentSpan span) { - return scopeManager.captureSpan(span, ScopeSource.INSTRUMENTATION.id()); + return scopeManager.captureSpan(span); } @Override diff --git a/dd-trace-core/src/main/java/datadog/trace/core/monitor/HealthMetrics.java b/dd-trace-core/src/main/java/datadog/trace/core/monitor/HealthMetrics.java index f0dd6cc8859..47ec862b258 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/monitor/HealthMetrics.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/monitor/HealthMetrics.java @@ -51,7 +51,7 @@ public void onFinishSpan() {} public void onCreateTrace() {} - public void onScopeCloseError(int scopeSource) {} + public void onScopeCloseError(boolean manual) {} public void onCaptureContinuation() {} diff --git a/dd-trace-core/src/main/java/datadog/trace/core/monitor/TracerHealthMetrics.java b/dd-trace-core/src/main/java/datadog/trace/core/monitor/TracerHealthMetrics.java index 684a542dcd2..20d07843ab2 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/monitor/TracerHealthMetrics.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/monitor/TracerHealthMetrics.java @@ -11,7 +11,6 @@ import datadog.trace.api.StatsDClient; import datadog.trace.api.cache.RadixTreeCache; -import datadog.trace.bootstrap.instrumentation.api.ScopeSource; import datadog.trace.common.writer.RemoteApi; import datadog.trace.core.DDSpan; import datadog.trace.util.AgentTaskScheduler; @@ -282,9 +281,9 @@ public void onCreateTrace() { } @Override - public void onScopeCloseError(int scopeSource) { + public void onScopeCloseError(boolean manual) { scopeCloseErrors.inc(); - if (scopeSource == ScopeSource.MANUAL.id()) { + if (manual) { userScopeCloseErrors.inc(); } } diff --git a/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScope.java b/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScope.java index a07333b11c8..7993f885f92 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScope.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScope.java @@ -6,11 +6,16 @@ import datadog.trace.bootstrap.instrumentation.api.AgentScope; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.AttachableWrapper; -import datadog.trace.bootstrap.instrumentation.api.ScopeSource; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import javax.annotation.Nonnull; class ContinuableScope implements AgentScope, AttachableWrapper { + + // different sources of scopes + static final byte INSTRUMENTATION = 0; + static final byte MANUAL = 1; + static final byte ITERATION = 2; + private final ContinuableScopeManager scopeManager; final AgentSpan span; // package-private so scopeManager can access it directly @@ -58,8 +63,8 @@ public final void close() { } byte source = source(); - scopeManager.healthMetrics.onScopeCloseError(source); - if (source == ScopeSource.MANUAL.id() && scopeManager.strictMode) { + scopeManager.healthMetrics.onScopeCloseError(source == MANUAL); + if (source == MANUAL && scopeManager.strictMode) { throw new RuntimeException("Tried to close " + span + " scope when not on top"); } } diff --git a/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScopeManager.java b/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScopeManager.java index 83589add514..174d87e7503 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScopeManager.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScopeManager.java @@ -3,6 +3,9 @@ import static datadog.trace.api.ConfigDefaults.DEFAULT_ASYNC_PROPAGATING; import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.noopScope; import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.noopSpan; +import static datadog.trace.core.scopemanager.ContinuableScope.INSTRUMENTATION; +import static datadog.trace.core.scopemanager.ContinuableScope.ITERATION; +import static datadog.trace.core.scopemanager.ContinuableScope.MANUAL; import static java.util.concurrent.TimeUnit.MINUTES; import static java.util.concurrent.TimeUnit.NANOSECONDS; import static java.util.concurrent.TimeUnit.SECONDS; @@ -16,7 +19,6 @@ import datadog.trace.bootstrap.instrumentation.api.AgentTracer; import datadog.trace.bootstrap.instrumentation.api.ProfilerContext; import datadog.trace.bootstrap.instrumentation.api.ProfilingContextIntegration; -import datadog.trace.bootstrap.instrumentation.api.ScopeSource; import datadog.trace.bootstrap.instrumentation.api.ScopeState; import datadog.trace.bootstrap.instrumentation.api.ScopeStateAware; import datadog.trace.core.monitor.HealthMetrics; @@ -39,6 +41,7 @@ * ScopeInterceptors to provide additional functionality. */ public final class ContinuableScopeManager implements ScopeStateAware { + static final Logger log = LoggerFactory.getLogger(ContinuableScopeManager.class); static final RatelimitedLogger ratelimitedLog = new RatelimitedLogger(log, 1, MINUTES); static final long iterationKeepAlive = @@ -82,13 +85,12 @@ public ContinuableScopeManager( this.profilingContextIntegration = profilingContextIntegration; } - public AgentScope activate(final AgentSpan span, final ScopeSource source) { - return activate(span, source.id(), false, /* ignored */ false); + public AgentScope activateSpan(final AgentSpan span) { + return activate(span, INSTRUMENTATION, true, DEFAULT_ASYNC_PROPAGATING); } - public AgentScope activate( - final AgentSpan span, final ScopeSource source, boolean isAsyncPropagating) { - return activate(span, source.id(), true, isAsyncPropagating); + public AgentScope activateManualSpan(final AgentSpan span) { + return activate(span, MANUAL, false, /* ignored */ false); } public AgentScope.Continuation captureActiveSpan() { @@ -100,7 +102,11 @@ public AgentScope.Continuation captureActiveSpan() { } } - public AgentScope.Continuation captureSpan(final AgentSpan span, byte source) { + public AgentScope.Continuation captureSpan(final AgentSpan span) { + return captureSpan(span, INSTRUMENTATION); + } + + private AgentScope.Continuation captureSpan(final AgentSpan span, byte source) { ScopeContinuation continuation = new ScopeContinuation(this, span, source); continuation.register(); healthMetrics.onCaptureContinuation(); @@ -193,7 +199,7 @@ public void closePrevious(final boolean finishSpan) { // close any immediately previous iteration scope final ContinuableScope top = scopeStack.top; - if (top != null && top.source() == ScopeSource.ITERATION.id()) { + if (top != null && top.source() == ITERATION) { if (iterationKeepAlive > 0) { // skip depth check because cancelling is cheap cancelRootIterationScopeCleanup(scopeStack, top); } @@ -223,8 +229,7 @@ public AgentScope activateNext(final AgentSpan span) { boolean asyncPropagation = top != null ? top.isAsyncPropagating() : DEFAULT_ASYNC_PROPAGATING; final ContinuableScope scope = - new ContinuableScope( - this, span, ScopeSource.ITERATION.id(), asyncPropagation, createScopeState(span)); + new ContinuableScope(this, span, ITERATION, asyncPropagation, createScopeState(span)); if (iterationKeepAlive > 0 && currentDepth == 0) { // no surrounding scope to aid cleanup, so use background task instead diff --git a/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ScopeStack.java b/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ScopeStack.java index 78ea56d7d8a..f7de0f7d101 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ScopeStack.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ScopeStack.java @@ -1,7 +1,8 @@ package datadog.trace.core.scopemanager; +import static datadog.trace.core.scopemanager.ContinuableScope.ITERATION; + import datadog.trace.bootstrap.instrumentation.api.ProfilingContextIntegration; -import datadog.trace.bootstrap.instrumentation.api.ScopeSource; import java.util.ArrayDeque; /** @@ -77,7 +78,7 @@ boolean checkTop(final ContinuableScope expectedScope) { */ final boolean checkOverdueScopes(final ContinuableScope expectedScope) { // we already know 'top' isn't the expected scope, so just need to check its source - if (top == null || top.source() != ScopeSource.ITERATION.id()) { + if (top == null || top.source() != ITERATION) { return false; } // avoid calling close() as we're already in that method, instead just clear any @@ -86,7 +87,7 @@ final boolean checkOverdueScopes(final ContinuableScope expectedScope) { top.span.finishWithEndToEnd(); // now do the same for any previous iteration scopes ahead of the expected scope for (ContinuableScope scope : stack) { - if (scope.source() != ScopeSource.ITERATION.id()) { + if (scope.source() != ITERATION) { return expectedScope.equals(scope); } else { scope.clearReferences(); diff --git a/dd-trace-core/src/test/groovy/datadog/trace/core/PendingTraceBufferTest.groovy b/dd-trace-core/src/test/groovy/datadog/trace/core/PendingTraceBufferTest.groovy index eec8bb3befd..c0a97cfd3ed 100644 --- a/dd-trace-core/src/test/groovy/datadog/trace/core/PendingTraceBufferTest.groovy +++ b/dd-trace-core/src/test/groovy/datadog/trace/core/PendingTraceBufferTest.groovy @@ -8,7 +8,6 @@ import datadog.trace.api.DDTraceId import datadog.trace.api.flare.TracerFlare import datadog.trace.api.time.SystemTimeSource import datadog.trace.api.datastreams.NoopPathwayContext -import datadog.trace.bootstrap.instrumentation.api.ScopeSource import datadog.trace.context.TraceScope import datadog.trace.core.monitor.HealthMetrics import datadog.trace.core.propagation.PropagationTags @@ -495,8 +494,8 @@ class PendingTraceBufferTest extends DDSpecification { def addContinuation(DDSpan span) { - def scope = scopeManager.activate(span, ScopeSource.INSTRUMENTATION, true) - continuations << scopeManager.captureSpan(span, ScopeSource.INSTRUMENTATION.id()) + def scope = scopeManager.activateSpan(span) + continuations << scopeManager.captureSpan(span) scope.close() return span } diff --git a/dd-trace-core/src/test/groovy/datadog/trace/core/monitor/HealthMetricsTest.groovy b/dd-trace-core/src/test/groovy/datadog/trace/core/monitor/HealthMetricsTest.groovy index 9897af4ae4b..30bb3a77c9b 100644 --- a/dd-trace-core/src/test/groovy/datadog/trace/core/monitor/HealthMetricsTest.groovy +++ b/dd-trace-core/src/test/groovy/datadog/trace/core/monitor/HealthMetricsTest.groovy @@ -2,7 +2,6 @@ package datadog.trace.core.monitor import datadog.trace.api.StatsDClient import datadog.trace.api.sampling.PrioritySampling -import datadog.trace.bootstrap.instrumentation.api.ScopeSource import datadog.trace.common.writer.RemoteApi import datadog.trace.common.writer.RemoteWriter import spock.lang.Ignore @@ -365,21 +364,21 @@ class HealthMetricsTest extends Specification { } def "test onScopeCloseError"() { setup: - def latch = new CountDownLatch(1 + (source == ScopeSource.MANUAL ? 1 : 0)) + def latch = new CountDownLatch(1 + (manual ? 1 : 0)) def healthMetrics = new TracerHealthMetrics(new Latched(statsD, latch), 100, TimeUnit.MILLISECONDS) healthMetrics.start() when: - healthMetrics.onScopeCloseError(source.id()) + healthMetrics.onScopeCloseError(manual) latch.await(5, TimeUnit.SECONDS) then: 1 * statsD.count("scope.close.error", 1, _) - if (source == ScopeSource.MANUAL) { + if (manual) { 1 * statsD.count("scope.user.close.error", 1, _) } cleanup: healthMetrics.close() where: - source << ScopeSource.values() + manual << [false, true] } def "test onScopeStackOverflow"() { setup: diff --git a/dd-trace-core/src/test/groovy/datadog/trace/core/scopemanager/ScopeManagerDepthTest.groovy b/dd-trace-core/src/test/groovy/datadog/trace/core/scopemanager/ScopeManagerDepthTest.groovy index 8e4cd6c7644..4c7a1176ee7 100644 --- a/dd-trace-core/src/test/groovy/datadog/trace/core/scopemanager/ScopeManagerDepthTest.groovy +++ b/dd-trace-core/src/test/groovy/datadog/trace/core/scopemanager/ScopeManagerDepthTest.groovy @@ -3,7 +3,6 @@ package datadog.trace.core.scopemanager import datadog.trace.api.config.TracerConfig import datadog.trace.bootstrap.instrumentation.api.AgentScope import datadog.trace.bootstrap.instrumentation.api.AgentSpan -import datadog.trace.bootstrap.instrumentation.api.ScopeSource import datadog.trace.common.writer.ListWriter import datadog.trace.core.test.DDCoreSpecification @@ -35,7 +34,7 @@ class ScopeManagerDepthTest extends DDCoreSpecification { scope == noopScope() when: "activate a noop scope over the limit" - scope = scopeManager.activate(noopSpan(), ScopeSource.MANUAL) + scope = scopeManager.activateManualSpan(noopSpan()) then: "still have a noop instance" scope == noopScope() @@ -77,7 +76,7 @@ class ScopeManagerDepthTest extends DDCoreSpecification { scopeManager.scopeStack().depth() == defaultLimit + 1 when: "activate a noop span" - scope = scopeManager.activate(noopSpan(), ScopeSource.MANUAL) + scope = scopeManager.activateManualSpan(noopSpan()) then: "a real instance is still returned" scope != noopScope() diff --git a/dd-trace-core/src/test/groovy/datadog/trace/core/scopemanager/ScopeManagerTest.groovy b/dd-trace-core/src/test/groovy/datadog/trace/core/scopemanager/ScopeManagerTest.groovy index 819783d2ae7..b337609873c 100644 --- a/dd-trace-core/src/test/groovy/datadog/trace/core/scopemanager/ScopeManagerTest.groovy +++ b/dd-trace-core/src/test/groovy/datadog/trace/core/scopemanager/ScopeManagerTest.groovy @@ -9,7 +9,6 @@ import datadog.trace.api.scopemanager.ExtendedScopeListener import datadog.trace.bootstrap.instrumentation.api.AgentScope import datadog.trace.bootstrap.instrumentation.api.AgentSpan import datadog.trace.bootstrap.instrumentation.api.ProfilingContextIntegration -import datadog.trace.bootstrap.instrumentation.api.ScopeSource import datadog.trace.common.writer.ListWriter import datadog.trace.api.scopemanager.ScopeListener import datadog.trace.context.TraceScope @@ -156,7 +155,7 @@ class ScopeManagerTest extends DDCoreSpecification { def "non-ddspan activation results in a continuable scope"() { when: - def scope = scopeManager.activate(noopSpan(), ScopeSource.INSTRUMENTATION) + def scope = scopeManager.activateSpan(noopSpan()) then: scopeManager.active() == scope @@ -443,14 +442,14 @@ class ScopeManagerTest extends DDCoreSpecification { def state = Mock(Stateful) when: - AgentScope scope1 = scopeManager.activate(span, ScopeSource.INSTRUMENTATION) + AgentScope scope1 = scopeManager.activateSpan(span) then: assertEvents([ACTIVATE]) 1 * profilingContext.newScopeState(_) >> state when: - AgentScope scope2 = scopeManager.activate(span, ScopeSource.INSTRUMENTATION) + AgentScope scope2 = scopeManager.activateSpan(span) then: 'Activating the same span multiple times does not create a new scope' assertEvents([ACTIVATE]) @@ -638,13 +637,13 @@ class ScopeManagerTest extends DDCoreSpecification { def span = tracer.buildSpan("test", "test").start() when: - AgentScope scope1 = scopeManager.activate(span, ScopeSource.INSTRUMENTATION) + AgentScope scope1 = scopeManager.activateSpan(span) then: assertEvents([ACTIVATE]) when: - AgentScope scope2 = scopeManager.activate(span, ScopeSource.INSTRUMENTATION) + AgentScope scope2 = scopeManager.activateSpan(span) then: 'Activating the same span multiple times does not create a new scope' assertEvents([ACTIVATE]) @@ -874,7 +873,7 @@ class ScopeManagerTest extends DDCoreSpecification { def span = tracer.buildSpan("test", "test").start() when: - AgentScope scope = scopeManager.activate(span, ScopeSource.INSTRUMENTATION) + AgentScope scope = scopeManager.activateSpan(span) then: assertEvents([ACTIVATE]) @@ -904,7 +903,7 @@ class ScopeManagerTest extends DDCoreSpecification { def span = tracer.buildSpan("test", "test").start() when: - AgentScope scope = scopeManager.activate(span, ScopeSource.INSTRUMENTATION) + AgentScope scope = scopeManager.activateSpan(span) then: assertEvents([ACTIVATE]) diff --git a/dd-trace-ot/src/test/groovy/datadog/opentracing/TypeConverterTest.groovy b/dd-trace-ot/src/test/groovy/datadog/opentracing/TypeConverterTest.groovy index 2bdceb91b0f..a9e5f7a8494 100644 --- a/dd-trace-ot/src/test/groovy/datadog/opentracing/TypeConverterTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/opentracing/TypeConverterTest.groovy @@ -4,7 +4,6 @@ import datadog.trace.api.DDSpanId import datadog.trace.api.DDTraceId import datadog.trace.api.sampling.PrioritySampling import datadog.trace.api.datastreams.NoopPathwayContext -import datadog.trace.bootstrap.instrumentation.api.ScopeSource import datadog.trace.core.CoreTracer import datadog.trace.core.DDSpan import datadog.trace.core.DDSpanContext @@ -58,8 +57,8 @@ class TypeConverterTest extends DDSpecification { def context = createTestSpanContext() def span1 = new DDSpan("test", 0, context, null) def span2 = new DDSpan("test", 0, context, null) - def scope1 = scopeManager.activate(span1, ScopeSource.MANUAL) - def scope2 = scopeManager.activate(span2, ScopeSource.MANUAL) + def scope1 = scopeManager.activateManualSpan(span1) + def scope2 = scopeManager.activateManualSpan(span2) expect: // return the same wrapper for the same scope typeConverter.toScope(scope1, true) is typeConverter.toScope(scope1, true) diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/ScopeSource.java b/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/ScopeSource.java deleted file mode 100644 index b801c83273f..00000000000 --- a/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/ScopeSource.java +++ /dev/null @@ -1,17 +0,0 @@ -package datadog.trace.bootstrap.instrumentation.api; - -public enum ScopeSource { - INSTRUMENTATION((byte) 0), - MANUAL((byte) 1), - ITERATION((byte) 2); - - private final byte id; - - ScopeSource(byte id) { - this.id = id; - } - - public byte id() { - return id; - } -} From e8eb022f5d96323243ed46377279a5bc55f58267 Mon Sep 17 00:00:00 2001 From: Bruce Bujon Date: Mon, 17 Mar 2025 11:12:28 +0100 Subject: [PATCH 44/98] fix(ci): Mark tests as flaky (#8568) --- .../groovy/datadog/smoketest/LogInjectionSmokeTest.groovy | 3 +++ .../groovy/datadog/smoketest/SampleTraceSmokeTest.groovy | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/dd-smoke-tests/log-injection/src/test/groovy/datadog/smoketest/LogInjectionSmokeTest.groovy b/dd-smoke-tests/log-injection/src/test/groovy/datadog/smoketest/LogInjectionSmokeTest.groovy index e36b922ab78..f1f8211f0c6 100644 --- a/dd-smoke-tests/log-injection/src/test/groovy/datadog/smoketest/LogInjectionSmokeTest.groovy +++ b/dd-smoke-tests/log-injection/src/test/groovy/datadog/smoketest/LogInjectionSmokeTest.groovy @@ -3,11 +3,13 @@ package datadog.smoketest import com.squareup.moshi.Moshi import com.squareup.moshi.Types import datadog.trace.api.config.GeneralConfig +import datadog.trace.test.util.Flaky import spock.lang.AutoCleanup import spock.lang.Shared import static datadog.trace.api.config.TraceInstrumentationConfig.TRACE_128_BIT_TRACEID_LOGGING_ENABLED import static datadog.trace.api.config.TracerConfig.TRACE_128_BIT_TRACEID_GENERATION_ENABLED +import static datadog.trace.test.util.Predicates.IBM8 import static java.util.concurrent.TimeUnit.SECONDS /** @@ -254,6 +256,7 @@ abstract class LogInjectionSmokeTest extends AbstractSmokeTest { return unmangled.split(" ")[1..2] } + @Flaky(condition = IBM8) def "check raw file injection"() { when: def count = waitForTraceCount(2) diff --git a/dd-smoke-tests/sample-trace/src/test/groovy/datadog/smoketest/SampleTraceSmokeTest.groovy b/dd-smoke-tests/sample-trace/src/test/groovy/datadog/smoketest/SampleTraceSmokeTest.groovy index cab3fa97596..e7ee1d7211d 100644 --- a/dd-smoke-tests/sample-trace/src/test/groovy/datadog/smoketest/SampleTraceSmokeTest.groovy +++ b/dd-smoke-tests/sample-trace/src/test/groovy/datadog/smoketest/SampleTraceSmokeTest.groovy @@ -1,5 +1,9 @@ package datadog.smoketest +import datadog.trace.test.util.Flaky + +import static datadog.trace.test.util.Predicates.IBM8 + class SampleTraceSmokeTest extends AbstractSmokeTest { @Override @@ -21,6 +25,7 @@ class SampleTraceSmokeTest extends AbstractSmokeTest { processBuilder.directory(new File(buildDirectory)) } + @Flaky(condition = IBM8) def 'sample traces are sent'() { when: waitForTraceCount(10) From 7ff940b5c90a6b057b15cef521e202532e1db8c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20=C3=81lvarez=20=C3=81lvarez?= Date: Mon, 17 Mar 2025 13:46:46 +0100 Subject: [PATCH 45/98] Prevent before callsites targeting constructors in super calls (#8549) Prevent before callsites targeting calls to super in constructors --- .../plugin/csi/impl/AdviceGeneratorImpl.java | 9 +++ .../plugin/csi/impl/ext/IastExtension.java | 8 +- .../plugin/csi/util/CallSiteConstants.java | 2 + .../csi/impl/AdviceGeneratorTest.groovy | 3 + .../csi/impl/assertion/AdviceAssert.groovy | 5 ++ .../csi/impl/assertion/AssertBuilder.groovy | 6 +- .../csi/impl/ext/IastExtensionTest.groovy | 4 +- .../csi/CallSiteBenchmarkInstrumentation.java | 3 + .../agent/tooling/bytebuddy/csi/Advices.java | 78 ++++++++++++++++++- .../bytebuddy/csi/CallSiteTransformer.java | 49 +++++++++++- .../agent/tooling/csi/CallSiteAdvice.java | 9 +++ .../trace/agent/tooling/csi/CallSites.java | 13 ++-- .../agent/tooling/csi/BaseCallSiteTest.groovy | 19 +++-- .../csi/CallSiteInstrumentationTest.groovy | 6 +- .../src/test/java/MockCallSites.java | 4 +- .../src/test/java/MockRaspCallSites.java | 4 +- .../io/ObjectInputStreamCallSiteTest.groovy | 25 +++++- .../foo/bar/TestCustomObjectInputStream.java | 12 +++ 18 files changed, 226 insertions(+), 33 deletions(-) create mode 100644 dd-java-agent/instrumentation/java-io/src/test/java/foo/bar/TestCustomObjectInputStream.java diff --git a/buildSrc/call-site-instrumentation-plugin/src/main/java/datadog/trace/plugin/csi/impl/AdviceGeneratorImpl.java b/buildSrc/call-site-instrumentation-plugin/src/main/java/datadog/trace/plugin/csi/impl/AdviceGeneratorImpl.java index 04c7a9be704..14efc4a42d4 100644 --- a/buildSrc/call-site-instrumentation-plugin/src/main/java/datadog/trace/plugin/csi/impl/AdviceGeneratorImpl.java +++ b/buildSrc/call-site-instrumentation-plugin/src/main/java/datadog/trace/plugin/csi/impl/AdviceGeneratorImpl.java @@ -2,6 +2,7 @@ import static com.github.javaparser.ast.Modifier.Keyword.PUBLIC; import static datadog.trace.plugin.csi.impl.CallSiteFactory.typeResolver; +import static datadog.trace.plugin.csi.util.CallSiteConstants.ADVICE_TYPE_CLASS; import static datadog.trace.plugin.csi.util.CallSiteConstants.AUTO_SERVICE_FQDN; import static datadog.trace.plugin.csi.util.CallSiteConstants.CALL_SITES_CLASS; import static datadog.trace.plugin.csi.util.CallSiteConstants.CALL_SITES_FQCN; @@ -185,20 +186,24 @@ private void addAdviceLambda( final MethodType pointCut = spec.getPointcut(); final BlockStmt adviceBody = new BlockStmt(); final Expression advice; + final String type; if (spec.isInvokeDynamic()) { advice = invokeDynamicAdviceSignature(adviceBody); } else { advice = invokeAdviceSignature(adviceBody); } if (spec instanceof BeforeSpecification) { + type = "BEFORE"; writeStackOperations(spec, adviceBody); writeAdviceMethodCall(spec, adviceBody); writeOriginalMethodCall(spec, adviceBody); } else if (spec instanceof AfterSpecification) { + type = "AFTER"; writeStackOperations(spec, adviceBody); writeOriginalMethodCall(spec, adviceBody); writeAdviceMethodCall(spec, adviceBody); } else { + type = "AROUND"; writeAdviceMethodCall(spec, adviceBody); } body.addStatement( @@ -207,6 +212,10 @@ private void addAdviceLambda( .setName("addAdvice") .setArguments( new NodeList<>( + new FieldAccessExpr() + .setScope( + new TypeExpr(new ClassOrInterfaceType().setName(ADVICE_TYPE_CLASS))) + .setName(type), new StringLiteralExpr(pointCut.getOwner().getInternalName()), new StringLiteralExpr(pointCut.getMethodName()), new StringLiteralExpr(pointCut.getMethodType().getDescriptor()), diff --git a/buildSrc/call-site-instrumentation-plugin/src/main/java/datadog/trace/plugin/csi/impl/ext/IastExtension.java b/buildSrc/call-site-instrumentation-plugin/src/main/java/datadog/trace/plugin/csi/impl/ext/IastExtension.java index e86ca097d85..46e7c96dc89 100644 --- a/buildSrc/call-site-instrumentation-plugin/src/main/java/datadog/trace/plugin/csi/impl/ext/IastExtension.java +++ b/buildSrc/call-site-instrumentation-plugin/src/main/java/datadog/trace/plugin/csi/impl/ext/IastExtension.java @@ -364,19 +364,19 @@ private static LambdaExpr findAdviceLambda( final MethodType pointcut = spec.getPointcut(); for (final MethodCallExpr add : addAdvices) { final NodeList arguments = add.getArguments(); - final String owner = arguments.get(0).asStringLiteralExpr().asString(); + final String owner = arguments.get(1).asStringLiteralExpr().asString(); if (!owner.equals(pointcut.getOwner().getInternalName())) { continue; } - final String method = arguments.get(1).asStringLiteralExpr().asString(); + final String method = arguments.get(2).asStringLiteralExpr().asString(); if (!method.equals(pointcut.getMethodName())) { continue; } - final String description = arguments.get(2).asStringLiteralExpr().asString(); + final String description = arguments.get(3).asStringLiteralExpr().asString(); if (!description.equals(pointcut.getMethodType().getDescriptor())) { continue; } - return arguments.get(3).asLambdaExpr(); + return arguments.get(4).asLambdaExpr(); } throw new IllegalArgumentException("Cannot find lambda expression for pointcut " + pointcut); } diff --git a/buildSrc/call-site-instrumentation-plugin/src/main/java/datadog/trace/plugin/csi/util/CallSiteConstants.java b/buildSrc/call-site-instrumentation-plugin/src/main/java/datadog/trace/plugin/csi/util/CallSiteConstants.java index 390df62d9a9..8613af8958d 100644 --- a/buildSrc/call-site-instrumentation-plugin/src/main/java/datadog/trace/plugin/csi/util/CallSiteConstants.java +++ b/buildSrc/call-site-instrumentation-plugin/src/main/java/datadog/trace/plugin/csi/util/CallSiteConstants.java @@ -30,6 +30,8 @@ private CallSiteConstants() {} public static final String HAS_ENABLED_PROPERTY_CLASS = CALL_SITES_CLASS + ".HasEnabledProperty"; + public static final String ADVICE_TYPE_CLASS = "AdviceType"; + public static final String STACK_DUP_MODE_CLASS = "StackDupMode"; public static final String METHOD_HANDLER_CLASS = "MethodHandler"; diff --git a/buildSrc/call-site-instrumentation-plugin/src/test/groovy/datadog/trace/plugin/csi/impl/AdviceGeneratorTest.groovy b/buildSrc/call-site-instrumentation-plugin/src/test/groovy/datadog/trace/plugin/csi/impl/AdviceGeneratorTest.groovy index 3ec2a6da5c5..2958c292cac 100644 --- a/buildSrc/call-site-instrumentation-plugin/src/test/groovy/datadog/trace/plugin/csi/impl/AdviceGeneratorTest.groovy +++ b/buildSrc/call-site-instrumentation-plugin/src/test/groovy/datadog/trace/plugin/csi/impl/AdviceGeneratorTest.groovy @@ -44,6 +44,7 @@ final class AdviceGeneratorTest extends BaseCsiPluginTest { interfaces(CallSites) helpers(BeforeAdvice) advices(0) { + type("BEFORE") pointcut('java/security/MessageDigest', 'getInstance', '(Ljava/lang/String;)Ljava/security/MessageDigest;') statements( 'handler.dupParameters(descriptor, StackDupMode.COPY);', @@ -76,6 +77,7 @@ final class AdviceGeneratorTest extends BaseCsiPluginTest { interfaces(CallSites) helpers(AroundAdvice) advices(0) { + type("AROUND") pointcut('java/lang/String', 'replaceAll', '(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;') statements( 'handler.advice("datadog/trace/plugin/csi/impl/AdviceGeneratorTest$AroundAdvice", "around", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");' @@ -106,6 +108,7 @@ final class AdviceGeneratorTest extends BaseCsiPluginTest { interfaces(CallSites) helpers(AfterAdvice) advices(0) { + type("AFTER") pointcut('java/lang/String', 'concat', '(Ljava/lang/String;)Ljava/lang/String;') statements( 'handler.dupInvoke(owner, descriptor, StackDupMode.COPY);', diff --git a/buildSrc/call-site-instrumentation-plugin/src/test/groovy/datadog/trace/plugin/csi/impl/assertion/AdviceAssert.groovy b/buildSrc/call-site-instrumentation-plugin/src/test/groovy/datadog/trace/plugin/csi/impl/assertion/AdviceAssert.groovy index 419cc49178a..d83120a6c52 100644 --- a/buildSrc/call-site-instrumentation-plugin/src/test/groovy/datadog/trace/plugin/csi/impl/assertion/AdviceAssert.groovy +++ b/buildSrc/call-site-instrumentation-plugin/src/test/groovy/datadog/trace/plugin/csi/impl/assertion/AdviceAssert.groovy @@ -1,11 +1,16 @@ package datadog.trace.plugin.csi.impl.assertion class AdviceAssert { + protected String type protected String owner protected String method protected String descriptor protected Collection statements + void type(String type) { + assert type == this.type + } + void pointcut(String owner, String method, String descriptor) { assert owner == this.owner assert method == this.method diff --git a/buildSrc/call-site-instrumentation-plugin/src/test/groovy/datadog/trace/plugin/csi/impl/assertion/AssertBuilder.groovy b/buildSrc/call-site-instrumentation-plugin/src/test/groovy/datadog/trace/plugin/csi/impl/assertion/AssertBuilder.groovy index c8f192ca447..f80c258dfda 100644 --- a/buildSrc/call-site-instrumentation-plugin/src/test/groovy/datadog/trace/plugin/csi/impl/assertion/AssertBuilder.groovy +++ b/buildSrc/call-site-instrumentation-plugin/src/test/groovy/datadog/trace/plugin/csi/impl/assertion/AssertBuilder.groovy @@ -83,10 +83,12 @@ class AssertBuilder { return getMethodCalls(acceptMethod).findAll { it.nameAsString == 'addAdvice' }.collect { - def (owner, method, descriptor) = it.arguments.subList(0, 3)*.asStringLiteralExpr()*.asString() - final handlerLambda = it.arguments[3].asLambdaExpr() + final adviceType = it.arguments.get(0).asFieldAccessExpr().getName() + def (owner, method, descriptor) = it.arguments.subList(1, 4)*.asStringLiteralExpr()*.asString() + final handlerLambda = it.arguments[4].asLambdaExpr() final advice = handlerLambda.body.asBlockStmt().statements*.toString() return new AdviceAssert([ + type : adviceType, owner : owner, method : method, descriptor: descriptor, diff --git a/buildSrc/call-site-instrumentation-plugin/src/test/groovy/datadog/trace/plugin/csi/impl/ext/IastExtensionTest.groovy b/buildSrc/call-site-instrumentation-plugin/src/test/groovy/datadog/trace/plugin/csi/impl/ext/IastExtensionTest.groovy index 5ffe27e95b9..bcd28fad4e4 100644 --- a/buildSrc/call-site-instrumentation-plugin/src/test/groovy/datadog/trace/plugin/csi/impl/ext/IastExtensionTest.groovy +++ b/buildSrc/call-site-instrumentation-plugin/src/test/groovy/datadog/trace/plugin/csi/impl/ext/IastExtensionTest.groovy @@ -217,8 +217,8 @@ class IastExtensionTest extends BaseCsiPluginTest { return getMethodCalls(acceptMethod).findAll { it.nameAsString == 'addAdvice' }.collect { - def (owner, method, descriptor) = it.arguments.subList(0, 3)*.asStringLiteralExpr()*.asString() - final handlerLambda = it.arguments[3].asLambdaExpr() + def (owner, method, descriptor) = it.arguments.subList(1, 4)*.asStringLiteralExpr()*.asString() + final handlerLambda = it.arguments[4].asLambdaExpr() final statements = handlerLambda.body.asBlockStmt().statements final instrumentedStmt = statements.get(0).asIfStmt() final executedStmt = statements.get(1).asIfStmt() diff --git a/dd-java-agent/agent-tooling/src/jmh/java/datadog/trace/agent/tooling/bytebuddy/csi/CallSiteBenchmarkInstrumentation.java b/dd-java-agent/agent-tooling/src/jmh/java/datadog/trace/agent/tooling/bytebuddy/csi/CallSiteBenchmarkInstrumentation.java index a03865f0756..4796b15f4eb 100644 --- a/dd-java-agent/agent-tooling/src/jmh/java/datadog/trace/agent/tooling/bytebuddy/csi/CallSiteBenchmarkInstrumentation.java +++ b/dd-java-agent/agent-tooling/src/jmh/java/datadog/trace/agent/tooling/bytebuddy/csi/CallSiteBenchmarkInstrumentation.java @@ -1,5 +1,7 @@ package datadog.trace.agent.tooling.bytebuddy.csi; +import static datadog.trace.agent.tooling.csi.CallSiteAdvice.AdviceType.AROUND; + import datadog.trace.agent.tooling.csi.CallSites; import datadog.trace.agent.tooling.csi.InvokeAdvice; import datadog.trace.agent.tooling.muzzle.ReferenceMatcher; @@ -44,6 +46,7 @@ public Iterable get() { return Collections.singletonList( (container -> { container.addAdvice( + AROUND, "javax/servlet/ServletRequest", "getParameter", "(Ljava/lang/String;)Ljava/lang/String;", diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/csi/Advices.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/csi/Advices.java index a574ab0fcb4..705bebf7a87 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/csi/Advices.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/csi/Advices.java @@ -6,6 +6,8 @@ import datadog.trace.agent.tooling.bytebuddy.ClassFileLocators; import datadog.trace.agent.tooling.csi.CallSiteAdvice; import datadog.trace.agent.tooling.csi.CallSites; +import datadog.trace.agent.tooling.csi.InvokeAdvice; +import datadog.trace.agent.tooling.csi.InvokeDynamicAdvice; import java.lang.reflect.Field; import java.util.Arrays; import java.util.Collections; @@ -141,6 +143,11 @@ public CallSiteAdvice findAdvice( return methodAdvices.get(descriptor); } + /** Gets the type of advice we are dealing with */ + public byte typeOf(final CallSiteAdvice advice) { + return ((TypedAdvice) advice).getType(); + } + public String[] getHelpers() { return helpers; } @@ -176,15 +183,17 @@ public void addHelpers(final String... helperClassNames) { @Override public void addAdvice( - final String type, + final byte type, + final String owner, final String method, final String descriptor, final CallSiteAdvice advice) { final Map> typeAdvices = - advices.computeIfAbsent(type, k -> new HashMap<>()); + advices.computeIfAbsent(owner, k -> new HashMap<>()); final Map methodAdvices = typeAdvices.computeIfAbsent(method, k -> new HashMap<>()); - final CallSiteAdvice oldAdvice = methodAdvices.put(descriptor, advice); + final CallSiteAdvice oldAdvice = + methodAdvices.put(descriptor, TypedAdvice.withType(advice, type)); if (oldAdvice != null) { throw new UnsupportedOperationException( String.format( @@ -360,4 +369,67 @@ public interface Listener { void onConstantPool( @Nonnull TypeDescription type, @Nonnull ConstantPool pool, final byte[] classFile); } + + private interface TypedAdvice { + byte getType(); + + static CallSiteAdvice withType(final CallSiteAdvice advice, final byte type) { + if (advice instanceof InvokeAdvice) { + return new InvokeWithType((InvokeAdvice) advice, type); + } else { + return new InvokeDynamicWithType((InvokeDynamicAdvice) advice, type); + } + } + } + + private static class InvokeWithType implements InvokeAdvice, TypedAdvice { + private final InvokeAdvice advice; + private final byte type; + + private InvokeWithType(InvokeAdvice advice, byte type) { + this.advice = advice; + this.type = type; + } + + @Override + public byte getType() { + return type; + } + + @Override + public void apply( + final MethodHandler handler, + final int opcode, + final String owner, + final String name, + final String descriptor, + final boolean isInterface) { + advice.apply(handler, opcode, owner, name, descriptor, isInterface); + } + } + + private static class InvokeDynamicWithType implements InvokeDynamicAdvice, TypedAdvice { + private final InvokeDynamicAdvice advice; + private final byte type; + + private InvokeDynamicWithType(final InvokeDynamicAdvice advice, final byte type) { + this.advice = advice; + this.type = type; + } + + @Override + public byte getType() { + return type; + } + + @Override + public void apply( + final MethodHandler handler, + final String name, + final String descriptor, + final Handle bootstrapMethodHandle, + final Object... bootstrapMethodArguments) { + advice.apply(handler, name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments); + } + } } diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/csi/CallSiteTransformer.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/csi/CallSiteTransformer.java index 991523069c1..3b38c22891b 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/csi/CallSiteTransformer.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/csi/CallSiteTransformer.java @@ -1,5 +1,6 @@ package datadog.trace.agent.tooling.bytebuddy.csi; +import static datadog.trace.agent.tooling.csi.CallSiteAdvice.AdviceType.AFTER; import static datadog.trace.api.telemetry.LogCollector.SEND_TELEMETRY; import static net.bytebuddy.jar.asm.ClassWriter.COMPUTE_MAXS; @@ -126,7 +127,7 @@ public MethodVisitor visitMethod( private static class CallSiteMethodVisitor extends MethodVisitor implements CallSiteAdvice.MethodHandler { - private final Advices advices; + protected final Advices advices; private CallSiteMethodVisitor( @Nonnull final Advices advices, @Nonnull final MethodVisitor delegated) { @@ -144,12 +145,22 @@ public void visitMethodInsn( CallSiteAdvice advice = advices.findAdvice(owner, name, descriptor); if (advice instanceof InvokeAdvice) { - ((InvokeAdvice) advice).apply(this, opcode, owner, name, descriptor, isInterface); + invokeAdvice((InvokeAdvice) advice, opcode, owner, name, descriptor, isInterface); } else { mv.visitMethodInsn(opcode, owner, name, descriptor, isInterface); } } + protected void invokeAdvice( + final InvokeAdvice advice, + final int opcode, + final String owner, + final String name, + final String descriptor, + final boolean isInterface) { + advice.apply(this, opcode, owner, name, descriptor, isInterface); + } + @Override public void visitInvokeDynamicInsn( final String name, @@ -158,14 +169,27 @@ public void visitInvokeDynamicInsn( final Object... bootstrapMethodArguments) { CallSiteAdvice advice = advices.findAdvice(bootstrapMethodHandle); if (advice instanceof InvokeDynamicAdvice) { - ((InvokeDynamicAdvice) advice) - .apply(this, name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments); + invokeDynamicAdvice( + (InvokeDynamicAdvice) advice, + name, + descriptor, + bootstrapMethodHandle, + bootstrapMethodArguments); } else { mv.visitInvokeDynamicInsn( name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments); } } + protected void invokeDynamicAdvice( + final InvokeDynamicAdvice advice, + final String name, + final String descriptor, + final Handle bootstrapMethodHandle, + final Object... bootstrapMethodArguments) { + advice.apply(this, name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments); + } + @Override public void instruction(final int opcode) { mv.visitInsn(opcode); @@ -347,5 +371,22 @@ public void dupParameters(final String methodDescriptor, final StackDupMode mode super.dupParameters( methodDescriptor, isSuperCall ? StackDupMode.PREPEND_ARRAY_SUPER_CTOR : mode); } + + @Override + protected void invokeAdvice( + final InvokeAdvice advice, + final int opcode, + final String owner, + final String name, + final String descriptor, + final boolean isInterface) { + if (isSuperCall && advices.typeOf(advice) != AFTER) { + // TODO APPSEC-57009 calls to super are only instrumented by after call sites + // just ignore the advice and keep on + mv.visitMethodInsn(opcode, owner, name, descriptor, isInterface); + } else { + super.invokeAdvice(advice, opcode, owner, name, descriptor, isInterface); + } + } } } diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/csi/CallSiteAdvice.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/csi/CallSiteAdvice.java index 0e43f3602e8..dbe925c7b8a 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/csi/CallSiteAdvice.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/csi/CallSiteAdvice.java @@ -72,4 +72,13 @@ enum StackDupMode { /** Copies the parameters in an array and appends it */ APPEND_ARRAY } + + abstract class AdviceType { + + private AdviceType() {} + + public static final byte BEFORE = -1; + public static final byte AROUND = 0; + public static final byte AFTER = 1; + } } diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/csi/CallSites.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/csi/CallSites.java index 4fbefc851f3..6bb36ff7773 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/csi/CallSites.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/csi/CallSites.java @@ -6,22 +6,25 @@ public interface CallSites extends Consumer { interface Container { default void addAdvice( - final String type, + final byte type, + final String owner, final String method, final String descriptor, final InvokeAdvice advice) { - addAdvice(type, method, descriptor, (CallSiteAdvice) advice); + addAdvice(type, owner, method, descriptor, (CallSiteAdvice) advice); } default void addAdvice( - final String type, + final byte type, + final String owner, final String method, final String descriptor, final InvokeDynamicAdvice advice) { - addAdvice(type, method, descriptor, (CallSiteAdvice) advice); + addAdvice(type, owner, method, descriptor, (CallSiteAdvice) advice); } - void addAdvice(String type, String method, String descriptor, CallSiteAdvice advice); + void addAdvice( + byte kind, String owner, String method, String descriptor, CallSiteAdvice advice); void addHelpers(String... helperClassNames); } diff --git a/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/csi/BaseCallSiteTest.groovy b/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/csi/BaseCallSiteTest.groovy index 416092536e9..12e242e1807 100644 --- a/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/csi/BaseCallSiteTest.groovy +++ b/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/csi/BaseCallSiteTest.groovy @@ -24,18 +24,19 @@ import java.security.MessageDigest import java.lang.reflect.Method import java.security.ProtectionDomain +import static datadog.trace.agent.tooling.csi.CallSiteAdvice.AdviceType.BEFORE import static net.bytebuddy.matcher.ElementMatchers.any import static net.bytebuddy.matcher.ElementMatchers.named @CompileDynamic class BaseCallSiteTest extends DDSpecification { - protected CallSites mockCallSites(final CallSiteAdvice advice, final Pointcut target, final String... helpers) { + protected CallSites mockCallSites(final byte type = BEFORE, final CallSiteAdvice advice, final Pointcut target, final String... helpers) { return Stub(CallSites) { accept(_ as CallSites.Container) >> { final container = it[0] as CallSites.Container container.addHelpers(helpers) - container.addAdvice(target.type, target.method, target.descriptor, advice) + container.addAdvice(type, target.type, target.method, target.descriptor, advice) } } } @@ -44,10 +45,16 @@ class BaseCallSiteTest extends DDSpecification { final advices = [:] as Map>> final helpers = [] as Set final container = Stub(CallSites.Container) { - addAdvice(_ as String, _ as String, _ as String, _ as CallSiteAdvice) >> { - advices.computeIfAbsent(it[0] as String, t -> [:]) - .computeIfAbsent(it[1] as String, m -> [:]) - .put(it[2] as String, it[3] as CallSiteAdvice) + addAdvice(_, _ as String, _ as String, _ as String, _ as CallSiteAdvice) >> { + final type = it[0] as byte + final owner = it[1] as String + final method = it[2] as String + final descriptor = it[3] as String + final advice = it[4] as CallSiteAdvice + advices + .computeIfAbsent(owner, t -> [:]) + .computeIfAbsent(method, m -> [:]) + .put(descriptor, advice) } addHelpers(_ as String[]) >> { Collections.addAll(helpers, it[0] as String[]) diff --git a/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/csi/CallSiteInstrumentationTest.groovy b/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/csi/CallSiteInstrumentationTest.groovy index b56b94779ad..1b37b8891e7 100644 --- a/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/csi/CallSiteInstrumentationTest.groovy +++ b/dd-java-agent/agent-tooling/src/test/groovy/datadog/trace/agent/tooling/csi/CallSiteInstrumentationTest.groovy @@ -9,6 +9,8 @@ import net.bytebuddy.jar.asm.Type import java.util.concurrent.atomic.AtomicInteger import static datadog.trace.agent.tooling.csi.CallSiteAdvice.StackDupMode.PREPEND_ARRAY_CTOR +import static datadog.trace.agent.tooling.csi.CallSiteAdvice.AdviceType.AFTER +import static datadog.trace.agent.tooling.csi.CallSiteAdvice.AdviceType.BEFORE class CallSiteInstrumentationTest extends BaseCallSiteTest { @@ -84,7 +86,7 @@ class CallSiteInstrumentationTest extends BaseCallSiteTest { ) } } - final callSiteTransformer = new CallSiteTransformer(mockAdvices([mockCallSites(advice, pointcut)])) + final callSiteTransformer = new CallSiteTransformer(mockAdvices([mockCallSites(AFTER, advice, pointcut)])) when: final transformedClass = transformType(source, target, callSiteTransformer) @@ -101,7 +103,7 @@ class CallSiteInstrumentationTest extends BaseCallSiteTest { @Override void accept(final Container container) { final pointcut = buildPointcut(String.getDeclaredMethod('concat', String)) - container.addAdvice(pointcut.type, pointcut.method, pointcut.descriptor, new StringConcatAdvice()) + container.addAdvice(BEFORE, pointcut.type, pointcut.method, pointcut.descriptor, new StringConcatAdvice()) } } diff --git a/dd-java-agent/instrumentation/iast-instrumenter/src/test/java/MockCallSites.java b/dd-java-agent/instrumentation/iast-instrumenter/src/test/java/MockCallSites.java index 8b3888a5edf..b569d2d874d 100644 --- a/dd-java-agent/instrumentation/iast-instrumenter/src/test/java/MockCallSites.java +++ b/dd-java-agent/instrumentation/iast-instrumenter/src/test/java/MockCallSites.java @@ -1,3 +1,5 @@ +import static datadog.trace.agent.tooling.csi.CallSiteAdvice.AdviceType.BEFORE; + import datadog.trace.agent.tooling.csi.CallSiteAdvice; import datadog.trace.agent.tooling.csi.CallSites; import datadog.trace.api.iast.IastCallSites; @@ -5,6 +7,6 @@ public class MockCallSites implements IastCallSites, CallSites { @Override public void accept(final Container container) { - container.addAdvice("type", "method", "descriptor", (CallSiteAdvice) null); + container.addAdvice(BEFORE, "type", "method", "descriptor", (CallSiteAdvice) null); } } diff --git a/dd-java-agent/instrumentation/iast-instrumenter/src/test/java/MockRaspCallSites.java b/dd-java-agent/instrumentation/iast-instrumenter/src/test/java/MockRaspCallSites.java index 408c7850931..5db049a3383 100644 --- a/dd-java-agent/instrumentation/iast-instrumenter/src/test/java/MockRaspCallSites.java +++ b/dd-java-agent/instrumentation/iast-instrumenter/src/test/java/MockRaspCallSites.java @@ -1,3 +1,5 @@ +import static datadog.trace.agent.tooling.csi.CallSiteAdvice.AdviceType.BEFORE; + import datadog.trace.agent.tooling.csi.CallSiteAdvice; import datadog.trace.agent.tooling.csi.CallSites; import datadog.trace.api.appsec.RaspCallSites; @@ -5,6 +7,6 @@ public class MockRaspCallSites implements RaspCallSites, CallSites { @Override public void accept(final Container container) { - container.addAdvice("type", "method", "descriptor", (CallSiteAdvice) null); + container.addAdvice(BEFORE, "typeRasp", "methodRasp", "descriptorRasp", (CallSiteAdvice) null); } } diff --git a/dd-java-agent/instrumentation/java-io/src/test/groovy/datadog/trace/instrumentation/java/io/ObjectInputStreamCallSiteTest.groovy b/dd-java-agent/instrumentation/java-io/src/test/groovy/datadog/trace/instrumentation/java/io/ObjectInputStreamCallSiteTest.groovy index d7c73006b05..38c997bd5ff 100644 --- a/dd-java-agent/instrumentation/java-io/src/test/groovy/datadog/trace/instrumentation/java/io/ObjectInputStreamCallSiteTest.groovy +++ b/dd-java-agent/instrumentation/java-io/src/test/groovy/datadog/trace/instrumentation/java/io/ObjectInputStreamCallSiteTest.groovy @@ -5,6 +5,8 @@ import datadog.trace.api.iast.InstrumentationBridge import datadog.trace.api.iast.sink.UntrustedDeserializationModule import foo.bar.TestObjectInputStreamSuite +import foo.bar.TestCustomObjectInputStream + class ObjectInputStreamCallSiteTest extends AgentTestRunner { @Override @@ -17,12 +19,29 @@ class ObjectInputStreamCallSiteTest extends AgentTestRunner { final module = Mock(UntrustedDeserializationModule) InstrumentationBridge.registerIastModule(module) - final InputStream inputStream = new ByteArrayInputStream(new byte[0]) - when: - TestObjectInputStreamSuite.init(inputStream) + TestObjectInputStreamSuite.init(inputStream()) then: 1 * module.onObject(_) } + + void 'test super call to ObjectInputStream.'() { + given: + final iastModule = Mock(UntrustedDeserializationModule) + InstrumentationBridge.registerIastModule(iastModule) + + when: + new TestCustomObjectInputStream(inputStream()) + + then: + // TODO APPSEC-57009 calls to super are only instrumented by after callsites + 0 * iastModule.onObject(_) + } + + private static InputStream inputStream() { + final baos = new ByteArrayOutputStream() + new ObjectOutputStream(baos).writeObject([:]) + return new ByteArrayInputStream(baos.toByteArray()) + } } diff --git a/dd-java-agent/instrumentation/java-io/src/test/java/foo/bar/TestCustomObjectInputStream.java b/dd-java-agent/instrumentation/java-io/src/test/java/foo/bar/TestCustomObjectInputStream.java new file mode 100644 index 00000000000..0010d56fe9a --- /dev/null +++ b/dd-java-agent/instrumentation/java-io/src/test/java/foo/bar/TestCustomObjectInputStream.java @@ -0,0 +1,12 @@ +package foo.bar; + +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; + +public class TestCustomObjectInputStream extends ObjectInputStream { + + public TestCustomObjectInputStream(final InputStream in) throws IOException { + super(in); + } +} From 3d8d129a4df55150437996e4b75e240be0cc92cb Mon Sep 17 00:00:00 2001 From: Sarah Chen Date: Mon, 17 Mar 2025 09:27:33 -0400 Subject: [PATCH 46/98] Add JDK built-in support for UDS on Java 16+ (#8314) * Use the JDK's built-in support for Unix Domain Sockets on Java 16+ * First draft of timeout test. * Add server to test. * Fix build.gradle file. * Add debugging statements. * Second draft of timeout test. * Update getInputStream to use a selector. * Clean code. * Adjust dd-java-agent build.gradle. * Revert dd-java-agent build.gradle change * Revert another build.gradle change. * Try specifying setSrcDirs. * Try changing compatibility version. * Revert previous two changes. * Avoid implementation dependency for Java17. * Make gradle dependency more specific and add testImplementation to socket-utils. * Add synchronization to ensure that server starts before client connects. * Try this... * Add print statements. * Add catch statement. * Refactor getInputStream and getOutputStream. * Address PR comments. * Add test for when timeout is 0. * Add config option. --------- Co-authored-by: Stuart McCulloch --- .../trace/api/config/GeneralConfig.java | 1 + gradle/java_no_deps.gradle | 10 +- .../main/java/datadog/trace/api/Config.java | 10 + .../datadog/trace/api/ConfigTest.groovy | 3 + utils/socket-utils/build.gradle | 25 +- .../socket/UnixDomainSocketFactory.java | 13 +- .../common/socket/TunnelingJdkSocket.java | 255 ++++++++++++++++++ .../common/socket/TunnelingJdkSocketTest.java | 105 ++++++++ 8 files changed, 417 insertions(+), 5 deletions(-) create mode 100644 utils/socket-utils/src/main/java17/datadog/common/socket/TunnelingJdkSocket.java create mode 100644 utils/socket-utils/src/test/java/datadog/common/socket/TunnelingJdkSocketTest.java diff --git a/dd-trace-api/src/main/java/datadog/trace/api/config/GeneralConfig.java b/dd-trace-api/src/main/java/datadog/trace/api/config/GeneralConfig.java index 9a5caf5c4a2..a882a097e59 100644 --- a/dd-trace-api/src/main/java/datadog/trace/api/config/GeneralConfig.java +++ b/dd-trace-api/src/main/java/datadog/trace/api/config/GeneralConfig.java @@ -94,6 +94,7 @@ public final class GeneralConfig { public static final String AGENTLESS_LOG_SUBMISSION_LEVEL = "agentless.log.submission.level"; public static final String AGENTLESS_LOG_SUBMISSION_URL = "agentless.log.submission.url"; public static final String APM_TRACING_ENABLED = "apm.tracing.enabled"; + public static final String JDK_SOCKET_ENABLED = "jdk.socket.enabled"; private GeneralConfig() {} } diff --git a/gradle/java_no_deps.gradle b/gradle/java_no_deps.gradle index 4a05431c074..95a87f0e8ed 100644 --- a/gradle/java_no_deps.gradle +++ b/gradle/java_no_deps.gradle @@ -59,9 +59,15 @@ if (project.hasProperty('minJavaVersionForTests') && project.getProperty('minJav targetCompatibility = version } + // "socket-utils" is only set to compileOnly because the implementation dependency incorrectly adds Java17 classes to all jar prefixes. + // This causes the AgentJarIndex to search for other non-Java17 classes in the wrong prefix location and fail to resolve class names. dependencies { - compileOnly files(project.sourceSets."main_$name".compileClasspath) - implementation files(project.sourceSets."main_$name".output) + if ("${project.projectDir}".endsWith("socket-utils")) { + compileOnly files(project.sourceSets."main_$name".output) + } else { + compileOnly files(project.sourceSets."main_$name".compileClasspath) + implementation files(project.sourceSets."main_$name".output) + } } jar { diff --git a/internal-api/src/main/java/datadog/trace/api/Config.java b/internal-api/src/main/java/datadog/trace/api/Config.java index 599e96c5cfd..635d9b8230f 100644 --- a/internal-api/src/main/java/datadog/trace/api/Config.java +++ b/internal-api/src/main/java/datadog/trace/api/Config.java @@ -563,6 +563,8 @@ public static String getHostName() { private final boolean apmTracingEnabled; private final Set experimentalFeaturesEnabled; + private final boolean jdkSocketEnabled; + // Read order: System Properties -> Env Variables, [-> properties file], [-> default value] private Config() { this(ConfigProvider.createDefault()); @@ -1959,6 +1961,8 @@ PROFILING_DATADOG_PROFILER_ENABLED, isDatadogProfilerSafeInCurrentEnvironment()) this.apmTracingEnabled = configProvider.getBoolean(GeneralConfig.APM_TRACING_ENABLED, true); + this.jdkSocketEnabled = configProvider.getBoolean(JDK_SOCKET_ENABLED, true); + log.debug("New instance: {}", this); } @@ -3537,6 +3541,10 @@ public boolean isApmTracingEnabled() { return apmTracingEnabled; } + public boolean isJdkSocketEnabled() { + return jdkSocketEnabled; + } + /** @return A map of tags to be applied only to the local application root span. */ public Map getLocalRootSpanTags() { final Map runtimeTags = getRuntimeTags(); @@ -4784,6 +4792,8 @@ public String toString() { + dataJobsCommandPattern + ", apmTracingEnabled=" + apmTracingEnabled + + ", jdkSocketEnabled=" + + jdkSocketEnabled + ", cloudRequestPayloadTagging=" + cloudRequestPayloadTagging + ", cloudResponsePayloadTagging=" diff --git a/internal-api/src/test/groovy/datadog/trace/api/ConfigTest.groovy b/internal-api/src/test/groovy/datadog/trace/api/ConfigTest.groovy index f9594ab1165..d603b41a3bf 100644 --- a/internal-api/src/test/groovy/datadog/trace/api/ConfigTest.groovy +++ b/internal-api/src/test/groovy/datadog/trace/api/ConfigTest.groovy @@ -51,6 +51,7 @@ import static datadog.trace.api.config.GeneralConfig.GLOBAL_TAGS import static datadog.trace.api.config.GeneralConfig.HEALTH_METRICS_ENABLED import static datadog.trace.api.config.GeneralConfig.HEALTH_METRICS_STATSD_HOST import static datadog.trace.api.config.GeneralConfig.HEALTH_METRICS_STATSD_PORT +import static datadog.trace.api.config.GeneralConfig.JDK_SOCKET_ENABLED import static datadog.trace.api.config.GeneralConfig.PERF_METRICS_ENABLED import static datadog.trace.api.config.GeneralConfig.SERVICE_NAME import static datadog.trace.api.config.GeneralConfig.SITE @@ -261,6 +262,7 @@ class ConfigTest extends DDSpecification { prop.setProperty(DYNAMIC_INSTRUMENTATION_EXCLUDE_FILES, "exclude file") prop.setProperty(EXCEPTION_REPLAY_ENABLED, "true") prop.setProperty(TRACE_X_DATADOG_TAGS_MAX_LENGTH, "128") + prop.setProperty(JDK_SOCKET_ENABLED, "false") when: Config config = Config.get(prop) @@ -354,6 +356,7 @@ class ConfigTest extends DDSpecification { config.dynamicInstrumentationInstrumentTheWorld == true config.dynamicInstrumentationExcludeFiles == "exclude file" config.debuggerExceptionEnabled == true + config.jdkSocketEnabled == false config.xDatadogTagsMaxLength == 128 } diff --git a/utils/socket-utils/build.gradle b/utils/socket-utils/build.gradle index eb09cca849f..d2e05364414 100644 --- a/utils/socket-utils/build.gradle +++ b/utils/socket-utils/build.gradle @@ -1,8 +1,31 @@ +ext { + minJavaVersionForTests = JavaVersion.VERSION_17 +} + apply from: "$rootDir/gradle/java.gradle" +apply plugin: "idea" + +[compileMain_java17Java, compileTestJava].each { + it.configure { + setJavaVersion(it, 17) + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } +} dependencies { implementation libs.slf4j implementation project(':internal-api') + implementation libs.jnr.unixsocket + testImplementation files(sourceSets.main_java17.output) +} + +forbiddenApisMain_java17 { + failOnMissingClasses = false +} - implementation group: 'com.github.jnr', name: 'jnr-unixsocket', version: libs.versions.jnr.unixsocket.get() +idea { + module { + jdkName = '17' + } } diff --git a/utils/socket-utils/src/main/java/datadog/common/socket/UnixDomainSocketFactory.java b/utils/socket-utils/src/main/java/datadog/common/socket/UnixDomainSocketFactory.java index bb1929f369b..8e141b939f2 100644 --- a/utils/socket-utils/src/main/java/datadog/common/socket/UnixDomainSocketFactory.java +++ b/utils/socket-utils/src/main/java/datadog/common/socket/UnixDomainSocketFactory.java @@ -3,6 +3,7 @@ import static java.util.concurrent.TimeUnit.MINUTES; import datadog.trace.api.Config; +import datadog.trace.api.Platform; import datadog.trace.relocate.api.RatelimitedLogger; import java.io.File; import java.io.IOException; @@ -24,6 +25,8 @@ public final class UnixDomainSocketFactory extends SocketFactory { private static final Logger log = LoggerFactory.getLogger(UnixDomainSocketFactory.class); + private static final boolean JDK_SUPPORTS_UDS = Platform.isJavaVersionAtLeast(16); + private final RatelimitedLogger rlLog = new RatelimitedLogger(log, 5, MINUTES); private final File path; @@ -35,8 +38,14 @@ public UnixDomainSocketFactory(final File path) { @Override public Socket createSocket() throws IOException { try { - final UnixSocketChannel channel = UnixSocketChannel.open(); - return new TunnelingUnixSocket(path, channel); + if (JDK_SUPPORTS_UDS && Config.get().isJdkSocketEnabled()) { + try { + return new TunnelingJdkSocket(path.toPath()); + } catch (Throwable ignore) { + // fall back to jnr-unixsocket library + } + } + return new TunnelingUnixSocket(path, UnixSocketChannel.open()); } catch (Throwable e) { if (Config.get().isAgentConfiguredUsingDefault()) { // fall back to port if we previously auto-discovered this socket file diff --git a/utils/socket-utils/src/main/java17/datadog/common/socket/TunnelingJdkSocket.java b/utils/socket-utils/src/main/java17/datadog/common/socket/TunnelingJdkSocket.java new file mode 100644 index 00000000000..6db94aa15ac --- /dev/null +++ b/utils/socket-utils/src/main/java17/datadog/common/socket/TunnelingJdkSocket.java @@ -0,0 +1,255 @@ +package datadog.common.socket; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.SocketAddress; +import java.net.SocketException; +import java.net.UnixDomainSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.SocketChannel; +import java.nio.file.Path; +import java.util.Iterator; +import java.util.Set; + +/** + * Subtype UNIX socket for a higher-fidelity impersonation of TCP sockets. This is named "tunneling" + * because it assumes the ultimate destination has a hostname and port. + * + *

Bsed on {@link TunnelingUnixSocket}; adapted to use the built-in UDS support added in Java 16. + */ +final class TunnelingJdkSocket extends Socket { + private final SocketAddress unixSocketAddress; + private InetSocketAddress inetSocketAddress; + + private SocketChannel unixSocketChannel; + + private int timeout; + private boolean shutIn; + private boolean shutOut; + private boolean closed; + + TunnelingJdkSocket(final Path path) { + this.unixSocketAddress = UnixDomainSocketAddress.of(path); + } + + TunnelingJdkSocket(final Path path, final InetSocketAddress address) { + this(path); + inetSocketAddress = address; + } + + @Override + public boolean isConnected() { + return null != unixSocketChannel; + } + + @Override + public boolean isInputShutdown() { + return shutIn; + } + + @Override + public boolean isOutputShutdown() { + return shutOut; + } + + @Override + public boolean isClosed() { + return closed; + } + + @Override + public synchronized void setSoTimeout(int timeout) throws SocketException { + if (isClosed()) { + throw new SocketException("Socket is closed"); + } + if (timeout < 0) { + throw new IllegalArgumentException("Socket timeout can't be negative"); + } + this.timeout = timeout; + } + + @Override + public synchronized int getSoTimeout() throws SocketException { + if (isClosed()) { + throw new SocketException("Socket is closed"); + } + return timeout; + } + + @Override + public void connect(final SocketAddress endpoint) throws IOException { + if (isClosed()) { + throw new SocketException("Socket is closed"); + } + if (isConnected()) { + throw new SocketException("Socket is already connected"); + } + inetSocketAddress = (InetSocketAddress) endpoint; + unixSocketChannel = SocketChannel.open(unixSocketAddress); + } + + // `timeout` is intentionally ignored here, like in the jnr-unixsocket implementation. + // See: + // https://github.com/jnr/jnr-unixsocket/blob/master/src/main/java/jnr/unixsocket/UnixSocket.java#L89-L97 + @Override + public void connect(final SocketAddress endpoint, final int timeout) throws IOException { + if (isClosed()) { + throw new SocketException("Socket is closed"); + } + if (isConnected()) { + throw new SocketException("Socket is already connected"); + } + inetSocketAddress = (InetSocketAddress) endpoint; + unixSocketChannel = SocketChannel.open(unixSocketAddress); + } + + @Override + public SocketChannel getChannel() { + return unixSocketChannel; + } + + @Override + public InputStream getInputStream() throws IOException { + if (isClosed()) { + throw new SocketException("Socket is closed"); + } + if (!isConnected()) { + throw new SocketException("Socket is not connected"); + } + if (isInputShutdown()) { + throw new SocketException("Socket input is shutdown"); + } + + return new InputStream() { + private final ByteBuffer buffer = ByteBuffer.allocate(8192); + private final Selector selector = Selector.open(); + + { + unixSocketChannel.configureBlocking(false); + unixSocketChannel.register(selector, SelectionKey.OP_READ); + } + + @Override + public int read() throws IOException { + byte[] nextByte = new byte[1]; + return (read(nextByte, 0, 1) == -1) ? -1 : (nextByte[0] & 0xFF); + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + buffer.clear(); + + int readyChannels = selector.select(timeout); + if (readyChannels == 0) { + System.out.println("Timeout (" + timeout + "ms) while waiting for data."); + return 0; + } + + Set selectedKeys = selector.selectedKeys(); + Iterator keyIterator = selectedKeys.iterator(); + while (keyIterator.hasNext()) { + SelectionKey key = keyIterator.next(); + keyIterator.remove(); + if (key.isReadable()) { + int r = unixSocketChannel.read(buffer); + if (r == -1) { + return -1; + } + buffer.flip(); + len = Math.min(r, len); + buffer.get(b, off, len); + return len; + } + } + return 0; + } + + @Override + public void close() throws IOException { + selector.close(); + } + }; + } + + @Override + public OutputStream getOutputStream() throws IOException { + if (isClosed()) { + throw new SocketException("Socket is closed"); + } + if (!isConnected()) { + throw new SocketException("Socket is not connected"); + } + if (isInputShutdown()) { + throw new SocketException("Socket output is shutdown"); + } + + return new OutputStream() { + @Override + public void write(int b) throws IOException { + byte[] array = ByteBuffer.allocate(4).putInt(b).array(); + write(array, 0, 4); + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + ByteBuffer buffer = ByteBuffer.wrap(b, off, len); + + while (buffer.hasRemaining()) { + unixSocketChannel.write(buffer); + } + } + }; + } + + @Override + public void shutdownInput() throws IOException { + if (isClosed()) { + throw new SocketException("Socket is closed"); + } + if (!isConnected()) { + throw new SocketException("Socket is not connected"); + } + if (isInputShutdown()) { + throw new SocketException("Socket input is already shutdown"); + } + unixSocketChannel.shutdownInput(); + shutIn = true; + } + + @Override + public void shutdownOutput() throws IOException { + if (isClosed()) { + throw new SocketException("Socket is closed"); + } + if (!isConnected()) { + throw new SocketException("Socket is not connected"); + } + if (isOutputShutdown()) { + throw new SocketException("Socket output is already shutdown"); + } + unixSocketChannel.shutdownOutput(); + shutOut = true; + } + + @Override + public InetAddress getInetAddress() { + return inetSocketAddress.getAddress(); + } + + @Override + public void close() throws IOException { + if (isClosed()) { + return; + } + if (null != unixSocketChannel) { + unixSocketChannel.close(); + } + closed = true; + } +} diff --git a/utils/socket-utils/src/test/java/datadog/common/socket/TunnelingJdkSocketTest.java b/utils/socket-utils/src/test/java/datadog/common/socket/TunnelingJdkSocketTest.java new file mode 100644 index 00000000000..05cf96e94d8 --- /dev/null +++ b/utils/socket-utils/src/test/java/datadog/common/socket/TunnelingJdkSocketTest.java @@ -0,0 +1,105 @@ +package datadog.common.socket; + +import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively; +import static org.junit.jupiter.api.Assertions.fail; + +import datadog.trace.api.Config; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.StandardProtocolFamily; +import java.net.UnixDomainSocketAddress; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.Duration; +import java.util.concurrent.atomic.AtomicBoolean; +import org.junit.jupiter.api.Test; + +public class TunnelingJdkSocketTest { + + private static final AtomicBoolean isServerRunning = new AtomicBoolean(false); + + @Test + public void testTimeout() throws Exception { + if (!Config.get().isJdkSocketEnabled()) { + System.out.println( + "TunnelingJdkSocket usage is disabled. Enable it by setting the property 'JDK_SOCKET_ENABLED' to 'true'."); + return; + } + + int testTimeout = 3000; + Path socketPath = getSocketPath(); + UnixDomainSocketAddress socketAddress = UnixDomainSocketAddress.of(socketPath); + startServer(socketAddress); + TunnelingJdkSocket clientSocket = createClient(socketPath); + + // Test that the socket unblocks when timeout is set to >0 + clientSocket.setSoTimeout(1000); + assertTimeoutPreemptively( + Duration.ofMillis(testTimeout), () -> clientSocket.getInputStream().read()); + + // Test that the socket blocks indefinitely when timeout is set to 0, per + // https://docs.oracle.com/en/java/javase/16/docs/api//java.base/java/net/Socket.html#setSoTimeout(int). + clientSocket.setSoTimeout(0); + boolean infiniteTimeOut = false; + try { + assertTimeoutPreemptively( + Duration.ofMillis(testTimeout), () -> clientSocket.getInputStream().read()); + } catch (AssertionError e) { + infiniteTimeOut = true; + } + if (!infiniteTimeOut) { + fail("Test failed: Expected infinite blocking when timeout is set to 0."); + } + + clientSocket.close(); + isServerRunning.set(false); + } + + private Path getSocketPath() throws IOException { + Path socketPath = Files.createTempFile("testSocket", null); + Files.delete(socketPath); + socketPath.toFile().deleteOnExit(); + return socketPath; + } + + private static void startServer(UnixDomainSocketAddress socketAddress) { + Thread serverThread = + new Thread( + () -> { + try (ServerSocketChannel serverChannel = + ServerSocketChannel.open(StandardProtocolFamily.UNIX)) { + serverChannel.bind(socketAddress); + isServerRunning.set(true); + + synchronized (isServerRunning) { + isServerRunning.notifyAll(); + } + + while (isServerRunning.get()) { + SocketChannel clientChannel = serverChannel.accept(); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + serverThread.start(); + + synchronized (isServerRunning) { + while (!isServerRunning.get()) { + try { + isServerRunning.wait(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + } + } + + private TunnelingJdkSocket createClient(Path socketPath) throws IOException { + TunnelingJdkSocket clientSocket = new TunnelingJdkSocket(socketPath); + clientSocket.connect(new InetSocketAddress("localhost", 0)); + return clientSocket; + } +} From 8327a8f0928dc4204970c7e1295d7b1c89a35bf2 Mon Sep 17 00:00:00 2001 From: Nikita Tkachenko <121111529+nikita-tkachenko-datadog@users.noreply.github.com> Date: Mon, 17 Mar 2025 15:30:09 +0100 Subject: [PATCH 47/98] Allow to manually set PR info (#8566) --- .../CiVisibilityRepoServices.java | 20 ++++++++++++++- .../civisibility/CiVisibilityServices.java | 3 ++- .../datadog/trace/civisibility/Constants.java | 25 +++++++++++++++++++ .../domain/AbstractTestModule.java | 2 +- .../domain/AbstractTestSession.java | 2 +- .../trace/civisibility/domain/TestImpl.java | 2 +- .../civisibility/domain/TestSuiteImpl.java | 2 +- .../buildsystem/BuildSystemModuleImpl.java | 4 +-- .../buildsystem/BuildSystemSessionImpl.java | 5 ++-- .../domain/headless/HeadlessTestModule.java | 4 +-- .../domain/headless/HeadlessTestSession.java | 5 ++-- .../trace/api/civisibility/CIConstants.java | 7 ------ 12 files changed, 58 insertions(+), 23 deletions(-) create mode 100644 dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/Constants.java diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/CiVisibilityRepoServices.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/CiVisibilityRepoServices.java index 6078e61880e..7ebbe41c005 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/CiVisibilityRepoServices.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/CiVisibilityRepoServices.java @@ -9,6 +9,7 @@ import datadog.trace.civisibility.ci.CIProviderInfo; import datadog.trace.civisibility.ci.CITagsProvider; import datadog.trace.civisibility.ci.PullRequestInfo; +import datadog.trace.civisibility.ci.env.CiEnvironment; import datadog.trace.civisibility.codeowners.Codeowners; import datadog.trace.civisibility.codeowners.CodeownersProvider; import datadog.trace.civisibility.codeowners.NoCodeowners; @@ -39,6 +40,7 @@ import java.nio.file.Paths; import java.util.Map; import java.util.concurrent.CompletableFuture; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -64,7 +66,7 @@ public class CiVisibilityRepoServices { ciProvider = ciProviderInfo.getProvider(); CIInfo ciInfo = ciProviderInfo.buildCIInfo(); - PullRequestInfo pullRequestInfo = ciProviderInfo.buildPullRequestInfo(); + PullRequestInfo pullRequestInfo = buildPullRequestInfo(services.environment, ciProviderInfo); if (pullRequestInfo.isNotEmpty()) { LOGGER.info("PR detected: {}", pullRequestInfo); @@ -107,6 +109,22 @@ public class CiVisibilityRepoServices { } } + @Nonnull + private static PullRequestInfo buildPullRequestInfo( + CiEnvironment environment, CIProviderInfo ciProviderInfo) { + PullRequestInfo ciProviderPrInfo = ciProviderInfo.buildPullRequestInfo(); + if (ciProviderPrInfo.isNotEmpty()) { + return ciProviderPrInfo; + } + + // could not get PR info from CI provider, + // check if it was set manually + return new PullRequestInfo( + null, + environment.get(Constants.DDCI_PULL_REQUEST_TARGET_SHA), + environment.get(Constants.DDCI_PULL_REQUEST_SOURCE_SHA)); + } + private static String getRepoRoot(CIInfo ciInfo, GitClient.Factory gitClientFactory) { String ciWorkspace = ciInfo.getNormalizedCiWorkspace(); if (Strings.isNotBlank(ciWorkspace)) { diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/CiVisibilityServices.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/CiVisibilityServices.java index c2b3f22fa20..f46986f31a5 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/CiVisibilityServices.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/CiVisibilityServices.java @@ -67,6 +67,7 @@ public class CiVisibilityServices { final CiVisibilityMetricCollector metricCollector; final BackendApi backendApi; final JvmInfoFactory jvmInfoFactory; + final CiEnvironment environment; final CIProviderInfoFactory ciProviderInfoFactory; final GitClient.Factory gitClientFactory; final GitInfoProvider gitInfoProvider; @@ -87,7 +88,7 @@ public class CiVisibilityServices { this.jvmInfoFactory = new CachingJvmInfoFactory(config, new JvmInfoFactoryImpl()); this.gitClientFactory = buildGitClientFactory(config, metricCollector); - CiEnvironment environment = buildCiEnvironment(config, sco); + this.environment = buildCiEnvironment(config, sco); this.ciProviderInfoFactory = new CIProviderInfoFactory(config, environment); this.linesResolver = new BestEffortLinesResolver(new CompilerAidedLinesResolver(), new ByteCodeLinesResolver()); diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/Constants.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/Constants.java new file mode 100644 index 00000000000..d662f9b5e58 --- /dev/null +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/Constants.java @@ -0,0 +1,25 @@ +package datadog.trace.civisibility; + +/** Constants that are not part of the internal (or external) API. */ +public interface Constants { + + /** + * Indicates that early flakiness detection feature was aborted in a test session because too many + * test cases were considered new. + */ + String EFD_ABORT_REASON_FAULTY = "faulty"; + + String CI_VISIBILITY_INSTRUMENTATION_NAME = "civisibility"; + + /** + * Env var containing SHA of the feature branch HEAD commit when running in a PR. Set manually if + * the necessary data is not exposed by the CI provider + */ + String DDCI_PULL_REQUEST_SOURCE_SHA = "DDCI_PULL_REQUEST_SOURCE_SHA"; + + /** + * Env var containing SHA of the target branch HEAD commit when running in a PR. Set manually if + * the necessary data is not exposed by the CI provider + */ + String DDCI_PULL_REQUEST_TARGET_SHA = "DDCI_PULL_REQUEST_TARGET_SHA"; +} diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/AbstractTestModule.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/AbstractTestModule.java index 18f383106bd..5e99ea598f2 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/AbstractTestModule.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/AbstractTestModule.java @@ -1,6 +1,6 @@ package datadog.trace.civisibility.domain; -import static datadog.trace.api.civisibility.CIConstants.CI_VISIBILITY_INSTRUMENTATION_NAME; +import static datadog.trace.civisibility.Constants.CI_VISIBILITY_INSTRUMENTATION_NAME; import datadog.trace.api.Config; import datadog.trace.api.civisibility.telemetry.CiVisibilityCountMetric; diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/AbstractTestSession.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/AbstractTestSession.java index 90681d6a02e..51d2b1ceec9 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/AbstractTestSession.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/AbstractTestSession.java @@ -1,7 +1,7 @@ package datadog.trace.civisibility.domain; import static datadog.trace.api.TracePropagationStyle.NONE; -import static datadog.trace.api.civisibility.CIConstants.CI_VISIBILITY_INSTRUMENTATION_NAME; +import static datadog.trace.civisibility.Constants.CI_VISIBILITY_INSTRUMENTATION_NAME; import datadog.trace.api.Config; import datadog.trace.api.DDTraceId; diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/TestImpl.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/TestImpl.java index 270c3c1c7ee..f869618117d 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/TestImpl.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/TestImpl.java @@ -1,8 +1,8 @@ package datadog.trace.civisibility.domain; import static datadog.json.JsonMapper.toJson; -import static datadog.trace.api.civisibility.CIConstants.CI_VISIBILITY_INSTRUMENTATION_NAME; import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activateSpan; +import static datadog.trace.civisibility.Constants.CI_VISIBILITY_INSTRUMENTATION_NAME; import datadog.trace.api.Config; import datadog.trace.api.DDTraceId; diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/TestSuiteImpl.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/TestSuiteImpl.java index 65ee32ad17f..93facb1a93e 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/TestSuiteImpl.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/TestSuiteImpl.java @@ -1,8 +1,8 @@ package datadog.trace.civisibility.domain; import static datadog.json.JsonMapper.toJson; -import static datadog.trace.api.civisibility.CIConstants.CI_VISIBILITY_INSTRUMENTATION_NAME; import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activateSpan; +import static datadog.trace.civisibility.Constants.CI_VISIBILITY_INSTRUMENTATION_NAME; import datadog.trace.api.Config; import datadog.trace.api.civisibility.DDTestSuite; diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/buildsystem/BuildSystemModuleImpl.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/buildsystem/BuildSystemModuleImpl.java index 3754c6cee22..d38fc439408 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/buildsystem/BuildSystemModuleImpl.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/buildsystem/BuildSystemModuleImpl.java @@ -6,7 +6,6 @@ import datadog.context.propagation.CarrierSetter; import datadog.trace.api.Config; import datadog.trace.api.DDTags; -import datadog.trace.api.civisibility.CIConstants; import datadog.trace.api.civisibility.domain.BuildModuleLayout; import datadog.trace.api.civisibility.domain.BuildModuleSettings; import datadog.trace.api.civisibility.domain.BuildSessionSettings; @@ -16,6 +15,7 @@ import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.AgentSpanContext; import datadog.trace.bootstrap.instrumentation.api.Tags; +import datadog.trace.civisibility.Constants; import datadog.trace.civisibility.codeowners.Codeowners; import datadog.trace.civisibility.config.ExecutionSettings; import datadog.trace.civisibility.coverage.percentage.CoverageCalculator; @@ -269,7 +269,7 @@ private SignalResponse onModuleExecutionResultReceived(ModuleExecutionResult res if (result.isEarlyFlakeDetectionEnabled()) { setTag(Tags.TEST_EARLY_FLAKE_ENABLED, true); if (result.isEarlyFlakeDetectionFaulty()) { - setTag(Tags.TEST_EARLY_FLAKE_ABORT_REASON, CIConstants.EFD_ABORT_REASON_FAULTY); + setTag(Tags.TEST_EARLY_FLAKE_ABORT_REASON, Constants.EFD_ABORT_REASON_FAULTY); } } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/buildsystem/BuildSystemSessionImpl.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/buildsystem/BuildSystemSessionImpl.java index 513cb74938f..c8a289caa7a 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/buildsystem/BuildSystemSessionImpl.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/buildsystem/BuildSystemSessionImpl.java @@ -4,7 +4,6 @@ import datadog.trace.api.Config; import datadog.trace.api.DDTags; -import datadog.trace.api.civisibility.CIConstants; import datadog.trace.api.civisibility.domain.BuildModuleLayout; import datadog.trace.api.civisibility.domain.BuildSessionSettings; import datadog.trace.api.civisibility.domain.JavaAgent; @@ -14,6 +13,7 @@ import datadog.trace.api.civisibility.telemetry.tag.Provider; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.Tags; +import datadog.trace.civisibility.Constants; import datadog.trace.civisibility.codeowners.Codeowners; import datadog.trace.civisibility.config.ExecutionSettings; import datadog.trace.civisibility.config.ExecutionSettingsFactory; @@ -208,8 +208,7 @@ public BuildSessionSettings getSettings() { @Override protected Collection additionalTelemetryTags() { - if (CIConstants.EFD_ABORT_REASON_FAULTY.equals( - span.getTag(Tags.TEST_EARLY_FLAKE_ABORT_REASON))) { + if (Constants.EFD_ABORT_REASON_FAULTY.equals(span.getTag(Tags.TEST_EARLY_FLAKE_ABORT_REASON))) { return Collections.singleton(EarlyFlakeDetectionAbortReason.FAULTY); } return Collections.emptySet(); diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/headless/HeadlessTestModule.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/headless/HeadlessTestModule.java index 65a75ed685a..2d8a66135e9 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/headless/HeadlessTestModule.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/headless/HeadlessTestModule.java @@ -2,7 +2,6 @@ import datadog.trace.api.Config; import datadog.trace.api.DDTags; -import datadog.trace.api.civisibility.CIConstants; import datadog.trace.api.civisibility.config.LibraryCapability; import datadog.trace.api.civisibility.config.TestIdentifier; import datadog.trace.api.civisibility.config.TestSourceData; @@ -14,6 +13,7 @@ import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.AgentSpanContext; import datadog.trace.bootstrap.instrumentation.api.Tags; +import datadog.trace.civisibility.Constants; import datadog.trace.civisibility.codeowners.Codeowners; import datadog.trace.civisibility.config.EarlyFlakeDetectionSettings; import datadog.trace.civisibility.config.ExecutionSettings; @@ -150,7 +150,7 @@ public void end(@Nullable Long endTime) { if (earlyFlakeDetectionSettings.isEnabled()) { setTag(Tags.TEST_EARLY_FLAKE_ENABLED, true); if (executionStrategy.isEFDLimitReached()) { - setTag(Tags.TEST_EARLY_FLAKE_ABORT_REASON, CIConstants.EFD_ABORT_REASON_FAULTY); + setTag(Tags.TEST_EARLY_FLAKE_ABORT_REASON, Constants.EFD_ABORT_REASON_FAULTY); } } diff --git a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/headless/HeadlessTestSession.java b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/headless/HeadlessTestSession.java index a499793115b..ccafd04a41d 100644 --- a/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/headless/HeadlessTestSession.java +++ b/dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/headless/HeadlessTestSession.java @@ -2,7 +2,6 @@ import datadog.trace.api.Config; import datadog.trace.api.DDTags; -import datadog.trace.api.civisibility.CIConstants; import datadog.trace.api.civisibility.config.LibraryCapability; import datadog.trace.api.civisibility.coverage.CoverageStore; import datadog.trace.api.civisibility.telemetry.CiVisibilityMetricCollector; @@ -11,6 +10,7 @@ import datadog.trace.api.civisibility.telemetry.tag.Provider; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.bootstrap.instrumentation.api.Tags; +import datadog.trace.civisibility.Constants; import datadog.trace.civisibility.codeowners.Codeowners; import datadog.trace.civisibility.decorator.TestDecorator; import datadog.trace.civisibility.domain.AbstractTestSession; @@ -102,8 +102,7 @@ private void propagateModuleTags(AgentSpan moduleSpan) { @Override protected Collection additionalTelemetryTags() { - if (CIConstants.EFD_ABORT_REASON_FAULTY.equals( - span.getTag(Tags.TEST_EARLY_FLAKE_ABORT_REASON))) { + if (Constants.EFD_ABORT_REASON_FAULTY.equals(span.getTag(Tags.TEST_EARLY_FLAKE_ABORT_REASON))) { return Collections.singleton(EarlyFlakeDetectionAbortReason.FAULTY); } return Collections.emptySet(); diff --git a/internal-api/src/main/java/datadog/trace/api/civisibility/CIConstants.java b/internal-api/src/main/java/datadog/trace/api/civisibility/CIConstants.java index 08d5b7a13cf..a4ed5a1d9c6 100644 --- a/internal-api/src/main/java/datadog/trace/api/civisibility/CIConstants.java +++ b/internal-api/src/main/java/datadog/trace/api/civisibility/CIConstants.java @@ -1,16 +1,9 @@ package datadog.trace.api.civisibility; public interface CIConstants { - /** - * Indicates that early flakiness detection feature was aborted in a test session because too many - * test cases were considered new. - */ - String EFD_ABORT_REASON_FAULTY = "faulty"; String SELENIUM_BROWSER_DRIVER = "selenium"; - String CI_VISIBILITY_INSTRUMENTATION_NAME = "civisibility"; - String FAIL_FAST_TEST_ORDER = "FAILFAST"; String CIAPP_TEST_ORIGIN = "ciapp-test"; From 9a78dd7903f5905986534c74b4fed87e705400e8 Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Mon, 17 Mar 2025 14:24:34 -0400 Subject: [PATCH 48/98] Nits: Update comments and include exception in log messages --- .../trace/bootstrap/config/provider/StableConfigParser.java | 3 +-- .../trace/bootstrap/config/provider/StableConfigSource.java | 5 ++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java index ed50ed96e72..bcfa6997a47 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java @@ -133,8 +133,7 @@ public static boolean selectorMatch( } return false; case "process_arguments": - // TODO: export getVMArgumentsThroughReflection to a utility class and cache its results, so - // as not to re-run this query + // TODO: use CLIHelper once merged return true; case "tags": // TODO: Determine where tags are sourced from diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java index ce5e61d09e5..5bd5132cf85 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java @@ -39,7 +39,10 @@ public final class StableConfigSource extends ConfigProvider.Source { try { cfg = StableConfigParser.parse(filePath); } catch (Throwable e) { - log.debug("Stable configuration file not readable at specified path: {}", file); + log.error( + "Encountered the following exception when attempting to read stable configuration file at path: {}, dropping configs: {}", + file, + e.getMessage()); cfg = StableConfig.EMPTY; } this.config = cfg; From 630c61fcc6d5580829c800895476d7378f158ee9 Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Tue, 18 Mar 2025 11:26:58 +0000 Subject: [PATCH 49/98] Vendor snakeyaml --- dd-java-agent/build.gradle | 3 ++- gradle/dependencies.gradle | 3 +++ internal-api/build.gradle | 1 - 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/dd-java-agent/build.gradle b/dd-java-agent/build.gradle index 95737b79eeb..d03ea2e440e 100644 --- a/dd-java-agent/build.gradle +++ b/dd-java-agent/build.gradle @@ -59,8 +59,9 @@ ext.generalShadowJarConfig = { final String projectName = "${project.name}" - // Prevents conflict with other OkHttp instances, but don't relocate instrumentation + // Prevents conflict with other instances, but doesn't relocate instrumentation if (!projectName.equals('instrumentation')) { + relocate 'org.yaml.snakeyaml', 'datadog.snakeyaml' relocate 'okhttp3', 'datadog.okhttp3' relocate 'okio', 'datadog.okio' } diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index 2fd95f2c4af..636efdf3f04 100644 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -48,6 +48,9 @@ final class CachedData { // cafe_crypto and its transitives exclude(dependency('cafe.cryptography::')) + + // snakeyaml and its transitives + exclude(dependency('org.yaml:snakeyaml')) } ] } diff --git a/internal-api/build.gradle b/internal-api/build.gradle index 57674cdcdfb..aaed92f5414 100644 --- a/internal-api/build.gradle +++ b/internal-api/build.gradle @@ -248,7 +248,6 @@ dependencies { testImplementation libs.commons.math testImplementation libs.bundles.mockito testImplementation libs.truth - testImplementation 'org.yaml:snakeyaml:2.0' } jmh { From 11b01da9f4ba149437081af7b52e3c570f03d740 Mon Sep 17 00:00:00 2001 From: "Santiago M. Mola" Date: Mon, 17 Mar 2025 18:34:25 +0100 Subject: [PATCH 50/98] Fix PlayNettySmokeTest logging config (#8576) --- dd-smoke-tests/play-2.4/conf/logback.xml | 4 +--- dd-smoke-tests/play-2.5/conf/logback.xml | 4 +--- dd-smoke-tests/play-2.6/conf/logback.xml | 4 +--- dd-smoke-tests/play-2.7/conf/logback.xml | 4 +--- dd-smoke-tests/play-2.8-otel/conf/logback.xml | 4 +--- dd-smoke-tests/play-2.8-split-routes/conf/logback.xml | 4 +--- dd-smoke-tests/play-2.8/conf/logback.xml | 4 +--- 7 files changed, 7 insertions(+), 21 deletions(-) diff --git a/dd-smoke-tests/play-2.4/conf/logback.xml b/dd-smoke-tests/play-2.4/conf/logback.xml index 605e8f00b27..1de959e02dc 100644 --- a/dd-smoke-tests/play-2.4/conf/logback.xml +++ b/dd-smoke-tests/play-2.4/conf/logback.xml @@ -1,11 +1,9 @@ - - - %coloredLevel %logger{15} - %message%n%xException{10} + %level %logger{15} - %message%n%xException{10} diff --git a/dd-smoke-tests/play-2.5/conf/logback.xml b/dd-smoke-tests/play-2.5/conf/logback.xml index 605e8f00b27..1de959e02dc 100644 --- a/dd-smoke-tests/play-2.5/conf/logback.xml +++ b/dd-smoke-tests/play-2.5/conf/logback.xml @@ -1,11 +1,9 @@ - - - %coloredLevel %logger{15} - %message%n%xException{10} + %level %logger{15} - %message%n%xException{10} diff --git a/dd-smoke-tests/play-2.6/conf/logback.xml b/dd-smoke-tests/play-2.6/conf/logback.xml index dda1dcc5c58..351eb6f60b2 100644 --- a/dd-smoke-tests/play-2.6/conf/logback.xml +++ b/dd-smoke-tests/play-2.6/conf/logback.xml @@ -1,11 +1,9 @@ - - - %coloredLevel %logger{15} - %message%n%xException{10} + %level %logger{15} - %message%n%xException{10} diff --git a/dd-smoke-tests/play-2.7/conf/logback.xml b/dd-smoke-tests/play-2.7/conf/logback.xml index dda1dcc5c58..351eb6f60b2 100644 --- a/dd-smoke-tests/play-2.7/conf/logback.xml +++ b/dd-smoke-tests/play-2.7/conf/logback.xml @@ -1,11 +1,9 @@ - - - %coloredLevel %logger{15} - %message%n%xException{10} + %level %logger{15} - %message%n%xException{10} diff --git a/dd-smoke-tests/play-2.8-otel/conf/logback.xml b/dd-smoke-tests/play-2.8-otel/conf/logback.xml index dda1dcc5c58..351eb6f60b2 100644 --- a/dd-smoke-tests/play-2.8-otel/conf/logback.xml +++ b/dd-smoke-tests/play-2.8-otel/conf/logback.xml @@ -1,11 +1,9 @@ - - - %coloredLevel %logger{15} - %message%n%xException{10} + %level %logger{15} - %message%n%xException{10} diff --git a/dd-smoke-tests/play-2.8-split-routes/conf/logback.xml b/dd-smoke-tests/play-2.8-split-routes/conf/logback.xml index dda1dcc5c58..351eb6f60b2 100644 --- a/dd-smoke-tests/play-2.8-split-routes/conf/logback.xml +++ b/dd-smoke-tests/play-2.8-split-routes/conf/logback.xml @@ -1,11 +1,9 @@ - - - %coloredLevel %logger{15} - %message%n%xException{10} + %level %logger{15} - %message%n%xException{10} diff --git a/dd-smoke-tests/play-2.8/conf/logback.xml b/dd-smoke-tests/play-2.8/conf/logback.xml index dda1dcc5c58..351eb6f60b2 100644 --- a/dd-smoke-tests/play-2.8/conf/logback.xml +++ b/dd-smoke-tests/play-2.8/conf/logback.xml @@ -1,11 +1,9 @@ - - - %coloredLevel %logger{15} - %message%n%xException{10} + %level %logger{15} - %message%n%xException{10} From 888cbd43c8c1bd77f440c08f191eed36805c5de1 Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Mon, 17 Mar 2025 17:36:59 +0000 Subject: [PATCH 51/98] Expose Context.empty() as building block for creating custom root contexts (#8575) This supports custom ContextManagers that want to define their own root context without needing to expose all the different context implementations. They can start with Context.empty() and add any elements they want, storing the final context as a constant so it can be supplied as Context.root() --- .../src/main/java/datadog/context/Context.java | 9 +++++++++ .../src/test/java/datadog/context/ContextTest.java | 12 ++++++++++++ 2 files changed, 21 insertions(+) diff --git a/components/context/src/main/java/datadog/context/Context.java b/components/context/src/main/java/datadog/context/Context.java index da04ac4fe0b..b9e29af6efb 100644 --- a/components/context/src/main/java/datadog/context/Context.java +++ b/components/context/src/main/java/datadog/context/Context.java @@ -36,6 +36,15 @@ * @see ContextKey */ public interface Context { + /** + * Returns the empty context. + * + * @return the context containing no values at all. + */ + static Context empty() { + return EmptyContext.INSTANCE; + } + /** * Returns the root context. * diff --git a/components/context/src/test/java/datadog/context/ContextTest.java b/components/context/src/test/java/datadog/context/ContextTest.java index 8bf69b645cb..3d624212bce 100644 --- a/components/context/src/test/java/datadog/context/ContextTest.java +++ b/components/context/src/test/java/datadog/context/ContextTest.java @@ -1,5 +1,6 @@ package datadog.context; +import static datadog.context.Context.empty; import static datadog.context.Context.root; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -21,6 +22,17 @@ class ContextTest { static final ContextKey FLOAT_KEY = ContextKey.named("float-key"); static final ContextKey LONG_KEY = ContextKey.named("long-key"); + @Test + void testEmpty() { + // Test empty is always the same + Context empty = empty(); + assertEquals(empty, empty(), "Empty context should be consistent"); + // Test empty is not mutated + String stringValue = "value"; + empty.with(STRING_KEY, stringValue); + assertEquals(empty, empty(), "Empty context should be immutable"); + } + @Test void testRoot() { // Test root is always the same From b5b31c329ae1f3021a6564b68a14f4ce2e4e59e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Gonz=C3=A1lez=20Garc=C3=ADa?= Date: Mon, 17 Mar 2025 19:05:21 +0100 Subject: [PATCH 52/98] RASP capabilities for LFI is not sent when RASP is not fully enabled (#8573) What Does This Do Only send RASP LFI capability if appsec is fully enabled Motivation Some RASP features have been implemented using callsite instrumentation, specifically LFI and partially SSRF. Since callsite instrumentation requires activation at application startup to function correctly, it will not work properly when RASP is dynamically enabled via 1-click activation. --- .../config/AppSecConfigServiceImpl.java | 6 +- ...ppSecConfigServiceImplSpecification.groovy | 69 +++++++++++++++++-- 2 files changed, 69 insertions(+), 6 deletions(-) diff --git a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/config/AppSecConfigServiceImpl.java b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/config/AppSecConfigServiceImpl.java index 1539000bf88..069733a03fd 100644 --- a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/config/AppSecConfigServiceImpl.java +++ b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/config/AppSecConfigServiceImpl.java @@ -115,9 +115,13 @@ private void subscribeConfigurationPoller() { if (tracerConfig.isAppSecRaspEnabled()) { capabilities |= CAPABILITY_ASM_RASP_SQLI; capabilities |= CAPABILITY_ASM_RASP_SSRF; - capabilities |= CAPABILITY_ASM_RASP_LFI; capabilities |= CAPABILITY_ASM_RASP_CMDI; capabilities |= CAPABILITY_ASM_RASP_SHI; + // RASP LFI is only available in fully enabled mode as it's implemented using callsite + // instrumentation + if (tracerConfig.getAppSecActivation() == ProductActivation.FULLY_ENABLED) { + capabilities |= CAPABILITY_ASM_RASP_LFI; + } } this.configurationPoller.addCapabilities(capabilities); } diff --git a/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/config/AppSecConfigServiceImplSpecification.groovy b/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/config/AppSecConfigServiceImplSpecification.groovy index 2978bc27fed..33f07f611b5 100644 --- a/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/config/AppSecConfigServiceImplSpecification.groovy +++ b/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/config/AppSecConfigServiceImplSpecification.groovy @@ -202,7 +202,7 @@ class AppSecConfigServiceImplSpecification extends DDSpecification { then: 1 * config.isAppSecRaspEnabled() >> true 1 * config.getAppSecRulesFile() >> null - 1 * config.getAppSecActivation() >> ProductActivation.ENABLED_INACTIVE + 2 * config.getAppSecActivation() >> ProductActivation.ENABLED_INACTIVE 1 * poller.addListener(Product.ASM_FEATURES, _, _) >> { listeners.savedFeaturesDeserializer = it[1] listeners.savedFeaturesListener = it[2] @@ -239,7 +239,7 @@ class AppSecConfigServiceImplSpecification extends DDSpecification { then: 1 * config.isAppSecRaspEnabled() >> true 1 * config.getAppSecRulesFile() >> null - 1 * config.getAppSecActivation() >> ProductActivation.ENABLED_INACTIVE + 2 * config.getAppSecActivation() >> ProductActivation.ENABLED_INACTIVE 1 * poller.addListener(Product.ASM_DD, _, _) >> { listeners.savedConfDeserializer = it[1] listeners.savedConfChangesListener = it[2] @@ -273,7 +273,6 @@ class AppSecConfigServiceImplSpecification extends DDSpecification { | CAPABILITY_ASM_RASP_SSRF | CAPABILITY_ASM_RASP_CMDI | CAPABILITY_ASM_RASP_SHI - | CAPABILITY_ASM_RASP_LFI | CAPABILITY_ENDPOINT_FINGERPRINT | CAPABILITY_ASM_SESSION_FINGERPRINT | CAPABILITY_ASM_NETWORK_FINGERPRINT @@ -393,7 +392,7 @@ class AppSecConfigServiceImplSpecification extends DDSpecification { then: 1 * config.isAppSecRaspEnabled() >> true 1 * config.getAppSecRulesFile() >> null - 1 * config.getAppSecActivation() >> ProductActivation.ENABLED_INACTIVE + 2 * config.getAppSecActivation() >> ProductActivation.ENABLED_INACTIVE 1 * poller.addListener(Product.ASM_DD, _, _) >> { listeners.savedConfDeserializer = it[1] listeners.savedConfChangesListener = it[2] @@ -427,7 +426,6 @@ class AppSecConfigServiceImplSpecification extends DDSpecification { | CAPABILITY_ASM_RASP_SSRF | CAPABILITY_ASM_RASP_CMDI | CAPABILITY_ASM_RASP_SHI - | CAPABILITY_ASM_RASP_LFI | CAPABILITY_ENDPOINT_FINGERPRINT | CAPABILITY_ASM_SESSION_FINGERPRINT | CAPABILITY_ASM_NETWORK_FINGERPRINT @@ -564,6 +562,67 @@ class AppSecConfigServiceImplSpecification extends DDSpecification { autoUserInstrum('yolo') | DISABLED } + void 'RASP capabilities for LFI is not sent when RASP is not fully enabled '() { + AppSecModuleConfigurer.SubconfigListener subconfigListener = Mock() + SavedListeners listeners = new SavedListeners() + Optional initialWafConfig + + when: + AppSecSystem.active = false + appSecConfigService.init() + appSecConfigService.maybeSubscribeConfigPolling() + def configurer = appSecConfigService.createAppSecModuleConfigurer() + initialWafConfig = configurer.addSubConfigListener("waf", subconfigListener) + configurer.commit() + + then: + 1 * config.isAppSecRaspEnabled() >> true + 1 * config.getAppSecRulesFile() >> null + 2 * config.getAppSecActivation() >> ProductActivation.FULLY_ENABLED + 1 * poller.addListener(Product.ASM_DD, _, _) >> { + listeners.savedConfDeserializer = it[1] + listeners.savedConfChangesListener = it[2] + } + 1 * poller.addListener(Product.ASM_DATA, _, _) >> { + listeners.savedWafDataDeserializer = it[1] + listeners.savedWafDataChangesListener = it[2] + } + 1 * poller.addListener(Product.ASM, _, _) >> { + listeners.savedWafRulesOverrideDeserializer = it[1] + listeners.savedWafRulesOverrideListener = it[2] + } + 1 * poller.addListener(Product.ASM_FEATURES, _, _) >> { + listeners.savedFeaturesDeserializer = it[1] + listeners.savedFeaturesListener = it[2] + } + 1 * poller.addConfigurationEndListener(_) >> { listeners.savedConfEndListener = it[0] } + 1 * poller.addCapabilities(CAPABILITY_ASM_API_SECURITY_SAMPLE_RATE) + 1 * poller.addCapabilities(CAPABILITY_ASM_AUTO_USER_INSTRUM_MODE) + 1 * poller.addCapabilities(CAPABILITY_ASM_DD_RULES + | CAPABILITY_ASM_IP_BLOCKING + | CAPABILITY_ASM_EXCLUSIONS + | CAPABILITY_ASM_EXCLUSION_DATA + | CAPABILITY_ASM_REQUEST_BLOCKING + | CAPABILITY_ASM_USER_BLOCKING + | CAPABILITY_ASM_CUSTOM_RULES + | CAPABILITY_ASM_CUSTOM_BLOCKING_RESPONSE + | CAPABILITY_ASM_TRUSTED_IPS + | CAPABILITY_ASM_RASP_SQLI + | CAPABILITY_ASM_RASP_SSRF + | CAPABILITY_ASM_RASP_CMDI + | CAPABILITY_ASM_RASP_SHI + | CAPABILITY_ASM_RASP_LFI + | CAPABILITY_ENDPOINT_FINGERPRINT + | CAPABILITY_ASM_SESSION_FINGERPRINT + | CAPABILITY_ASM_NETWORK_FINGERPRINT + | CAPABILITY_ASM_HEADER_FINGERPRINT) + 0 * _._ + initialWafConfig.get() != null + + cleanup: + AppSecSystem.active = true + } + private static AppSecFeatures autoUserInstrum(String mode) { return new AppSecFeatures().tap { features -> features.autoUserInstrum = new AppSecFeatures.AutoUserInstrum().tap { instrum -> From 64736213871687844cf6f99bf1a5562d8c257196 Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Tue, 18 Mar 2025 08:05:31 +0000 Subject: [PATCH 53/98] Minor test changes to avoid deprecated API (#8574) --- .../src/akka23Test/scala/AkkaActors.scala | 6 +++--- .../src/test/scala/PekkoActors.scala | 6 +++--- .../scala/ScalaConcurrentTests.scala | 12 ++++++------ .../src/test/scala/ScalaConcurrentTests.scala | 12 ++++++------ .../slick/src/test/scala/SlickUtils.scala | 6 +++--- .../core/scopemanager/ScopeManagerTest.groovy | 16 ++++++++-------- 6 files changed, 29 insertions(+), 29 deletions(-) diff --git a/dd-java-agent/instrumentation/akka-concurrent/src/akka23Test/scala/AkkaActors.scala b/dd-java-agent/instrumentation/akka-concurrent/src/akka23Test/scala/AkkaActors.scala index b7140a4fb6d..5ca469ec5ad 100644 --- a/dd-java-agent/instrumentation/akka-concurrent/src/akka23Test/scala/AkkaActors.scala +++ b/dd-java-agent/instrumentation/akka-concurrent/src/akka23Test/scala/AkkaActors.scala @@ -6,7 +6,7 @@ import akka.util.Timeout import datadog.trace.api.Trace import datadog.trace.bootstrap.instrumentation.api.AgentTracer.{ activateSpan, - activeScope, + setAsyncPropagationEnabled, activeSpan, startSpan } @@ -57,7 +57,7 @@ class AkkaActors extends AutoCloseable { @Trace def send(name: String, who: String): Unit = { val actor = actors(name) - activeScope().setAsyncPropagation(true) + setAsyncPropagationEnabled(true) activeSpan().setSpanName(name) actor ! WhoToGreet(who) if (name == "ask") { @@ -69,7 +69,7 @@ class AkkaActors extends AutoCloseable { @Trace def leak(who: String, leak: String): Unit = { - activeScope().setAsyncPropagation(true) + setAsyncPropagationEnabled(true) activeSpan().setSpanName("leak all the things") tellGreeter ! WhoToGreet(who) tellGreeter ! Leak(leak) diff --git a/dd-java-agent/instrumentation/pekko-concurrent/src/test/scala/PekkoActors.scala b/dd-java-agent/instrumentation/pekko-concurrent/src/test/scala/PekkoActors.scala index 094c70faf18..ac6d226d709 100644 --- a/dd-java-agent/instrumentation/pekko-concurrent/src/test/scala/PekkoActors.scala +++ b/dd-java-agent/instrumentation/pekko-concurrent/src/test/scala/PekkoActors.scala @@ -6,7 +6,7 @@ import org.apache.pekko.util.Timeout import datadog.trace.api.Trace import datadog.trace.bootstrap.instrumentation.api.AgentTracer.{ activateSpan, - activeScope, + setAsyncPropagationEnabled, activeSpan, startSpan } @@ -55,7 +55,7 @@ class PekkoActors extends AutoCloseable { @Trace def send(name: String, who: String): Unit = { val actor = actors(name) - activeScope().setAsyncPropagation(true) + setAsyncPropagationEnabled(true) activeSpan().setSpanName(name) actor ! WhoToGreet(who) if (name == "ask") { @@ -67,7 +67,7 @@ class PekkoActors extends AutoCloseable { @Trace def leak(who: String, leak: String): Unit = { - activeScope().setAsyncPropagation(true) + setAsyncPropagationEnabled(true) activeSpan().setSpanName("leak all the things") tellGreeter ! WhoToGreet(who) tellGreeter ! Leak(leak) diff --git a/dd-java-agent/instrumentation/scala-concurrent/src/latestDepTest/scala/ScalaConcurrentTests.scala b/dd-java-agent/instrumentation/scala-concurrent/src/latestDepTest/scala/ScalaConcurrentTests.scala index 4f512a2d9ea..a4033616e73 100644 --- a/dd-java-agent/instrumentation/scala-concurrent/src/latestDepTest/scala/ScalaConcurrentTests.scala +++ b/dd-java-agent/instrumentation/scala-concurrent/src/latestDepTest/scala/ScalaConcurrentTests.scala @@ -1,6 +1,6 @@ import datadog.trace.agent.test.AgentTestRunner.blockUntilChildSpansFinished import datadog.trace.api.Trace -import datadog.trace.bootstrap.instrumentation.api.AgentTracer.{activeScope, activeSpan} +import datadog.trace.bootstrap.instrumentation.api.AgentTracer.{setAsyncPropagationEnabled, activeSpan} import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.duration._ @@ -13,7 +13,7 @@ class ScalaConcurrentTests { */ @Trace def traceWithFutureAndCallbacks(): Integer = { - activeScope().setAsyncPropagation(true) + setAsyncPropagationEnabled(true) val goodFuture: Future[Integer] = Future { tracedChild("goodFuture") 1 @@ -31,7 +31,7 @@ class ScalaConcurrentTests { @Trace def tracedAcrossThreadsWithNoTrace(): Integer = { - activeScope().setAsyncPropagation(true) + setAsyncPropagationEnabled(true) val goodFuture: Future[Integer] = Future { 1 } @@ -51,7 +51,7 @@ class ScalaConcurrentTests { */ @Trace def traceWithPromises(): Integer = { - activeScope().setAsyncPropagation(true) + setAsyncPropagationEnabled(true) val keptPromise = Promise[Boolean]() val brokenPromise = Promise[Boolean]() val afterPromise = keptPromise.future @@ -78,7 +78,7 @@ class ScalaConcurrentTests { */ @Trace def tracedWithFutureFirstCompletions(): Integer = { - activeScope().setAsyncPropagation(true) + setAsyncPropagationEnabled(true) val completedVal = Future.firstCompletedOf(List(Future { tracedChild("timeout1") false @@ -100,7 +100,7 @@ class ScalaConcurrentTests { */ @Trace def tracedTimeout(): Integer = { - activeScope().setAsyncPropagation(true) + setAsyncPropagationEnabled(true) val f: Future[String] = Future { tracedChild("timeoutChild") while (true) { diff --git a/dd-java-agent/instrumentation/scala-concurrent/src/test/scala/ScalaConcurrentTests.scala b/dd-java-agent/instrumentation/scala-concurrent/src/test/scala/ScalaConcurrentTests.scala index 4f512a2d9ea..a4033616e73 100644 --- a/dd-java-agent/instrumentation/scala-concurrent/src/test/scala/ScalaConcurrentTests.scala +++ b/dd-java-agent/instrumentation/scala-concurrent/src/test/scala/ScalaConcurrentTests.scala @@ -1,6 +1,6 @@ import datadog.trace.agent.test.AgentTestRunner.blockUntilChildSpansFinished import datadog.trace.api.Trace -import datadog.trace.bootstrap.instrumentation.api.AgentTracer.{activeScope, activeSpan} +import datadog.trace.bootstrap.instrumentation.api.AgentTracer.{setAsyncPropagationEnabled, activeSpan} import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.duration._ @@ -13,7 +13,7 @@ class ScalaConcurrentTests { */ @Trace def traceWithFutureAndCallbacks(): Integer = { - activeScope().setAsyncPropagation(true) + setAsyncPropagationEnabled(true) val goodFuture: Future[Integer] = Future { tracedChild("goodFuture") 1 @@ -31,7 +31,7 @@ class ScalaConcurrentTests { @Trace def tracedAcrossThreadsWithNoTrace(): Integer = { - activeScope().setAsyncPropagation(true) + setAsyncPropagationEnabled(true) val goodFuture: Future[Integer] = Future { 1 } @@ -51,7 +51,7 @@ class ScalaConcurrentTests { */ @Trace def traceWithPromises(): Integer = { - activeScope().setAsyncPropagation(true) + setAsyncPropagationEnabled(true) val keptPromise = Promise[Boolean]() val brokenPromise = Promise[Boolean]() val afterPromise = keptPromise.future @@ -78,7 +78,7 @@ class ScalaConcurrentTests { */ @Trace def tracedWithFutureFirstCompletions(): Integer = { - activeScope().setAsyncPropagation(true) + setAsyncPropagationEnabled(true) val completedVal = Future.firstCompletedOf(List(Future { tracedChild("timeout1") false @@ -100,7 +100,7 @@ class ScalaConcurrentTests { */ @Trace def tracedTimeout(): Integer = { - activeScope().setAsyncPropagation(true) + setAsyncPropagationEnabled(true) val f: Future[String] = Future { tracedChild("timeoutChild") while (true) { diff --git a/dd-java-agent/instrumentation/slick/src/test/scala/SlickUtils.scala b/dd-java-agent/instrumentation/slick/src/test/scala/SlickUtils.scala index 3f5ae0fb642..531effffb92 100644 --- a/dd-java-agent/instrumentation/slick/src/test/scala/SlickUtils.scala +++ b/dd-java-agent/instrumentation/slick/src/test/scala/SlickUtils.scala @@ -1,6 +1,6 @@ import datadog.trace.agent.test.AgentTestRunner.blockUntilChildSpansFinished import datadog.trace.api.Trace -import datadog.trace.bootstrap.instrumentation.api.AgentTracer.{activeScope, activeSpan} +import datadog.trace.bootstrap.instrumentation.api.AgentTracer.{setAsyncPropagationEnabled, activeSpan} import datadog.trace.common.writer.ListWriter import datadog.trace.core.DDSpan import slick.jdbc.H2Profile.api._ @@ -26,7 +26,7 @@ class SlickUtils(TEST_WRITER: ListWriter) { @Trace def setup(): DDSpan = { - activeScope().setAsyncPropagation(true) + setAsyncPropagationEnabled(true) Await.result( database.run( sqlu"""CREATE ALIAS IF NOT EXISTS SLEEP FOR "java.lang.Thread.sleep(long)"""" @@ -39,7 +39,7 @@ class SlickUtils(TEST_WRITER: ListWriter) { @Trace def startQuery(query: String): Future[Vector[Int]] = { try { - activeScope().setAsyncPropagation(true) + setAsyncPropagationEnabled(true) database.run(sql"#$query".as[Int]) } finally { blockUntilChildSpansFinished(activeSpan(), 1) diff --git a/dd-trace-core/src/test/groovy/datadog/trace/core/scopemanager/ScopeManagerTest.groovy b/dd-trace-core/src/test/groovy/datadog/trace/core/scopemanager/ScopeManagerTest.groovy index b337609873c..78e5b3f56d0 100644 --- a/dd-trace-core/src/test/groovy/datadog/trace/core/scopemanager/ScopeManagerTest.groovy +++ b/dd-trace-core/src/test/groovy/datadog/trace/core/scopemanager/ScopeManagerTest.groovy @@ -541,7 +541,7 @@ class ScopeManagerTest extends DDCoreSpecification { def "closing scope out of order - complex"() { // Events are checked twice in each case to ensure a call to - // tracer.activeScope() or tracer.activeSpan() doesn't change the count + // scopeManager.active() or tracer.activeSpan() doesn't change the count when: AgentSpan firstSpan = tracer.buildSpan("test", "foo").start() @@ -550,7 +550,7 @@ class ScopeManagerTest extends DDCoreSpecification { then: assertEvents([ACTIVATE]) tracer.activeSpan() == firstSpan - tracer.activeScope() == firstScope + scopeManager.active() == firstScope assertEvents([ACTIVATE]) 1 * profilingContext.onRootSpanStarted(_) 1 * profilingContext.onAttach() @@ -565,7 +565,7 @@ class ScopeManagerTest extends DDCoreSpecification { then: assertEvents([ACTIVATE, ACTIVATE]) tracer.activeSpan() == secondSpan - tracer.activeScope() == secondScope + scopeManager.active() == secondScope assertEvents([ACTIVATE, ACTIVATE]) 1 * profilingContext.encodeOperationName("bar") 1 * profilingContext.newScopeState(_) >> Stub(Stateful) @@ -578,7 +578,7 @@ class ScopeManagerTest extends DDCoreSpecification { then: assertEvents([ACTIVATE, ACTIVATE, ACTIVATE]) tracer.activeSpan() == thirdSpan - tracer.activeScope() == thirdScope + scopeManager.active() == thirdScope assertEvents([ACTIVATE, ACTIVATE, ACTIVATE]) 1 * profilingContext.encodeOperationName("quux") 1 * profilingContext.newScopeState(_) >> Stub(Stateful) @@ -590,7 +590,7 @@ class ScopeManagerTest extends DDCoreSpecification { then: assertEvents([ACTIVATE, ACTIVATE, ACTIVATE]) tracer.activeSpan() == thirdSpan - tracer.activeScope() == thirdScope + scopeManager.active() == thirdScope assertEvents([ACTIVATE, ACTIVATE, ACTIVATE]) 0 * _ @@ -600,7 +600,7 @@ class ScopeManagerTest extends DDCoreSpecification { then: assertEvents([ACTIVATE, ACTIVATE, ACTIVATE, CLOSE, CLOSE, ACTIVATE]) tracer.activeSpan() == firstSpan - tracer.activeScope() == firstScope + scopeManager.active() == firstScope assertEvents([ACTIVATE, ACTIVATE, ACTIVATE, CLOSE, CLOSE, ACTIVATE]) 0 * _ @@ -618,7 +618,7 @@ class ScopeManagerTest extends DDCoreSpecification { ACTIVATE, CLOSE ]) - tracer.activeScope() == null + scopeManager.active() == null assertEvents([ ACTIVATE, ACTIVATE, @@ -656,7 +656,7 @@ class ScopeManagerTest extends DDCoreSpecification { then: assertEvents([ACTIVATE, ACTIVATE]) tracer.activeSpan() == thirdSpan - tracer.activeScope() == thirdScope + scopeManager.active() == thirdScope assertEvents([ACTIVATE, ACTIVATE]) 1 * profilingContext.encodeOperationName("quux") 1 * profilingContext.newScopeState(_) >> Stub(Stateful) From 84ba99a0759f88207e72e7165cdf176c1d1d329b Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Tue, 18 Mar 2025 11:39:25 +0000 Subject: [PATCH 54/98] internal tests for stable config use snakeyaml to build test files --- internal-api/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/internal-api/build.gradle b/internal-api/build.gradle index aaed92f5414..4e399bd77d9 100644 --- a/internal-api/build.gradle +++ b/internal-api/build.gradle @@ -241,6 +241,7 @@ dependencies { // it contains annotations that are also present in the instrumented application classes api "com.datadoghq:dd-javac-plugin-client:0.2.2" + testImplementation("org.yaml:snakeyaml:2.4") testImplementation project(":utils:test-utils") testImplementation("org.assertj:assertj-core:3.20.2") testImplementation libs.bundles.junit5 From a920812aea34185a3bd35e78005136ba84680c2f Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Tue, 18 Mar 2025 12:21:59 +0000 Subject: [PATCH 55/98] Fix test --- .../config/provider/StableConfigSourceTest.groovy | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigSourceTest.groovy b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigSourceTest.groovy index 80e5bd34a1b..b6596174985 100644 --- a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigSourceTest.groovy +++ b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigSourceTest.groovy @@ -1,5 +1,7 @@ package datadog.trace.bootstrap.config.provider +import static java.util.Collections.singletonMap + import datadog.trace.api.ConfigOrigin import datadog.trace.bootstrap.config.provider.stableconfigyaml.ConfigurationMap import datadog.trace.bootstrap.config.provider.stableconfigyaml.ConfigurationValue @@ -13,10 +15,9 @@ import org.yaml.snakeyaml.introspector.Property import org.yaml.snakeyaml.nodes.NodeTuple import org.yaml.snakeyaml.nodes.Tag import org.yaml.snakeyaml.representer.Representer -import spock.lang.Shared -import java.nio.file.Path import java.nio.file.Files +import java.nio.file.Path import java.nio.file.StandardOpenOption class StableConfigSourceTest extends DDSpecification { @@ -128,8 +129,8 @@ class StableConfigSourceTest extends DDSpecification { ''' // Matching and non-matching Rules used for testing, defined outside the 'where' block for readability - def static sampleMatchingRule = new Rule(Arrays.asList(new Selector("origin", "language", Arrays.asList("Java"), null)), new ConfigurationMap((Map)Map.of("DD_KEY_THREE", new ConfigurationValue("three")))) - def static sampleNonMatchingRule = new Rule(Arrays.asList(new Selector("origin", "language", Arrays.asList("Golang"), null)), new ConfigurationMap((Map)Map.of("DD_KEY_FOUR", new ConfigurationValue("four")))) + def static sampleMatchingRule = new Rule(Arrays.asList(new Selector("origin", "language", Arrays.asList("Java"), null)), new ConfigurationMap(singletonMap("DD_KEY_THREE", new ConfigurationValue("three")))) + def static sampleNonMatchingRule = new Rule(Arrays.asList(new Selector("origin", "language", Arrays.asList("Golang"), null)), new ConfigurationMap(singletonMap("DD_KEY_FOUR", new ConfigurationValue("four")))) // Helper functions static Path tempFile() { From f07ed11b7695efb3fb8579ea71828e3b3e540c0e Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Tue, 18 Mar 2025 12:59:23 +0000 Subject: [PATCH 56/98] Fix instrumentation test+muzzle --- dd-java-agent/instrumentation/snakeyaml/build.gradle | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/dd-java-agent/instrumentation/snakeyaml/build.gradle b/dd-java-agent/instrumentation/snakeyaml/build.gradle index 396fe9b937a..bf4e8688130 100644 --- a/dd-java-agent/instrumentation/snakeyaml/build.gradle +++ b/dd-java-agent/instrumentation/snakeyaml/build.gradle @@ -18,7 +18,17 @@ addTestSuiteForDir('latestDepTest', 'test') dependencies { compileOnly group: 'org.yaml', name: 'snakeyaml', version: '1.33' - testImplementation group: 'org.yaml', name: 'snakeyaml', version: '1.33' + + testImplementation('org.yaml:snakeyaml') { + version { + strictly '1.33' + } + } + muzzleBootstrap('org.yaml:snakeyaml') { + version { + strictly '1.+' + } + } latestDepTestImplementation group: 'org.yaml', name: 'snakeyaml', version: '1.+' } From e6245382a8b95e453886b5221c0c9f66c118fd79 Mon Sep 17 00:00:00 2001 From: Andrea Marziali Date: Tue, 18 Mar 2025 12:37:47 +0100 Subject: [PATCH 57/98] Inherited decision maker is a meta (#8578) --- .../bootstrap/instrumentation/decorator/WebsocketDecorator.java | 2 +- .../groovy/datadog/trace/agent/test/base/HttpServerTest.groovy | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/WebsocketDecorator.java b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/WebsocketDecorator.java index cdc758829d9..aa9a50623b4 100644 --- a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/WebsocketDecorator.java +++ b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/WebsocketDecorator.java @@ -138,7 +138,7 @@ private AgentSpan onFrameStart( if (useDedicatedTraces) { wsSpan = startSpan(WEBSOCKET.toString(), operationName, null); if (inheritSampling) { - wsSpan.setTag(DECISION_MAKER_INHERITED, 1); + wsSpan.setTag(DECISION_MAKER_INHERITED, "1"); wsSpan.setTag(DECISION_MAKER_SERVICE, handshakeSpan.getServiceName()); wsSpan.setTag(DECISION_MAKER_RESOURCE, handshakeSpan.getResourceName()); } diff --git a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/base/HttpServerTest.groovy b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/base/HttpServerTest.groovy index 0edf3993aaa..c7f72b0da5e 100644 --- a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/base/HttpServerTest.groovy +++ b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/base/HttpServerTest.groovy @@ -2082,7 +2082,7 @@ abstract class HttpServerTest extends WithHttpServer { tag(Tags.COMPONENT, "websocket") if (traceStarter && Config.get().isWebsocketMessagesSeparateTraces()) { if (Config.get().isWebsocketMessagesInheritSampling()) { - tag(DDTags.DECISION_MAKER_INHERITED, 1) + tag(DDTags.DECISION_MAKER_INHERITED, "1") tag(DDTags.DECISION_MAKER_SERVICE, handshake.getServiceName()) tag(DDTags.DECISION_MAKER_RESOURCE, handshake.getResourceName()) } From f7a339eff3630b0f68030a7b48fee67aa42d3bfa Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Tue, 18 Mar 2025 11:42:03 +0000 Subject: [PATCH 58/98] Simplification: Context.root() is always empty (#8580) We haven't needed a non-empty root context, and collapsing these concepts together simplifies the code. --- .../src/main/java/datadog/context/Context.java | 11 +---------- .../main/java/datadog/context/ContextManager.java | 11 ++--------- .../datadog/context/ThreadLocalContextManager.java | 5 ----- .../datadog/context/ContextProviderForkedTest.java | 5 ----- .../src/test/java/datadog/context/ContextTest.java | 12 ------------ 5 files changed, 3 insertions(+), 41 deletions(-) diff --git a/components/context/src/main/java/datadog/context/Context.java b/components/context/src/main/java/datadog/context/Context.java index b9e29af6efb..046713291ae 100644 --- a/components/context/src/main/java/datadog/context/Context.java +++ b/components/context/src/main/java/datadog/context/Context.java @@ -36,22 +36,13 @@ * @see ContextKey */ public interface Context { - /** - * Returns the empty context. - * - * @return the context containing no values at all. - */ - static Context empty() { - return EmptyContext.INSTANCE; - } - /** * Returns the root context. * * @return the initial local context that all contexts extend. */ static Context root() { - return manager().root(); + return EmptyContext.INSTANCE; } /** diff --git a/components/context/src/main/java/datadog/context/ContextManager.java b/components/context/src/main/java/datadog/context/ContextManager.java index e259644239d..9c4a58cfa19 100644 --- a/components/context/src/main/java/datadog/context/ContextManager.java +++ b/components/context/src/main/java/datadog/context/ContextManager.java @@ -2,17 +2,10 @@ /** Manages context across execution units. */ public interface ContextManager { - /** - * Returns the root context. - * - * @return the initial local context that all contexts extend. - */ - Context root(); - /** * Returns the context attached to the current execution unit. * - * @return the attached context; {@link #root()} if there is none. + * @return the attached context; {@link Context#root()} if there is none. */ Context current(); @@ -28,7 +21,7 @@ public interface ContextManager { * Swaps the given context with the one attached to current execution unit. * * @param context the context to swap. - * @return the previously attached context; {@link #root()} if there was none. + * @return the previously attached context; {@link Context#root()} if there was none. */ Context swap(Context context); diff --git a/components/context/src/main/java/datadog/context/ThreadLocalContextManager.java b/components/context/src/main/java/datadog/context/ThreadLocalContextManager.java index b492218cb6b..27c17445d14 100644 --- a/components/context/src/main/java/datadog/context/ThreadLocalContextManager.java +++ b/components/context/src/main/java/datadog/context/ThreadLocalContextManager.java @@ -5,11 +5,6 @@ final class ThreadLocalContextManager implements ContextManager { private static final ThreadLocal CURRENT_HOLDER = ThreadLocal.withInitial(() -> new Context[] {EmptyContext.INSTANCE}); - @Override - public Context root() { - return EmptyContext.INSTANCE; - } - @Override public Context current() { return CURRENT_HOLDER.get()[0]; diff --git a/components/context/src/test/java/datadog/context/ContextProviderForkedTest.java b/components/context/src/test/java/datadog/context/ContextProviderForkedTest.java index a0f1afafdc6..db5d2791057 100644 --- a/components/context/src/test/java/datadog/context/ContextProviderForkedTest.java +++ b/components/context/src/test/java/datadog/context/ContextProviderForkedTest.java @@ -42,11 +42,6 @@ void testCustomManager() { // register a NOOP context manager ContextManager.register( new ContextManager() { - @Override - public Context root() { - return EmptyContext.INSTANCE; - } - @Override public Context current() { return root(); diff --git a/components/context/src/test/java/datadog/context/ContextTest.java b/components/context/src/test/java/datadog/context/ContextTest.java index 3d624212bce..8bf69b645cb 100644 --- a/components/context/src/test/java/datadog/context/ContextTest.java +++ b/components/context/src/test/java/datadog/context/ContextTest.java @@ -1,6 +1,5 @@ package datadog.context; -import static datadog.context.Context.empty; import static datadog.context.Context.root; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -22,17 +21,6 @@ class ContextTest { static final ContextKey FLOAT_KEY = ContextKey.named("float-key"); static final ContextKey LONG_KEY = ContextKey.named("long-key"); - @Test - void testEmpty() { - // Test empty is always the same - Context empty = empty(); - assertEquals(empty, empty(), "Empty context should be consistent"); - // Test empty is not mutated - String stringValue = "value"; - empty.with(STRING_KEY, stringValue); - assertEquals(empty, empty(), "Empty context should be immutable"); - } - @Test void testRoot() { // Test root is always the same From 1e1ef672c22efa67c85d644a6617551af1d7199a Mon Sep 17 00:00:00 2001 From: Andrea Marziali Date: Tue, 18 Mar 2025 14:44:22 +0100 Subject: [PATCH 59/98] Support and test kafka-clients 4 (#8581) * Support and test kafka-clients 4 * Use java 17 for kafka-connect muzzle --- .../kafka-clients-3.8/build.gradle | 10 +- .../kafka-clients-3.8/gradle.lockfile | 400 +++++++++--------- .../kafka_clients38/ProducerAdvice.java | 8 +- ...kaClientCustomPropagationConfigTest.groovy | 3 - .../test/groovy/KafkaClientTestBase.groovy | 14 +- .../kafka-connect-0.11/build.gradle | 1 + 6 files changed, 211 insertions(+), 225 deletions(-) diff --git a/dd-java-agent/instrumentation/kafka-clients-3.8/build.gradle b/dd-java-agent/instrumentation/kafka-clients-3.8/build.gradle index fdc4ac1c2ae..cfe6fbd3b04 100644 --- a/dd-java-agent/instrumentation/kafka-clients-3.8/build.gradle +++ b/dd-java-agent/instrumentation/kafka-clients-3.8/build.gradle @@ -7,12 +7,14 @@ muzzle { module = "kafka-clients" versions = "[3.8.0,)" assertInverse = true + javaVersion = "17" } } apply from: "$rootDir/gradle/java.gradle" -addTestSuite('latestDepTest') +addTestSuiteForDir('latestDepTest', 'test') +addTestSuiteExtendingForDir('latestDepForkedTest', 'latestDepTest', 'test') [compileMain_java17Java, compileTestJava, compileLatestDepTestJava].each { it.configure { @@ -53,9 +55,9 @@ dependencies { // Include latest version of kafka itself along with latest version of client libs. // This seems to help with jar compatibility hell. latestDepTestImplementation group: 'org.apache.kafka', name: 'kafka_2.13', version: '2.+' - latestDepTestImplementation group: 'org.apache.kafka', name: 'kafka-clients', version: '3.+' - latestDepTestImplementation group: 'org.springframework.kafka', name: 'spring-kafka', version: '3.+' - latestDepTestImplementation group: 'org.springframework.kafka', name: 'spring-kafka-test', version: '3.+' + latestDepTestImplementation group: 'org.apache.kafka', name: 'kafka-clients', version: '+' + latestDepTestImplementation group: 'org.springframework.kafka', name: 'spring-kafka', version: '+' + latestDepTestImplementation group: 'org.springframework.kafka', name: 'spring-kafka-test', version: '+' latestDepTestImplementation group: 'org.assertj', name: 'assertj-core', version: '3.19.+' latestDepTestImplementation libs.guava diff --git a/dd-java-agent/instrumentation/kafka-clients-3.8/gradle.lockfile b/dd-java-agent/instrumentation/kafka-clients-3.8/gradle.lockfile index f5bba3e42a7..d67ecd4a7b0 100644 --- a/dd-java-agent/instrumentation/kafka-clients-3.8/gradle.lockfile +++ b/dd-java-agent/instrumentation/kafka-clients-3.8/gradle.lockfile @@ -1,303 +1,303 @@ # This is a Gradle generated file for dependency locking. # Manual edits can break the build and are not advised. # This file is expected to be part of source control. -cafe.cryptography:curve25519-elisabeth:0.1.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -cafe.cryptography:ed25519-elisabeth:0.1.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +cafe.cryptography:curve25519-elisabeth:0.1.0=instrumentPluginClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +cafe.cryptography:ed25519-elisabeth:0.1.0=instrumentPluginClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath ch.qos.logback:logback-classic:1.2.10=testCompileClasspath,testRuntimeClasspath -ch.qos.logback:logback-classic:1.2.13=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +ch.qos.logback:logback-classic:1.2.13=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath ch.qos.logback:logback-core:1.2.10=testCompileClasspath,testRuntimeClasspath -ch.qos.logback:logback-core:1.2.13=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath -com.beust:jcommander:1.78=latestDepTestRuntimeClasspath,testRuntimeClasspath -com.blogspot.mydailyjava:weak-lock-free:0.17=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.datadoghq.okhttp3:okhttp:3.12.15=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.datadoghq.okio:okio:1.17.6=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.datadoghq:dd-javac-plugin-client:0.2.2=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleBootstrap,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.datadoghq:java-dogstatsd-client:4.4.3=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.datadoghq:sketches-java:0.8.3=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.fasterxml.jackson.core:jackson-annotations:2.10.3=latestDepTestCompileClasspath,testCompileClasspath +ch.qos.logback:logback-core:1.2.13=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +com.beust:jcommander:1.78=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath +com.blogspot.mydailyjava:weak-lock-free:0.17=compileClasspath,instrumentPluginClasspath,latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.datadoghq.okhttp3:okhttp:3.12.15=compileClasspath,instrumentPluginClasspath,latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.datadoghq.okio:okio:1.17.6=compileClasspath,instrumentPluginClasspath,latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.datadoghq:dd-javac-plugin-client:0.2.2=compileClasspath,instrumentPluginClasspath,latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleBootstrap,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.datadoghq:java-dogstatsd-client:4.4.3=instrumentPluginClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.datadoghq:sketches-java:0.8.3=instrumentPluginClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.fasterxml.jackson.core:jackson-annotations:2.10.3=latestDepForkedTestCompileClasspath,latestDepTestCompileClasspath,testCompileClasspath com.fasterxml.jackson.core:jackson-annotations:2.13.5=testRuntimeClasspath -com.fasterxml.jackson.core:jackson-annotations:2.16.2=latestDepTestRuntimeClasspath +com.fasterxml.jackson.core:jackson-annotations:2.16.2=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath com.fasterxml.jackson.core:jackson-core:2.13.5=testRuntimeClasspath -com.fasterxml.jackson.core:jackson-core:2.16.2=latestDepTestRuntimeClasspath +com.fasterxml.jackson.core:jackson-core:2.16.2=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath com.fasterxml.jackson.core:jackson-databind:2.13.5=testRuntimeClasspath -com.fasterxml.jackson.core:jackson-databind:2.16.2=latestDepTestRuntimeClasspath +com.fasterxml.jackson.core:jackson-databind:2.16.2=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath com.fasterxml.jackson.dataformat:jackson-dataformat-csv:2.13.5=testRuntimeClasspath -com.fasterxml.jackson.dataformat:jackson-dataformat-csv:2.16.2=latestDepTestRuntimeClasspath +com.fasterxml.jackson.dataformat:jackson-dataformat-csv:2.16.2=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.13.5=testRuntimeClasspath -com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.16.2=latestDepTestRuntimeClasspath +com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.16.2=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath com.fasterxml.jackson.module:jackson-module-scala_2.13:2.13.5=testRuntimeClasspath -com.fasterxml.jackson.module:jackson-module-scala_2.13:2.16.2=latestDepTestRuntimeClasspath +com.fasterxml.jackson.module:jackson-module-scala_2.13:2.16.2=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath com.fasterxml.jackson:jackson-bom:2.13.5=testRuntimeClasspath -com.fasterxml.jackson:jackson-bom:2.16.2=latestDepTestRuntimeClasspath -com.github.ben-manes.caffeine:caffeine:2.9.3=latestDepTestRuntimeClasspath,testRuntimeClasspath -com.github.docker-java:docker-java-api:3.2.13=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -com.github.docker-java:docker-java-transport-zerodep:3.2.13=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -com.github.docker-java:docker-java-transport:3.2.13=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -com.github.javaparser:javaparser-core:3.25.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -com.github.jnr:jffi:1.3.13=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.github.jnr:jnr-a64asm:1.0.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.github.jnr:jnr-constants:0.10.4=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.github.jnr:jnr-enxio:0.32.17=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.github.jnr:jnr-ffi:2.2.16=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.github.jnr:jnr-posix:3.1.19=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.github.jnr:jnr-unixsocket:0.38.22=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.github.jnr:jnr-x86asm:1.0.2=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.fasterxml.jackson:jackson-bom:2.16.2=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath +com.github.ben-manes.caffeine:caffeine:2.9.3=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath +com.github.docker-java:docker-java-api:3.2.13=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.github.docker-java:docker-java-transport-zerodep:3.2.13=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.github.docker-java:docker-java-transport:3.2.13=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.github.javaparser:javaparser-core:3.25.1=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.github.jnr:jffi:1.3.13=instrumentPluginClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-a64asm:1.0.0=instrumentPluginClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-constants:0.10.4=instrumentPluginClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-enxio:0.32.17=instrumentPluginClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-ffi:2.2.16=instrumentPluginClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-posix:3.1.19=instrumentPluginClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-unixsocket:0.38.22=instrumentPluginClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.github.jnr:jnr-x86asm:1.0.2=instrumentPluginClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath com.github.luben:zstd-jni:1.5.6-3=testRuntimeClasspath -com.github.luben:zstd-jni:1.5.6-4=latestDepTestRuntimeClasspath -com.github.spotbugs:spotbugs-annotations:4.2.0=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.github.luben:zstd-jni:1.5.6-6=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath +com.github.spotbugs:spotbugs-annotations:4.2.0=compileClasspath,latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath com.github.spotbugs:spotbugs-annotations:4.7.3=spotbugs com.github.spotbugs:spotbugs:4.7.3=spotbugs -com.github.stefanbirkner:system-rules:1.19.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -com.google.auto.service:auto-service-annotations:1.0-rc7=annotationProcessor,compileClasspath,latestDepTestAnnotationProcessor,latestDepTestCompileClasspath,testAnnotationProcessor,testCompileClasspath -com.google.auto.service:auto-service:1.0-rc7=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor -com.google.auto:auto-common:0.10=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor -com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,compileClasspath,latestDepTestAnnotationProcessor,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath +com.github.stefanbirkner:system-rules:1.19.0=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.auto.service:auto-service-annotations:1.0-rc7=annotationProcessor,compileClasspath,latestDepForkedTestAnnotationProcessor,latestDepForkedTestCompileClasspath,latestDepTestAnnotationProcessor,latestDepTestCompileClasspath,testAnnotationProcessor,testCompileClasspath +com.google.auto.service:auto-service:1.0-rc7=annotationProcessor,latestDepForkedTestAnnotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.auto:auto-common:0.10=annotationProcessor,latestDepForkedTestAnnotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,compileClasspath,latestDepForkedTestAnnotationProcessor,latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestAnnotationProcessor,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath com.google.code.gson:gson:2.9.1=spotbugs -com.google.errorprone:error_prone_annotations:2.10.0=latestDepTestRuntimeClasspath,testRuntimeClasspath -com.google.errorprone:error_prone_annotations:2.2.0=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor -com.google.guava:failureaccess:1.0.1=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor -com.google.guava:guava:20.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -com.google.guava:guava:27.0.1-jre=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor -com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor -com.google.j2objc:j2objc-annotations:1.1=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor -com.google.re2j:re2j:1.7=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -com.squareup.moshi:moshi:1.11.0=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.squareup.okhttp3:logging-interceptor:3.12.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -com.squareup.okhttp3:okhttp:3.12.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -com.squareup.okio:okio:1.17.5=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.thoughtworks.paranamer:paranamer:2.8=latestDepTestRuntimeClasspath,testRuntimeClasspath -com.thoughtworks.qdox:qdox:1.12.1=latestDepTestRuntimeClasspath,testRuntimeClasspath -com.typesafe.scala-logging:scala-logging_2.13:3.9.4=latestDepTestRuntimeClasspath,testRuntimeClasspath -com.yammer.metrics:metrics-core:2.2.0=latestDepTestRuntimeClasspath,testRuntimeClasspath -commons-beanutils:commons-beanutils:1.9.4=latestDepTestRuntimeClasspath,testRuntimeClasspath -commons-cli:commons-cli:1.4=latestDepTestRuntimeClasspath,testRuntimeClasspath +com.google.errorprone:error_prone_annotations:2.10.0=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath +com.google.errorprone:error_prone_annotations:2.2.0=annotationProcessor,latestDepForkedTestAnnotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.guava:failureaccess:1.0.1=annotationProcessor,latestDepForkedTestAnnotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.guava:guava:20.0=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.guava:guava:27.0.1-jre=annotationProcessor,latestDepForkedTestAnnotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,latestDepForkedTestAnnotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.j2objc:j2objc-annotations:1.1=annotationProcessor,latestDepForkedTestAnnotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +com.google.re2j:re2j:1.7=instrumentPluginClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +com.squareup.moshi:moshi:1.11.0=compileClasspath,instrumentPluginClasspath,latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.squareup.okhttp3:logging-interceptor:3.12.12=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.squareup.okhttp3:okhttp:3.12.12=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +com.squareup.okio:okio:1.17.5=compileClasspath,instrumentPluginClasspath,latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.thoughtworks.paranamer:paranamer:2.8=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath +com.thoughtworks.qdox:qdox:1.12.1=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath +com.typesafe.scala-logging:scala-logging_2.13:3.9.4=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath +com.yammer.metrics:metrics-core:2.2.0=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath +commons-beanutils:commons-beanutils:1.9.4=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath +commons-cli:commons-cli:1.4=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath commons-codec:commons-codec:1.15=spotbugs -commons-collections:commons-collections:3.2.2=latestDepTestRuntimeClasspath,testRuntimeClasspath -commons-digester:commons-digester:2.1=latestDepTestRuntimeClasspath,testRuntimeClasspath -commons-fileupload:commons-fileupload:1.5=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -commons-io:commons-io:2.11.0=latestDepTestCompileClasspath,testCompileClasspath,testRuntimeClasspath -commons-io:commons-io:2.14.0=latestDepTestRuntimeClasspath -commons-logging:commons-logging:1.2=latestDepTestRuntimeClasspath -commons-validator:commons-validator:1.7=latestDepTestRuntimeClasspath,testRuntimeClasspath +commons-collections:commons-collections:3.2.2=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath +commons-digester:commons-digester:2.1=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath +commons-fileupload:commons-fileupload:1.5=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +commons-io:commons-io:2.11.0=latestDepForkedTestCompileClasspath,latestDepTestCompileClasspath,testCompileClasspath,testRuntimeClasspath +commons-io:commons-io:2.14.0=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath +commons-logging:commons-logging:1.3.4=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +commons-validator:commons-validator:1.7=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath de.thetaphi:forbiddenapis:3.8=compileClasspath -info.picocli:picocli:4.6.3=latestDepTestRuntimeClasspath,testRuntimeClasspath -io.dropwizard.metrics:metrics-core:4.1.12.1=latestDepTestRuntimeClasspath,testRuntimeClasspath +info.picocli:picocli:4.6.3=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath +io.dropwizard.metrics:metrics-core:4.1.12.1=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath io.micrometer:micrometer-commons:1.12.0=testCompileClasspath,testRuntimeClasspath -io.micrometer:micrometer-commons:1.14.4=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +io.micrometer:micrometer-commons:1.15.0-M3=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath io.micrometer:micrometer-observation:1.12.0=testCompileClasspath,testRuntimeClasspath -io.micrometer:micrometer-observation:1.14.4=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath -io.netty:netty-buffer:4.1.105.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +io.micrometer:micrometer-observation:1.15.0-M3=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +io.netty:netty-buffer:4.1.105.Final=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath io.netty:netty-buffer:4.1.94.Final=testCompileClasspath,testRuntimeClasspath -io.netty:netty-codec:4.1.105.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +io.netty:netty-codec:4.1.105.Final=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath io.netty:netty-codec:4.1.94.Final=testCompileClasspath,testRuntimeClasspath -io.netty:netty-common:4.1.105.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +io.netty:netty-common:4.1.105.Final=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath io.netty:netty-common:4.1.94.Final=testCompileClasspath,testRuntimeClasspath -io.netty:netty-handler:4.1.105.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +io.netty:netty-handler:4.1.105.Final=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath io.netty:netty-handler:4.1.94.Final=testCompileClasspath,testRuntimeClasspath -io.netty:netty-resolver:4.1.105.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +io.netty:netty-resolver:4.1.105.Final=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath io.netty:netty-resolver:4.1.94.Final=testCompileClasspath,testRuntimeClasspath -io.netty:netty-transport-classes-epoll:4.1.105.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +io.netty:netty-transport-classes-epoll:4.1.105.Final=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath io.netty:netty-transport-classes-epoll:4.1.94.Final=testCompileClasspath,testRuntimeClasspath -io.netty:netty-transport-native-epoll:4.1.105.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +io.netty:netty-transport-native-epoll:4.1.105.Final=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath io.netty:netty-transport-native-epoll:4.1.94.Final=testCompileClasspath,testRuntimeClasspath -io.netty:netty-transport-native-unix-common:4.1.105.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +io.netty:netty-transport-native-unix-common:4.1.105.Final=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath io.netty:netty-transport-native-unix-common:4.1.94.Final=testCompileClasspath,testRuntimeClasspath -io.netty:netty-transport:4.1.105.Final=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +io.netty:netty-transport:4.1.105.Final=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath io.netty:netty-transport:4.1.94.Final=testCompileClasspath,testRuntimeClasspath -io.sqreen:libsqreen:12.0.0=latestDepTestRuntimeClasspath,testRuntimeClasspath -javax.activation:activation:1.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -javax.servlet:javax.servlet-api:3.1.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -javax.xml.bind:jaxb-api:2.2.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -javax.xml.stream:stax-api:1.0-2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +io.sqreen:libsqreen:12.0.0=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath +javax.activation:activation:1.1=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +javax.servlet:javax.servlet-api:3.1.0=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +javax.xml.bind:jaxb-api:2.2.3=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +javax.xml.stream:stax-api:1.0-2=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath jaxen:jaxen:1.2.0=spotbugs -jline:jline:2.14.6=latestDepTestRuntimeClasspath,testRuntimeClasspath -junit:junit-dep:4.11=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -junit:junit:4.13.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -net.bytebuddy:byte-buddy-agent:1.14.18=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -net.bytebuddy:byte-buddy:1.14.18=compileClasspath,instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -net.java.dev.jna:jna-platform:5.8.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -net.java.dev.jna:jna:5.8.0=instrumentPluginClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -net.jcip:jcip-annotations:1.0=compileClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath -net.sf.jopt-simple:jopt-simple:5.0.4=latestDepTestRuntimeClasspath,testRuntimeClasspath +jline:jline:2.14.6=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath +junit:junit-dep:4.11=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +junit:junit:4.13.2=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +net.bytebuddy:byte-buddy-agent:1.14.18=compileClasspath,instrumentPluginClasspath,latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +net.bytebuddy:byte-buddy:1.14.18=compileClasspath,instrumentPluginClasspath,latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +net.java.dev.jna:jna-platform:5.8.0=instrumentPluginClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +net.java.dev.jna:jna:5.8.0=instrumentPluginClasspath,latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +net.jcip:jcip-annotations:1.0=compileClasspath,latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath +net.sf.jopt-simple:jopt-simple:5.0.4=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath net.sf.saxon:Saxon-HE:11.4=spotbugs -net.sourceforge.argparse4j:argparse4j:0.7.0=latestDepTestRuntimeClasspath,testRuntimeClasspath -org.apache.ant:ant-antlr:1.10.12=latestDepTestRuntimeClasspath,testRuntimeClasspath +net.sourceforge.argparse4j:argparse4j:0.7.0=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath +org.apache.ant:ant-antlr:1.10.12=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath org.apache.ant:ant-antlr:1.9.15=codenarc -org.apache.ant:ant-junit:1.10.12=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.apache.ant:ant-junit:1.10.12=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath org.apache.ant:ant-junit:1.9.15=codenarc -org.apache.ant:ant-launcher:1.10.12=latestDepTestRuntimeClasspath,testRuntimeClasspath -org.apache.ant:ant:1.10.12=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.apache.ant:ant-launcher:1.10.12=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath +org.apache.ant:ant:1.10.12=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath org.apache.bcel:bcel:6.5.0=spotbugs -org.apache.commons:commons-compress:1.21=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.apache.commons:commons-compress:1.21=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath org.apache.commons:commons-lang3:3.12.0=spotbugs org.apache.commons:commons-text:1.10.0=spotbugs org.apache.httpcomponents.client5:httpclient5:5.1.3=spotbugs org.apache.httpcomponents.core5:httpcore5-h2:5.1.3=spotbugs org.apache.httpcomponents.core5:httpcore5:5.1.3=spotbugs org.apache.kafka:kafka-clients:3.8.0=main_java17CompileClasspath,testCompileClasspath,testRuntimeClasspath -org.apache.kafka:kafka-clients:3.9.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath -org.apache.kafka:kafka-group-coordinator-api:3.8.1=latestDepTestRuntimeClasspath +org.apache.kafka:kafka-clients:4.0.0=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.apache.kafka:kafka-group-coordinator-api:3.8.1=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath org.apache.kafka:kafka-group-coordinator:3.6.0=testRuntimeClasspath -org.apache.kafka:kafka-group-coordinator:3.8.1=latestDepTestRuntimeClasspath +org.apache.kafka:kafka-group-coordinator:3.8.1=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath org.apache.kafka:kafka-metadata:3.6.0=testCompileClasspath,testRuntimeClasspath -org.apache.kafka:kafka-metadata:3.8.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.apache.kafka:kafka-metadata:3.8.1=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath org.apache.kafka:kafka-raft:3.6.0=testRuntimeClasspath -org.apache.kafka:kafka-raft:3.8.1=latestDepTestRuntimeClasspath +org.apache.kafka:kafka-raft:3.8.1=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath org.apache.kafka:kafka-server-common:3.6.0=testCompileClasspath,testRuntimeClasspath -org.apache.kafka:kafka-server-common:3.8.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath -org.apache.kafka:kafka-server:3.8.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.apache.kafka:kafka-server-common:3.8.1=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.apache.kafka:kafka-server:3.8.1=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath org.apache.kafka:kafka-storage-api:3.6.0=testRuntimeClasspath -org.apache.kafka:kafka-storage-api:3.8.1=latestDepTestRuntimeClasspath +org.apache.kafka:kafka-storage-api:3.8.1=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath org.apache.kafka:kafka-storage:3.6.0=testRuntimeClasspath -org.apache.kafka:kafka-storage:3.8.1=latestDepTestRuntimeClasspath +org.apache.kafka:kafka-storage:3.8.1=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath org.apache.kafka:kafka-streams-test-utils:3.6.0=testCompileClasspath,testRuntimeClasspath -org.apache.kafka:kafka-streams-test-utils:3.8.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.apache.kafka:kafka-streams-test-utils:3.8.1=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath org.apache.kafka:kafka-streams:3.6.0=testCompileClasspath,testRuntimeClasspath -org.apache.kafka:kafka-streams:3.8.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.apache.kafka:kafka-streams:3.8.1=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath org.apache.kafka:kafka-tools-api:3.6.0=testRuntimeClasspath -org.apache.kafka:kafka-tools-api:3.8.1=latestDepTestRuntimeClasspath -org.apache.kafka:kafka-transaction-coordinator:3.8.1=latestDepTestRuntimeClasspath +org.apache.kafka:kafka-tools-api:3.8.1=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath +org.apache.kafka:kafka-transaction-coordinator:3.8.1=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath org.apache.kafka:kafka_2.13:3.6.0=testCompileClasspath,testRuntimeClasspath -org.apache.kafka:kafka_2.13:3.8.1=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.apache.kafka:kafka_2.13:3.8.1=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath org.apache.logging.log4j:log4j-api:2.19.0=spotbugs org.apache.logging.log4j:log4j-core:2.19.0=spotbugs -org.apache.yetus:audience-annotations:0.12.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.apache.yetus:audience-annotations:0.12.0=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath org.apache.zookeeper:zookeeper-jute:3.8.3=testCompileClasspath,testRuntimeClasspath -org.apache.zookeeper:zookeeper-jute:3.8.4=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.apache.zookeeper:zookeeper-jute:3.8.4=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath org.apache.zookeeper:zookeeper:3.8.3=testCompileClasspath,testRuntimeClasspath -org.apache.zookeeper:zookeeper:3.8.4=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath -org.apiguardian:apiguardian-api:1.1.2=latestDepTestCompileClasspath,testCompileClasspath +org.apache.zookeeper:zookeeper:3.8.4=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.apiguardian:apiguardian-api:1.1.2=latestDepForkedTestCompileClasspath,latestDepTestCompileClasspath,testCompileClasspath org.assertj:assertj-core:2.9.1=testCompileClasspath,testRuntimeClasspath -org.assertj:assertj-core:3.19.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.assertj:assertj-core:3.19.0=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath org.bitbucket.b_c:jose4j:0.9.3=testRuntimeClasspath -org.bitbucket.b_c:jose4j:0.9.4=latestDepTestRuntimeClasspath -org.checkerframework:checker-qual:2.5.2=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor -org.checkerframework:checker-qual:3.19.0=latestDepTestRuntimeClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-all:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.bitbucket.b_c:jose4j:0.9.4=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath +org.checkerframework:checker-qual:2.5.2=annotationProcessor,latestDepForkedTestAnnotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +org.checkerframework:checker-qual:3.19.0=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-all:3.0.17=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath org.codehaus.groovy:groovy-ant:2.5.14=codenarc -org.codehaus.groovy:groovy-ant:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-astbuilder:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-cli-picocli:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-console:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-datetime:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-docgenerator:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-ant:3.0.17=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-astbuilder:3.0.17=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-cli-picocli:3.0.17=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-console:3.0.17=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-datetime:3.0.17=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-docgenerator:3.0.17=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath org.codehaus.groovy:groovy-groovydoc:2.5.14=codenarc -org.codehaus.groovy:groovy-groovydoc:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-groovysh:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-jmx:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-groovydoc:3.0.17=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-groovysh:3.0.17=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-jmx:3.0.17=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath org.codehaus.groovy:groovy-json:2.5.14=codenarc -org.codehaus.groovy:groovy-json:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-jsr223:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-macro:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-nio:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-servlet:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-sql:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-swing:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-json:3.0.17=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-jsr223:3.0.17=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-macro:3.0.17=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-nio:3.0.17=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-servlet:3.0.17=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-sql:3.0.17=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-swing:3.0.17=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath org.codehaus.groovy:groovy-templates:2.5.14=codenarc -org.codehaus.groovy:groovy-templates:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-test-junit5:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-test:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.codehaus.groovy:groovy-testng:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-templates:3.0.17=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-test-junit5:3.0.17=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-test:3.0.17=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-testng:3.0.17=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath org.codehaus.groovy:groovy-xml:2.5.14=codenarc -org.codehaus.groovy:groovy-xml:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.groovy:groovy-xml:3.0.17=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath org.codehaus.groovy:groovy:2.5.14=codenarc -org.codehaus.groovy:groovy:3.0.17=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.codehaus.mojo:animal-sniffer-annotations:1.17=annotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor +org.codehaus.groovy:groovy:3.0.17=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.codehaus.mojo:animal-sniffer-annotations:1.17=annotationProcessor,latestDepForkedTestAnnotationProcessor,latestDepTestAnnotationProcessor,testAnnotationProcessor org.codenarc:CodeNarc:2.2.0=codenarc org.dom4j:dom4j:2.1.3=spotbugs -org.eclipse.jetty:jetty-http:9.4.56.v20240826=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty:jetty-io:9.4.56.v20240826=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty:jetty-server:9.4.56.v20240826=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.eclipse.jetty:jetty-util:9.4.56.v20240826=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.eclipse.jetty:jetty-http:9.4.56.v20240826=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.eclipse.jetty:jetty-io:9.4.56.v20240826=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.eclipse.jetty:jetty-server:9.4.56.v20240826=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.eclipse.jetty:jetty-util:9.4.56.v20240826=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath org.gmetrics:GMetrics:1.1=codenarc -org.hamcrest:hamcrest-core:1.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.hamcrest:hamcrest:2.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.jctools:jctools-core:3.3.0=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath -org.jetbrains:annotations:17.0.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.hamcrest:hamcrest-core:1.3=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.hamcrest:hamcrest:2.2=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.jctools:jctools-core:3.3.0=instrumentPluginClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +org.jetbrains:annotations:17.0.0=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.jspecify:jspecify:1.0.0=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath org.junit.jupiter:junit-jupiter-api:5.10.0=testCompileClasspath,testRuntimeClasspath -org.junit.jupiter:junit-jupiter-api:5.11.4=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.junit.jupiter:junit-jupiter-api:5.11.4=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath org.junit.jupiter:junit-jupiter-engine:5.10.0=testRuntimeClasspath -org.junit.jupiter:junit-jupiter-engine:5.11.4=latestDepTestRuntimeClasspath +org.junit.jupiter:junit-jupiter-engine:5.11.4=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath org.junit.platform:junit-platform-commons:1.10.0=testCompileClasspath,testRuntimeClasspath -org.junit.platform:junit-platform-commons:1.11.4=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.junit.platform:junit-platform-commons:1.11.4=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath org.junit.platform:junit-platform-engine:1.10.0=testCompileClasspath,testRuntimeClasspath -org.junit.platform:junit-platform-engine:1.11.4=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.junit.platform:junit-platform-engine:1.11.4=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath org.junit.platform:junit-platform-launcher:1.10.0=testCompileClasspath,testRuntimeClasspath -org.junit.platform:junit-platform-launcher:1.11.4=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.junit.platform:junit-platform-launcher:1.11.4=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath org.junit.platform:junit-platform-runner:1.10.0=testRuntimeClasspath -org.junit.platform:junit-platform-runner:1.11.4=latestDepTestRuntimeClasspath +org.junit.platform:junit-platform-runner:1.11.4=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath org.junit.platform:junit-platform-suite-api:1.10.0=testRuntimeClasspath -org.junit.platform:junit-platform-suite-api:1.11.4=latestDepTestRuntimeClasspath +org.junit.platform:junit-platform-suite-api:1.11.4=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath org.junit.platform:junit-platform-suite-commons:1.10.0=testRuntimeClasspath -org.junit.platform:junit-platform-suite-commons:1.11.4=latestDepTestRuntimeClasspath +org.junit.platform:junit-platform-suite-commons:1.11.4=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath org.junit:junit-bom:5.10.0=testCompileClasspath,testRuntimeClasspath -org.junit:junit-bom:5.11.4=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.junit:junit-bom:5.11.4=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath org.junit:junit-bom:5.9.1=spotbugs -org.lz4:lz4-java:1.8.0=latestDepTestRuntimeClasspath,testRuntimeClasspath -org.mockito:mockito-core:2.19.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.objenesis:objenesis:3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.opentest4j:opentest4j:1.3.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.ow2.asm:asm-analysis:9.2=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +org.lz4:lz4-java:1.8.0=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath +org.mockito:mockito-core:2.19.0=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.objenesis:objenesis:3.3=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.opentest4j:opentest4j:1.3.0=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.ow2.asm:asm-analysis:9.2=instrumentPluginClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath org.ow2.asm:asm-analysis:9.4=spotbugs org.ow2.asm:asm-commons:9.2=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath org.ow2.asm:asm-commons:9.4=spotbugs -org.ow2.asm:asm-commons:9.7.1=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.ow2.asm:asm-commons:9.7.1=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath org.ow2.asm:asm-tree:9.2=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath org.ow2.asm:asm-tree:9.4=spotbugs -org.ow2.asm:asm-tree:9.7.1=latestDepTestRuntimeClasspath,testRuntimeClasspath -org.ow2.asm:asm-util:9.2=instrumentPluginClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath +org.ow2.asm:asm-tree:9.7.1=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath +org.ow2.asm:asm-util:9.2=instrumentPluginClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath,testRuntimeClasspath org.ow2.asm:asm-util:9.4=spotbugs org.ow2.asm:asm:9.2=instrumentPluginClasspath,main_java17RuntimeClasspath,muzzleTooling,runtimeClasspath org.ow2.asm:asm:9.4=spotbugs -org.ow2.asm:asm:9.7.1=latestDepTestRuntimeClasspath,testRuntimeClasspath -org.pcollections:pcollections:4.0.1=latestDepTestRuntimeClasspath,testRuntimeClasspath -org.rnorth.duct-tape:duct-tape:1.0.8=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.rocksdb:rocksdbjni:7.9.2=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.scala-lang.modules:scala-collection-compat_2.13:2.10.0=latestDepTestRuntimeClasspath,testRuntimeClasspath -org.scala-lang.modules:scala-java8-compat_2.13:1.0.2=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.ow2.asm:asm:9.7.1=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath +org.pcollections:pcollections:4.0.1=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath +org.rnorth.duct-tape:duct-tape:1.0.8=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.rocksdb:rocksdbjni:7.9.2=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.scala-lang.modules:scala-collection-compat_2.13:2.10.0=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath +org.scala-lang.modules:scala-java8-compat_2.13:1.0.2=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath org.scala-lang:scala-library:2.13.11=testCompileClasspath,testRuntimeClasspath -org.scala-lang:scala-library:2.13.14=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.scala-lang:scala-library:2.13.14=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath org.scala-lang:scala-reflect:2.13.11=testRuntimeClasspath -org.scala-lang:scala-reflect:2.13.14=latestDepTestRuntimeClasspath -org.slf4j:jcl-over-slf4j:1.7.30=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.slf4j:jul-to-slf4j:1.7.30=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.slf4j:log4j-over-slf4j:1.7.30=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.scala-lang:scala-reflect:2.13.14=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath +org.slf4j:jcl-over-slf4j:1.7.30=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.slf4j:jul-to-slf4j:1.7.30=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.slf4j:log4j-over-slf4j:1.7.30=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath org.slf4j:slf4j-api:1.7.30=compileClasspath,instrumentPluginClasspath,main_java17CompileClasspath,main_java17RuntimeClasspath,muzzleBootstrap,muzzleTooling,runtimeClasspath -org.slf4j:slf4j-api:1.7.35=latestDepTestCompileClasspath,testCompileClasspath -org.slf4j:slf4j-api:1.7.36=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.slf4j:slf4j-api:1.7.35=latestDepForkedTestCompileClasspath,latestDepTestCompileClasspath,testCompileClasspath +org.slf4j:slf4j-api:1.7.36=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath org.slf4j:slf4j-api:2.0.0=spotbugs,spotbugsSlf4j org.slf4j:slf4j-simple:2.0.0=spotbugsSlf4j -org.spockframework:spock-core:2.2-groovy-3.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.spockframework:spock-junit4:2.2-groovy-3.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.spockframework:spock-core:2.2-groovy-3.0=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.spockframework:spock-junit4:2.2-groovy-3.0=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath org.springframework.kafka:spring-kafka-test:3.1.0=testCompileClasspath,testRuntimeClasspath -org.springframework.kafka:spring-kafka-test:3.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.kafka:spring-kafka-test:4.0.0-M1=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath org.springframework.kafka:spring-kafka:3.1.0=testCompileClasspath,testRuntimeClasspath -org.springframework.kafka:spring-kafka:3.3.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath -org.springframework.retry:spring-retry:2.0.11=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.kafka:spring-kafka:4.0.0-M1=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework.retry:spring-retry:2.0.11=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath org.springframework.retry:spring-retry:2.0.4=testCompileClasspath,testRuntimeClasspath org.springframework:spring-aop:6.1.0=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-aop:6.2.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-aop:7.0.0-M3=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath org.springframework:spring-beans:6.1.0=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-beans:6.2.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-beans:7.0.0-M3=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath org.springframework:spring-context:6.1.0=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-context:6.2.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-context:7.0.0-M3=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath org.springframework:spring-core:6.1.0=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-core:6.2.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-core:7.0.0-M3=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath org.springframework:spring-expression:6.1.0=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-expression:6.2.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-expression:7.0.0-M3=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath org.springframework:spring-jcl:6.1.0=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-jcl:6.2.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath org.springframework:spring-messaging:6.1.0=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-messaging:6.2.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-messaging:7.0.0-M3=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath org.springframework:spring-test:6.1.0=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-test:6.2.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.springframework:spring-test:7.0.0-M3=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath org.springframework:spring-tx:6.1.0=testCompileClasspath,testRuntimeClasspath -org.springframework:spring-tx:6.2.3=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath -org.testcontainers:kafka:1.17.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.testcontainers:testcontainers:1.17.0=latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath -org.testng:testng:7.5=latestDepTestRuntimeClasspath,testRuntimeClasspath -org.webjars:jquery:3.5.1=latestDepTestRuntimeClasspath,testRuntimeClasspath -org.xerial.snappy:snappy-java:1.1.10.5=latestDepTestRuntimeClasspath,testRuntimeClasspath +org.springframework:spring-tx:7.0.0-M3=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath +org.testcontainers:kafka:1.17.0=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.testcontainers:testcontainers:1.17.0=latestDepForkedTestCompileClasspath,latestDepForkedTestRuntimeClasspath,latestDepTestCompileClasspath,latestDepTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath +org.testng:testng:7.5=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath +org.webjars:jquery:3.5.1=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath +org.xerial.snappy:snappy-java:1.1.10.5=latestDepForkedTestRuntimeClasspath,latestDepTestRuntimeClasspath,testRuntimeClasspath org.xmlresolver:xmlresolver:4.4.3=spotbugs xml-apis:xml-apis:1.4.01=spotbugs empty=main_java17AnnotationProcessor,spotbugsPlugins diff --git a/dd-java-agent/instrumentation/kafka-clients-3.8/src/main/java17/datadog/trace/instrumentation/kafka_clients38/ProducerAdvice.java b/dd-java-agent/instrumentation/kafka-clients-3.8/src/main/java17/datadog/trace/instrumentation/kafka_clients38/ProducerAdvice.java index a2e0feff854..0756f585b52 100644 --- a/dd-java-agent/instrumentation/kafka-clients-3.8/src/main/java17/datadog/trace/instrumentation/kafka_clients38/ProducerAdvice.java +++ b/dd-java-agent/instrumentation/kafka-clients-3.8/src/main/java17/datadog/trace/instrumentation/kafka_clients38/ProducerAdvice.java @@ -26,19 +26,16 @@ import datadog.trace.bootstrap.instrumentation.api.InstrumentationTags; import java.util.LinkedHashMap; import net.bytebuddy.asm.Advice; -import org.apache.kafka.clients.ApiVersions; import org.apache.kafka.clients.Metadata; import org.apache.kafka.clients.producer.Callback; import org.apache.kafka.clients.producer.ProducerConfig; import org.apache.kafka.clients.producer.ProducerRecord; import org.apache.kafka.clients.producer.internals.Sender; -import org.apache.kafka.common.record.RecordBatch; public class ProducerAdvice { @Advice.OnMethodEnter(suppress = Throwable.class) public static AgentScope onEnter( - @Advice.FieldValue("apiVersions") final ApiVersions apiVersions, @Advice.FieldValue("producerConfig") ProducerConfig producerConfig, @Advice.FieldValue("sender") Sender sender, @Advice.FieldValue("metadata") Metadata metadata, @@ -64,8 +61,9 @@ public static AgentScope onEnter( // This can help in mixed client environments where clients < 0.11 that do not support // headers attempt to read messages that were produced by clients > 0.11 and the magic // value of the broker(s) is >= 2 - if (apiVersions.maxUsableProduceMagic() >= RecordBatch.MAGIC_VALUE_V2 - && Config.get().isKafkaClientPropagationEnabled() + + // Please note that the minimum magic for kafka 3.8+ is 2 so there is no need to check this + if (Config.get().isKafkaClientPropagationEnabled() && !Config.get().isKafkaClientPropagationDisabledForTopic(record.topic())) { setter = TextMapInjectAdapter.SETTER; } diff --git a/dd-java-agent/instrumentation/kafka-clients-3.8/src/test/groovy/KafkaClientCustomPropagationConfigTest.groovy b/dd-java-agent/instrumentation/kafka-clients-3.8/src/test/groovy/KafkaClientCustomPropagationConfigTest.groovy index 5db495e5904..28a5e04cc5a 100644 --- a/dd-java-agent/instrumentation/kafka-clients-3.8/src/test/groovy/KafkaClientCustomPropagationConfigTest.groovy +++ b/dd-java-agent/instrumentation/kafka-clients-3.8/src/test/groovy/KafkaClientCustomPropagationConfigTest.groovy @@ -1,7 +1,6 @@ import datadog.trace.agent.test.AgentTestRunner import datadog.trace.api.config.TraceInstrumentationConfig import datadog.trace.bootstrap.instrumentation.api.AgentSpan -import datadog.trace.test.util.Flaky import org.apache.kafka.clients.consumer.ConsumerRecord import org.apache.kafka.clients.producer.ProducerRecord import org.apache.kafka.common.header.Headers @@ -54,7 +53,6 @@ class KafkaClientCustomPropagationConfigTest extends AgentTestRunner { injectSysConfig("dd.kafka.e2e.duration.enabled", "true") } - @Flaky def "test kafka client header propagation with topic filters"() { setup: injectSysConfig(TraceInstrumentationConfig.KAFKA_CLIENT_PROPAGATION_DISABLED_TOPICS, value as String) @@ -162,7 +160,6 @@ class KafkaClientCustomPropagationConfigTest extends AgentTestRunner { [value, expected1, expected2, expected3, expected4]<< dataTable() } - @Flaky def "test consumer with topic filters"() { setup: injectSysConfig(TraceInstrumentationConfig.KAFKA_CLIENT_PROPAGATION_DISABLED_TOPICS, value as String) diff --git a/dd-java-agent/instrumentation/kafka-clients-3.8/src/test/groovy/KafkaClientTestBase.groovy b/dd-java-agent/instrumentation/kafka-clients-3.8/src/test/groovy/KafkaClientTestBase.groovy index 0f952574a69..1cb068676bd 100644 --- a/dd-java-agent/instrumentation/kafka-clients-3.8/src/test/groovy/KafkaClientTestBase.groovy +++ b/dd-java-agent/instrumentation/kafka-clients-3.8/src/test/groovy/KafkaClientTestBase.groovy @@ -7,7 +7,6 @@ import datadog.trace.bootstrap.instrumentation.api.Tags import datadog.trace.common.writer.ListWriter import datadog.trace.core.DDSpan import datadog.trace.core.datastreams.StatsGroup -import datadog.trace.test.util.Flaky import org.apache.kafka.clients.consumer.ConsumerConfig import org.apache.kafka.clients.consumer.ConsumerRecord import org.apache.kafka.clients.consumer.KafkaConsumer @@ -31,12 +30,10 @@ import org.testcontainers.utility.DockerImageName import java.util.concurrent.ExecutionException import java.util.concurrent.Future - -import static datadog.trace.agent.test.utils.TraceUtils.basicSpan - import java.util.concurrent.LinkedBlockingQueue import java.util.concurrent.TimeUnit +import static datadog.trace.agent.test.utils.TraceUtils.basicSpan import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activeSpan import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.isAsyncPropagationEnabled @@ -151,7 +148,6 @@ abstract class KafkaClientTestBase extends VersionedNamingTestBase { return true } - @Flaky def "test kafka produce and consume"() { setup: // Create and start a Kafka container using Testcontainers @@ -294,7 +290,6 @@ abstract class KafkaClientTestBase extends VersionedNamingTestBase { kafkaContainer.stop() } - @Flaky def "test producing message too large"() { setup: // set a low max request size, so that we can crash it @@ -317,7 +312,6 @@ abstract class KafkaClientTestBase extends VersionedNamingTestBase { producer.close() } - @Flaky def "test spring kafka template produce and consume"() { setup: KafkaContainer kafkaContainer = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:latest")).withEmbeddedZookeeper().withEnv("KAFKA_CREATE_TOPICS", SHARED_TOPIC) @@ -461,7 +455,6 @@ abstract class KafkaClientTestBase extends VersionedNamingTestBase { kafkaContainer.stop() } - @Flaky def "test pass through tombstone"() { setup: KafkaContainer kafkaContainer = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:latest")).withEmbeddedZookeeper().withEnv("KAFKA_CREATE_TOPICS", SHARED_TOPIC) @@ -533,7 +526,6 @@ abstract class KafkaClientTestBase extends VersionedNamingTestBase { } - @Flaky def "test records(TopicPartition) kafka consume"() { setup: KafkaContainer kafkaContainer = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:latest")).withEmbeddedZookeeper().withEnv("KAFKA_CREATE_TOPICS", SHARED_TOPIC) @@ -594,7 +586,6 @@ abstract class KafkaClientTestBase extends VersionedNamingTestBase { } - @Flaky def "test records(TopicPartition).subList kafka consume"() { setup: @@ -657,7 +648,6 @@ abstract class KafkaClientTestBase extends VersionedNamingTestBase { } - @Flaky def "test records(TopicPartition).forEach kafka consume"() { setup: KafkaContainer kafkaContainer = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:latest")).withEmbeddedZookeeper().withEnv("KAFKA_CREATE_TOPICS", SHARED_TOPIC) @@ -719,7 +709,6 @@ abstract class KafkaClientTestBase extends VersionedNamingTestBase { } - @Flaky def "test iteration backwards over ConsumerRecords"() { setup: KafkaContainer kafkaContainer = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:latest")).withEmbeddedZookeeper().withEnv("KAFKA_CREATE_TOPICS", SHARED_TOPIC) @@ -834,7 +823,6 @@ abstract class KafkaClientTestBase extends VersionedNamingTestBase { } - @Flaky def "test kafka client header propagation manual config"() { setup: KafkaContainer kafkaContainer = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:latest")).withEmbeddedZookeeper().withEnv("KAFKA_CREATE_TOPICS", SHARED_TOPIC) diff --git a/dd-java-agent/instrumentation/kafka-connect-0.11/build.gradle b/dd-java-agent/instrumentation/kafka-connect-0.11/build.gradle index d5717e78304..e5ac493608e 100644 --- a/dd-java-agent/instrumentation/kafka-connect-0.11/build.gradle +++ b/dd-java-agent/instrumentation/kafka-connect-0.11/build.gradle @@ -3,6 +3,7 @@ muzzle { group = "org.apache.kafka" module = "connect-runtime" versions = "[0.11.0.0,)" + javaVersion = "17" assertInverse = true } } From 3f336db5e4486f4e356233289d420ca7f0397b3c Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Tue, 18 Mar 2025 15:48:18 +0000 Subject: [PATCH 60/98] List components:yaml in the dependencies to exclude outside of shared, to avoid duplication --- gradle/dependencies.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index 636efdf3f04..1f1141844f2 100644 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -18,6 +18,7 @@ final class CachedData { exclude(project(':communication')) exclude(project(':components:context')) exclude(project(':components:json')) + exclude(project(':components:yaml')) exclude(project(':remote-config:remote-config-api')) exclude(project(':remote-config:remote-config-core')) exclude(project(':telemetry')) From 0c2b8e2737c25e69c792c67b336ecfaf815a7d4b Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Tue, 18 Mar 2025 16:33:25 +0000 Subject: [PATCH 61/98] fix muzzle on CI --- dd-java-agent/instrumentation/snakeyaml/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dd-java-agent/instrumentation/snakeyaml/build.gradle b/dd-java-agent/instrumentation/snakeyaml/build.gradle index bf4e8688130..8894e9b8ed2 100644 --- a/dd-java-agent/instrumentation/snakeyaml/build.gradle +++ b/dd-java-agent/instrumentation/snakeyaml/build.gradle @@ -26,7 +26,7 @@ dependencies { } muzzleBootstrap('org.yaml:snakeyaml') { version { - strictly '1.+' + strictly '1.33' } } From c9d4c103a064b3e0ff4dfe48ec286cccd9e0dbd6 Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Tue, 18 Mar 2025 16:12:38 -0400 Subject: [PATCH 62/98] Improve StableConfig exception logging --- .../java/datadog.yaml/ConfigurationMap.java | 29 ++++++++++ .../yaml/src/main/java/datadog.yaml/Rule.java | 39 +++++++++++++ .../src/main/java/datadog.yaml/Selector.java | 58 +++++++++++++++++++ .../java/datadog.yaml/StableConfigYaml.java | 41 +++++++++++++ .../config/provider/StableConfigSource.java | 3 +- 5 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 components/yaml/src/main/java/datadog.yaml/ConfigurationMap.java create mode 100644 components/yaml/src/main/java/datadog.yaml/Rule.java create mode 100644 components/yaml/src/main/java/datadog.yaml/Selector.java create mode 100644 components/yaml/src/main/java/datadog.yaml/StableConfigYaml.java diff --git a/components/yaml/src/main/java/datadog.yaml/ConfigurationMap.java b/components/yaml/src/main/java/datadog.yaml/ConfigurationMap.java new file mode 100644 index 00000000000..c7b75bd6e25 --- /dev/null +++ b/components/yaml/src/main/java/datadog.yaml/ConfigurationMap.java @@ -0,0 +1,29 @@ +package datadog.yaml; + +import java.util.HashMap; +import java.util.Map; + +// TODO: Update this comment from "stable configuration" to whatever product decides on for the name +// ConfigurationMap represents configuration key-values found in stable configuration files +public class ConfigurationMap extends HashMap { + public ConfigurationMap() { + return; + } + + public ConfigurationMap(Map map) { + super(map); + } +} + +class ConfigurationValue { + private final String value; + + public ConfigurationValue(String value) { + this.value = value; + } + + @Override + public String toString() { + return value; + } +} diff --git a/components/yaml/src/main/java/datadog.yaml/Rule.java b/components/yaml/src/main/java/datadog.yaml/Rule.java new file mode 100644 index 00000000000..d6be3b646f1 --- /dev/null +++ b/components/yaml/src/main/java/datadog.yaml/Rule.java @@ -0,0 +1,39 @@ +package datadog.yaml; + +import java.util.ArrayList; +import java.util.List; + +// TODO: Update this comment from "stable configuration" to whatever product decides on for the name +// Rule represents a set of selectors and their corresponding configurations found in stable +// configuration files +public class Rule { + private List selectors; + private ConfigurationMap configuration; + + public Rule() { + this.selectors = new ArrayList<>(); + this.configuration = new ConfigurationMap(); + } + + public Rule(List selectors, ConfigurationMap configuration) { + this.selectors = selectors; + this.configuration = configuration; + } + + // Getters and setters + public List getSelectors() { + return selectors; + } + + public void setSelectors(List selectors) { + this.selectors = selectors; + } + + public ConfigurationMap getConfiguration() { + return configuration; + } + + public void setConfiguration(ConfigurationMap configuration) { + this.configuration = configuration; + } +} diff --git a/components/yaml/src/main/java/datadog.yaml/Selector.java b/components/yaml/src/main/java/datadog.yaml/Selector.java new file mode 100644 index 00000000000..2fb694a5a54 --- /dev/null +++ b/components/yaml/src/main/java/datadog.yaml/Selector.java @@ -0,0 +1,58 @@ +package datadog.yaml; + +import java.util.ArrayList; +import java.util.List; + +public class Selector { + private String origin; + private String key; + private List matches; + private String operator; + + public Selector() { + this.origin = null; + this.key = null; + this.matches = new ArrayList<>(); + this.operator = null; + } + + public Selector(String origin, String key, List matches, String operator) { + this.origin = origin; + this.key = key; + this.matches = matches; + this.operator = operator; + } + + // Getters and setters + public String getOrigin() { + return origin; + } + + public void setOrigin(String origin) { + this.origin = origin; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public List getMatches() { + return matches; + } + + public void setMatches(List matches) { + this.matches = matches; + } + + public String getOperator() { + return operator; + } + + public void setOperator(String operator) { + this.operator = operator; + } +} diff --git a/components/yaml/src/main/java/datadog.yaml/StableConfigYaml.java b/components/yaml/src/main/java/datadog.yaml/StableConfigYaml.java new file mode 100644 index 00000000000..ccf7615c60a --- /dev/null +++ b/components/yaml/src/main/java/datadog.yaml/StableConfigYaml.java @@ -0,0 +1,41 @@ +package datadog.yaml; + +import java.util.ArrayList; +import java.util.List; + +public class StableConfigYaml { + private String config_id; // optional + private ConfigurationMap apm_configuration_default; + private List apm_configuration_rules; // optional + + public StableConfigYaml() { + this.config_id = null; + this.apm_configuration_default = new ConfigurationMap(); + this.apm_configuration_rules = new ArrayList<>(); + } + + // Getters and setters + public String getConfig_id() { + return config_id; + } + + public void setConfig_id(String config_id) { + this.config_id = config_id; + } + + public ConfigurationMap getApm_configuration_default() { + return apm_configuration_default; + } + + public void setApm_configuration_default(ConfigurationMap apm_configuration_default) { + this.apm_configuration_default = apm_configuration_default; + } + + public List getApm_configuration_rules() { + return apm_configuration_rules; + } + + public void setApm_configuration_rules(List apm_configuration_rules) { + this.apm_configuration_rules = apm_configuration_rules; + } +} diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java index 5bd5132cf85..204fa24680b 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java @@ -40,8 +40,9 @@ public final class StableConfigSource extends ConfigProvider.Source { cfg = StableConfigParser.parse(filePath); } catch (Throwable e) { log.error( - "Encountered the following exception when attempting to read stable configuration file at path: {}, dropping configs: {}", + "Encountered the following exception when attempting to read stable configuration file at path: {}, dropping configs. Exception type: {}, message: {}", file, + e.getClass().getName(), e.getMessage()); cfg = StableConfig.EMPTY; } From 7a8fabe3e082b9e959e4b14d44480ad1ae4dc195 Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Tue, 18 Mar 2025 16:50:59 -0400 Subject: [PATCH 63/98] Include StableConfigYaml in java-agent shadowJar --- dd-java-agent/build.gradle | 2 ++ .../trace/bootstrap/config/provider/StableConfigSource.java | 5 ++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/dd-java-agent/build.gradle b/dd-java-agent/build.gradle index d03ea2e440e..f2db3451b5d 100644 --- a/dd-java-agent/build.gradle +++ b/dd-java-agent/build.gradle @@ -64,6 +64,8 @@ ext.generalShadowJarConfig = { relocate 'org.yaml.snakeyaml', 'datadog.snakeyaml' relocate 'okhttp3', 'datadog.okhttp3' relocate 'okio', 'datadog.okio' + // Include the YAML config classes in bootstrap + relocate 'datadog.trace.bootstrap.config.provider.StableConfigYaml', 'datadog.trace.bootstrap.config.provider.stableconfigyaml' } if (!project.hasProperty("disableShadowRelocate") || !disableShadowRelocate) { diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java index 204fa24680b..313d2bfc29a 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java @@ -40,10 +40,9 @@ public final class StableConfigSource extends ConfigProvider.Source { cfg = StableConfigParser.parse(filePath); } catch (Throwable e) { log.error( - "Encountered the following exception when attempting to read stable configuration file at path: {}, dropping configs. Exception type: {}, message: {}", + "Encountered the following exception when attempting to read stable configuration file at path: {}, dropping configs.\n", file, - e.getClass().getName(), - e.getMessage()); + e); cfg = StableConfig.EMPTY; } this.config = cfg; From d1fc5801b2a6753090302055162a59a160a1e8d1 Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Wed, 19 Mar 2025 09:35:09 -0400 Subject: [PATCH 64/98] Change in selectorMatch switch to return false --- .../trace/bootstrap/config/provider/StableConfigParser.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java index bcfa6997a47..526ee4bb764 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java @@ -136,8 +136,8 @@ public static boolean selectorMatch( // TODO: use CLIHelper once merged return true; case "tags": - // TODO: Determine where tags are sourced from - return true; + // TODO: Support this down the line (Must define the source of "tags" first) + return false; default: return false; } From f1fdaafccf85541d124de202a6ac008c4aedeccb Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Wed, 19 Mar 2025 14:05:58 -0400 Subject: [PATCH 65/98] Make selectorMatch case insensitive --- .../config/provider/StableConfigParser.java | 41 +++++++++++++++---- .../provider/StableConfigParserTest.groovy | 6 ++- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java index 526ee4bb764..a985460d1f4 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java @@ -85,46 +85,69 @@ private static StableConfigSource.StableConfig createStableConfig( return new StableConfigSource.StableConfig(configId, new HashMap<>(configMap)); } + private static boolean validOperatorForLanguageOrigin(String operator) { + operator = operator.toLowerCase(); + switch (operator) { + case "equals": + case "starts_with": + case "ends_with": + case "contains": + return true; + default: + return false; + } + } + // TODO: Make this private again after testing? + // We do all of the case insensitivity modifications in this function, because each selector will + // be viewed just once public static boolean selectorMatch( String origin, List matches, String operator, String key) { - switch (origin) { + switch (origin.toLowerCase()) { case "language": - return matches.contains("Java") || matches.contains("java") && operator.equals("equals"); + if (!validOperatorForLanguageOrigin(operator)) { + return false; + } + for (String entry : matches) { + // loose match on any reference to "*java*" + if (entry.toLowerCase().contains("java")) { + return true; + } + } case "environment_variables": - String envValue = System.getenv(key); + String envValue = System.getenv(key.toUpperCase()); if (envValue == null) { return false; } - switch (operator) { + envValue = envValue.toLowerCase(); + switch (operator.toLowerCase()) { case "exists": // We don't care about the value return true; - // TODO: Determine if substrings are case insensitive case "equals": for (String value : matches) { - if (value.equals(envValue)) { + if (value.equalsIgnoreCase(envValue)) { return true; } } break; case "starts_with": for (String value : matches) { - if (envValue.startsWith(value)) { + if (envValue.startsWith(value.toLowerCase())) { return true; } } break; case "ends_with": for (String value : matches) { - if (envValue.endsWith(value)) { + if (envValue.endsWith(value.toLowerCase())) { return true; } } break; case "contains": for (String value : matches) { - if (envValue.contains(value)) { + if (envValue.contains(value.toLowerCase())) { return true; } } diff --git a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy index 585ca7b1a94..d9aff3f8250 100644 --- a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy +++ b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy @@ -78,12 +78,14 @@ apm_configuration_rules: where: origin | matches | operator | key | expectMatch "language" | ["java"] | "equals" | "" | true + "LANGUAGE" | ["JaVa"] | "EQUALS" | "" | true // check case insensitivity "language" | ["java", "golang"] | "equals" | "" | true - "language" | ["java"] | "starts_with" | "" | false + "language" | ["java"] | "starts_with" | "" | true "language" | ["golang"] | "equals" | "" | false "environment_variables" | [] | "exists" | "DD_TAGS" | true - "environment_variables" | ["team:apm"] | "equals" | "DD_TAGS" | false "environment_variables" | ["team:apm"] | "contains" | "DD_TAGS" | true + "ENVIRONMENT_VARIABLES" | ["TeAm:ApM"] | "CoNtAiNs" | "Dd_TaGs" | true // check case insensitivity + "environment_variables" | ["team:apm"] | "equals" | "DD_TAGS" | false "environment_variables" | ["team:apm"] | "starts_with" | "DD_TAGS" | true "environment_variables" | ["true"] | "equals" | "DD_PROFILING_ENABLED" | true "environment_variables" | ["abcdefg"] | "equals" | "DD_PROFILING_ENABLED" | false From e94a06a01bd90d88d8a94ca62b2711dbc0ce9a26 Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Wed, 19 Mar 2025 15:11:51 -0400 Subject: [PATCH 66/98] fix null ptr exceptions in selectorMatch --- .../config/provider/StableConfigParser.java | 53 ++++++++++--------- .../provider/StableConfigParserTest.groovy | 3 +- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java index a985460d1f4..12b21914128 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java @@ -9,6 +9,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; +import java.util.function.BiPredicate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -98,6 +99,25 @@ private static boolean validOperatorForLanguageOrigin(String operator) { } } + private static boolean checkMatches( + String envValue, List matches, BiPredicate compareFunc) { + // envValue shouldn't be null, but doing an extra check to avoid NullPointerException on + // compareFunc.test + if (envValue == null) { + return false; + } + for (String value : matches) { + if (value == null) { + continue; + } + System.out.println("MTOFF: matching against " + value); + if (compareFunc.test(envValue, value.toLowerCase())) { + return true; + } + } + return false; + } + // TODO: Make this private again after testing? // We do all of the case insensitivity modifications in this function, because each selector will // be viewed just once @@ -115,46 +135,31 @@ public static boolean selectorMatch( } } case "environment_variables": + if (key == null) { + return false; + } + System.out.println("MTOFF: LOOKING FOR ENV " + key.toUpperCase()); String envValue = System.getenv(key.toUpperCase()); if (envValue == null) { return false; } envValue = envValue.toLowerCase(); + System.out.println("MTOFF: ENV VALUE IS " + envValue); switch (operator.toLowerCase()) { case "exists": // We don't care about the value return true; case "equals": - for (String value : matches) { - if (value.equalsIgnoreCase(envValue)) { - return true; - } - } - break; + return checkMatches(envValue, matches, String::equalsIgnoreCase); case "starts_with": - for (String value : matches) { - if (envValue.startsWith(value.toLowerCase())) { - return true; - } - } - break; + return checkMatches(envValue, matches, String::startsWith); case "ends_with": - for (String value : matches) { - if (envValue.endsWith(value.toLowerCase())) { - return true; - } - } - break; + return checkMatches(envValue, matches, String::endsWith); case "contains": - for (String value : matches) { - if (envValue.contains(value.toLowerCase())) { - return true; - } - } + return checkMatches(envValue, matches, String::contains); default: return false; } - return false; case "process_arguments": // TODO: use CLIHelper once merged return true; diff --git a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy index d9aff3f8250..2dacd864aba 100644 --- a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy +++ b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy @@ -13,7 +13,7 @@ class StableConfigParserTest extends DDSpecification { throw new AssertionError("Failed to create test file") } injectEnvConfig("DD_SERVICE", "mysvc") - // From the below yaml, only apm_configuration_default and the second selector should be applied + // From the below yaml, only apm_configuration_default and the second selector should be applied: We use the first matching rule and discard the rest String yaml = """ config_id: 12345 apm_configuration_default: @@ -95,6 +95,7 @@ apm_configuration_rules: "environment_variables" | ["svc"] | "ends_with" | "DD_SERVICE" | true "environment_variables" | ["svc"] | "contains" | "DD_SERVICE" | true "environment_variables" | ["other"] | "contains" | "DD_SERVICE" | false + "environment_variables" | [null] | "contains" | "DD_SERVICE" | false } def "test duplicate entries"() { From a52a393e202cedf626e6d0c8d86f3efeb12a3e6b Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Fri, 21 Mar 2025 14:46:48 -0400 Subject: [PATCH 67/98] convert underlying datastructure to hashmap; split jvm args into key vals --- .../src/main/java/datadog.cli/CLIHelper.java | 101 ++++++++++++++++-- 1 file changed, 94 insertions(+), 7 deletions(-) diff --git a/components/cli/src/main/java/datadog.cli/CLIHelper.java b/components/cli/src/main/java/datadog.cli/CLIHelper.java index 4fdfcc92e7d..c6202449ca1 100644 --- a/components/cli/src/main/java/datadog.cli/CLIHelper.java +++ b/components/cli/src/main/java/datadog.cli/CLIHelper.java @@ -6,26 +6,34 @@ import java.io.IOException; import java.lang.management.ManagementFactory; import java.lang.reflect.Field; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Set; public class CLIHelper { - public static final CLIHelper ARGS = new CLIHelper(initJvmArgs()); + public static final CLIHelper ARGS = new CLIHelper(); - private final HashSet args; + private final Map> args; - public CLIHelper(List args) { - this.args = new HashSet<>(args); + public CLIHelper() { + this.args = parseJvmArgs(initJvmArgs()); } - public HashSet getJvmArgs() { - return this.args; + public Set getJvmArgs() { + return new HashSet<>(args.keySet()); } public boolean contains(String argument) { - return this.args.contains(argument); + return args.containsKey(argument); + } + + public List getValues(String key) { + return args.getOrDefault(key, Collections.emptyList()); } @SuppressForbidden @@ -99,4 +107,83 @@ private static List getJvmArgsFromProcCmdline() throws IOException { return null; } } + + /** + * Parses JVM arguments into a Map where the key is the argument name and the value is a List of + * values. This allows for multiple values for the same key. + * + *

Handles the following formats: - -Dkey=value (system properties) - -X flags (like -Xmx2g) - + * -XX flags (like -XX:+UseG1GC) - -javaagent with values - Other flags like -jar, -cp, etc. + * + * @param args List of JVM arguments to parse + * @return Map containing parsed arguments with lists of values + */ + public static Map> parseJvmArgs(List args) { + Map> parsedArgs = new HashMap<>(); + if (args == null) { + return parsedArgs; + } + + for (String arg : args) { + if (arg == null || arg.isEmpty()) { + continue; + } + + // Handle system properties (-Dkey=value) + if (arg.startsWith("-D")) { + int equalsIndex = arg.indexOf('='); + if (equalsIndex >= 0) { + String key = arg.substring(0, equalsIndex); + String value = arg.substring(equalsIndex + 1); + parsedArgs.computeIfAbsent(key, k -> new ArrayList<>()).add(value); + } else { + parsedArgs.computeIfAbsent(arg, k -> new ArrayList<>()).add(null); + } + continue; + } + + // Handle -XX flags + if (arg.startsWith("-XX:")) { + // -XX flags can have values after = (like -XX:MaxMetaspaceSize=128m) + int equalsIndex = arg.indexOf('='); + if (equalsIndex >= 0) { + String key = arg.substring(0, equalsIndex); + String value = arg.substring(equalsIndex + 1); + parsedArgs.computeIfAbsent("-XX:" + key, k -> new ArrayList<>()).add(value); + } else { + parsedArgs.computeIfAbsent(arg, k -> new ArrayList<>()).add(null); + } + } + + // Handle -javaagent + if (arg.startsWith("-javaagent:")) { + String keyValue = arg.substring(11); // Remove "-javaagent:" prefix + int equalsIndex = keyValue.indexOf('='); + if (equalsIndex >= 0) { + String key = keyValue.substring(0, equalsIndex); + String value = keyValue.substring(equalsIndex + 1); + parsedArgs.computeIfAbsent("-javaagent:" + key, k -> new ArrayList<>()).add(value); + } else { + parsedArgs.computeIfAbsent(arg, k -> new ArrayList<>()).add(null); + } + continue; + } + + // Handle other flags that might have values + // Note that -X flags will not be parsed into key-vals; they'll be caught by the value-less + // case and stored as a key. Therefore, duplicate keys are not supported for -X flags + if (arg.startsWith("-")) { + int equalsIndex = arg.indexOf('='); + if (equalsIndex >= 0) { + String key = arg.substring(0, equalsIndex); + String value = arg.substring(equalsIndex + 1); + parsedArgs.computeIfAbsent(key, k -> new ArrayList<>()).add(value); + } else { + parsedArgs.computeIfAbsent(arg, k -> new ArrayList<>()).add(null); + } + } + } + + return parsedArgs; + } } From dab2bbbb64e59d369b2b4c04e3ca976e146a64b5 Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Fri, 21 Mar 2025 15:53:50 -0400 Subject: [PATCH 68/98] write CLIHelper Test --- .../src/main/java/datadog.cli/CLIHelper.java | 50 +++++++----------- .../groovy/datadog/cli/CLIHelperTest.groovy | 51 +++++++++++++++++++ 2 files changed, 68 insertions(+), 33 deletions(-) create mode 100644 components/cli/src/test/groovy/datadog/cli/CLIHelperTest.groovy diff --git a/components/cli/src/main/java/datadog.cli/CLIHelper.java b/components/cli/src/main/java/datadog.cli/CLIHelper.java index c6202449ca1..4e93662a7f1 100644 --- a/components/cli/src/main/java/datadog.cli/CLIHelper.java +++ b/components/cli/src/main/java/datadog.cli/CLIHelper.java @@ -131,41 +131,20 @@ public static Map> parseJvmArgs(List args) { // Handle system properties (-Dkey=value) if (arg.startsWith("-D")) { - int equalsIndex = arg.indexOf('='); - if (equalsIndex >= 0) { - String key = arg.substring(0, equalsIndex); - String value = arg.substring(equalsIndex + 1); - parsedArgs.computeIfAbsent(key, k -> new ArrayList<>()).add(value); - } else { - parsedArgs.computeIfAbsent(arg, k -> new ArrayList<>()).add(null); - } + addEntryToMap('=', arg, parsedArgs); continue; } // Handle -XX flags if (arg.startsWith("-XX:")) { // -XX flags can have values after = (like -XX:MaxMetaspaceSize=128m) - int equalsIndex = arg.indexOf('='); - if (equalsIndex >= 0) { - String key = arg.substring(0, equalsIndex); - String value = arg.substring(equalsIndex + 1); - parsedArgs.computeIfAbsent("-XX:" + key, k -> new ArrayList<>()).add(value); - } else { - parsedArgs.computeIfAbsent(arg, k -> new ArrayList<>()).add(null); - } + addEntryToMap('=', arg, parsedArgs); + continue; } // Handle -javaagent if (arg.startsWith("-javaagent:")) { - String keyValue = arg.substring(11); // Remove "-javaagent:" prefix - int equalsIndex = keyValue.indexOf('='); - if (equalsIndex >= 0) { - String key = keyValue.substring(0, equalsIndex); - String value = keyValue.substring(equalsIndex + 1); - parsedArgs.computeIfAbsent("-javaagent:" + key, k -> new ArrayList<>()).add(value); - } else { - parsedArgs.computeIfAbsent(arg, k -> new ArrayList<>()).add(null); - } + addEntryToMap(':', arg, parsedArgs); continue; } @@ -173,17 +152,22 @@ public static Map> parseJvmArgs(List args) { // Note that -X flags will not be parsed into key-vals; they'll be caught by the value-less // case and stored as a key. Therefore, duplicate keys are not supported for -X flags if (arg.startsWith("-")) { - int equalsIndex = arg.indexOf('='); - if (equalsIndex >= 0) { - String key = arg.substring(0, equalsIndex); - String value = arg.substring(equalsIndex + 1); - parsedArgs.computeIfAbsent(key, k -> new ArrayList<>()).add(value); - } else { - parsedArgs.computeIfAbsent(arg, k -> new ArrayList<>()).add(null); - } + addEntryToMap('=', arg, parsedArgs); } } return parsedArgs; } + + private static void addEntryToMap( + char equalsOperator, String arg, Map> parsedArgs) { + int equalsIndex = arg.indexOf(equalsOperator); + if (equalsIndex >= 0 && equalsIndex < (arg.length() - 1)) { + String key = arg.substring(0, equalsIndex); + String value = arg.substring(equalsIndex + 1); + parsedArgs.computeIfAbsent(key, k -> new ArrayList<>()).add(value); + } else { + parsedArgs.computeIfAbsent(arg, k -> new ArrayList<>()).add(null); + } + } } diff --git a/components/cli/src/test/groovy/datadog/cli/CLIHelperTest.groovy b/components/cli/src/test/groovy/datadog/cli/CLIHelperTest.groovy new file mode 100644 index 00000000000..3268b4f09c2 --- /dev/null +++ b/components/cli/src/test/groovy/datadog/cli/CLIHelperTest.groovy @@ -0,0 +1,51 @@ +package datadog.cli +import spock.lang.Specification + +class CLIHelperTest extends Specification { + def "test parseJvmArgs"() { + when: + List input = [ + "-XX:MaxMetaspaceSize=128m", + "-XX:+UseG1GC", + "-Dkey=value1", + "-Dkey=value2", + "-DdisableFeature", + "-javaagent:/path/to/dd-java-agent.jar", + "-javaagent:/path/to/another-agent.jar", + "-javaagent", + "-Xmx512", + "-Xdebug", + ] + Map> args = CLIHelper.parseJvmArgs(input) + + then: + // -Xdebug + args.containsKey("-Xdebug") + args.get("-Xdebug") == [null] + + // -Xmx512 + args.containsKey("-Xmx512") + args.get("-Xmx512") == [null] + + // -javaagent + args.containsKey("-javaagent") + args.get("-javaagent") == ["/path/to/dd-java-agent.jar", "/path/to/another-agent.jar", null] + + // -DdisableFeature + args.containsKey("-DdisableFeature") + args.get("-DdisableFeature") == [null] + + // -Dkey + // CLIHelper does not discriminate against what types of jvm args can have duplicate values, it accepts all args found on the process + args.containsKey("-Dkey") + args.get("-Dkey") == ["value1", "value2"] + + //-XX:+UseG1GC + args.containsKey("-XX:+UseG1GC") + args.get("-XX:+UseG1GC") == [null] + + //-XX:MaxMetaspaceSize + args.containsKey("-XX:MaxMetaspaceSize") + args.get("-XX:MaxMetaspaceSize") == ["128m"] + } +} From e9fec188d499613b2a1226d035073193807cb805 Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Fri, 21 Mar 2025 16:09:45 -0400 Subject: [PATCH 69/98] Update javaagent logic inside of AgentBootstrap --- .../src/main/java/datadog.cli/CLIHelper.java | 14 ++--------- .../trace/bootstrap/AgentBootstrap.java | 24 ++++++++----------- 2 files changed, 12 insertions(+), 26 deletions(-) diff --git a/components/cli/src/main/java/datadog.cli/CLIHelper.java b/components/cli/src/main/java/datadog.cli/CLIHelper.java index 4e93662a7f1..92faa1d8377 100644 --- a/components/cli/src/main/java/datadog.cli/CLIHelper.java +++ b/components/cli/src/main/java/datadog.cli/CLIHelper.java @@ -10,10 +10,8 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; public class CLIHelper { public static final CLIHelper ARGS = new CLIHelper(); @@ -24,16 +22,8 @@ public CLIHelper() { this.args = parseJvmArgs(initJvmArgs()); } - public Set getJvmArgs() { - return new HashSet<>(args.keySet()); - } - - public boolean contains(String argument) { - return args.containsKey(argument); - } - - public List getValues(String key) { - return args.getOrDefault(key, Collections.emptyList()); + public List getValues(String jvmArg) { + return this.args.get(jvmArg); } @SuppressForbidden 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 d715c1f3277..3c09987c53c 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 @@ -381,20 +381,16 @@ private static List getAgentFilesFromVMArguments() { // - On IBM-based JDKs since at least 1.7 // This prevents custom log managers from working correctly // Use reflection to bypass the loading of the class~ - for (final String argument : CLIHelper.ARGS.getJvmArgs()) { - if (argument.startsWith(JAVA_AGENT_ARGUMENT)) { - int index = argument.indexOf('=', JAVA_AGENT_ARGUMENT.length()); - String agentPathname = - argument.substring( - JAVA_AGENT_ARGUMENT.length(), index == -1 ? argument.length() : index); - File agentFile = new File(agentPathname); - if (agentFile.exists() && agentFile.isFile()) { - agentFiles.add(agentFile); - } else { - System.err.println( - "Could not get bootstrap jar from -javaagent arg: unable to find javaagent file: " - + agentFile); - } + for (final String argument : CLIHelper.ARGS.getValues(JAVA_AGENT_ARGUMENT)) { + int index = argument.indexOf('='); + String agentPathname = argument.substring(0, index == -1 ? argument.length() : index); + File agentFile = new File(agentPathname); + if (agentFile.exists() && agentFile.isFile()) { + agentFiles.add(agentFile); + } else { + System.err.println( + "Could not get bootstrap jar from -javaagent arg: unable to find javaagent file: " + + agentFile); } } } From f04424e9e9b3a6a979f6cccb1e687bef6906655c Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Fri, 21 Mar 2025 17:00:00 -0400 Subject: [PATCH 70/98] merge with base branch mtoff/jvm-args --- .../src/main/java/datadog.cli/CLIHelper.java | 1 + .../groovy/datadog/cli/CLIHelperTest.groovy | 17 +++---- internal-api/build.gradle | 1 + .../config/provider/StableConfigParser.java | 48 +++++++++++++------ .../provider/StableConfigParserTest.groovy | 2 + 5 files changed, 46 insertions(+), 23 deletions(-) diff --git a/components/cli/src/main/java/datadog.cli/CLIHelper.java b/components/cli/src/main/java/datadog.cli/CLIHelper.java index 92faa1d8377..4cd47f119ee 100644 --- a/components/cli/src/main/java/datadog.cli/CLIHelper.java +++ b/components/cli/src/main/java/datadog.cli/CLIHelper.java @@ -23,6 +23,7 @@ public CLIHelper() { } public List getValues(String jvmArg) { + System.out.println("MTOFF: arg IS " + jvmArg); return this.args.get(jvmArg); } diff --git a/components/cli/src/test/groovy/datadog/cli/CLIHelperTest.groovy b/components/cli/src/test/groovy/datadog/cli/CLIHelperTest.groovy index 3268b4f09c2..1fe7d5a894b 100644 --- a/components/cli/src/test/groovy/datadog/cli/CLIHelperTest.groovy +++ b/components/cli/src/test/groovy/datadog/cli/CLIHelperTest.groovy @@ -11,9 +11,8 @@ class CLIHelperTest extends Specification { "-Dkey=value2", "-DdisableFeature", "-javaagent:/path/to/dd-java-agent.jar", - "-javaagent:/path/to/another-agent.jar", "-javaagent", - "-Xmx512", + "-Xmx256", "-Xdebug", ] Map> args = CLIHelper.parseJvmArgs(input) @@ -23,29 +22,31 @@ class CLIHelperTest extends Specification { args.containsKey("-Xdebug") args.get("-Xdebug") == [null] - // -Xmx512 - args.containsKey("-Xmx512") - args.get("-Xmx512") == [null] + // -Xmx256 + args.containsKey("-Xmx256") + args.get("-Xmx256") == [null] // -javaagent args.containsKey("-javaagent") - args.get("-javaagent") == ["/path/to/dd-java-agent.jar", "/path/to/another-agent.jar", null] + args.get("-javaagent") == ["/path/to/dd-java-agent.jar", null] // -DdisableFeature args.containsKey("-DdisableFeature") args.get("-DdisableFeature") == [null] // -Dkey - // CLIHelper does not discriminate against what types of jvm args can have duplicate values, it accepts all args found on the process args.containsKey("-Dkey") + // The data structure does not discriminate against what types of jvm args are allowed to have duplicate keys; even though typically `javaagent` is the only jvm arg that supports multiple entries + // Therefore, system properties `-Dkey=value -Dkey=value2` will be respected by CLIHelper args.get("-Dkey") == ["value1", "value2"] //-XX:+UseG1GC args.containsKey("-XX:+UseG1GC") args.get("-XX:+UseG1GC") == [null] - //-XX:MaxMetaspaceSize + //-XX:MaxMetaspaceSize=128m args.containsKey("-XX:MaxMetaspaceSize") args.get("-XX:MaxMetaspaceSize") == ["128m"] + } } diff --git a/internal-api/build.gradle b/internal-api/build.gradle index 4e399bd77d9..1e002796965 100644 --- a/internal-api/build.gradle +++ b/internal-api/build.gradle @@ -233,6 +233,7 @@ dependencies { // references TraceScope and Continuation from public api api project(':dd-trace-api') api libs.slf4j + api project(':components:cli') api project(':components:context') api project(':components:yaml') api project(":utils:time-utils") diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java index 12b21914128..893085b523e 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java @@ -1,5 +1,6 @@ package datadog.trace.bootstrap.config.provider; +import datadog.cli.CLIHelper; import datadog.trace.bootstrap.config.provider.stableconfigyaml.ConfigurationMap; import datadog.trace.bootstrap.config.provider.stableconfigyaml.Rule; import datadog.trace.bootstrap.config.provider.stableconfigyaml.Selector; @@ -100,19 +101,20 @@ private static boolean validOperatorForLanguageOrigin(String operator) { } private static boolean checkMatches( - String envValue, List matches, BiPredicate compareFunc) { + List values, List matches, BiPredicate compareFunc) { // envValue shouldn't be null, but doing an extra check to avoid NullPointerException on // compareFunc.test - if (envValue == null) { + if (values == null) { return false; } - for (String value : matches) { - if (value == null) { + for (String match : matches) { + if (match == null) { continue; } - System.out.println("MTOFF: matching against " + value); - if (compareFunc.test(envValue, value.toLowerCase())) { - return true; + for (String value : values) { + if (compareFunc.test(value, match.toLowerCase())) { + return true; + } } } return false; @@ -138,31 +140,47 @@ public static boolean selectorMatch( if (key == null) { return false; } - System.out.println("MTOFF: LOOKING FOR ENV " + key.toUpperCase()); String envValue = System.getenv(key.toUpperCase()); if (envValue == null) { return false; } envValue = envValue.toLowerCase(); - System.out.println("MTOFF: ENV VALUE IS " + envValue); switch (operator.toLowerCase()) { case "exists": // We don't care about the value return true; case "equals": - return checkMatches(envValue, matches, String::equalsIgnoreCase); + return checkMatches( + Collections.singletonList(envValue), matches, String::equalsIgnoreCase); case "starts_with": - return checkMatches(envValue, matches, String::startsWith); + return checkMatches(Collections.singletonList(envValue), matches, String::startsWith); case "ends_with": - return checkMatches(envValue, matches, String::endsWith); + return checkMatches(Collections.singletonList(envValue), matches, String::endsWith); case "contains": - return checkMatches(envValue, matches, String::contains); + return checkMatches(Collections.singletonList(envValue), matches, String::contains); default: return false; } case "process_arguments": - // TODO: use CLIHelper once merged - return true; + List vals = CLIHelper.ARGS.getValues(key); + if (vals == null || vals.isEmpty()) { + return false; + } + switch (operator.toLowerCase()) { + case "exists": + // We don't care about the value + return true; + case "equals": + return checkMatches(vals, matches, String::equalsIgnoreCase); + case "starts_with": + return checkMatches(vals, matches, String::startsWith); + case "ends_with": + return checkMatches(vals, matches, String::endsWith); + case "contains": + return checkMatches(vals, matches, String::contains); + default: + return false; + } case "tags": // TODO: Support this down the line (Must define the source of "tags" first) return false; diff --git a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy index 2dacd864aba..469e00873cc 100644 --- a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy +++ b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy @@ -67,6 +67,7 @@ apm_configuration_rules: // TODO: This test will fail if we make selectorMatch private again def "test selectorMatch"() { when: + // Env vars injectEnvConfig("DD_PROFILING_ENABLED", "true") injectEnvConfig("DD_SERVICE", "mysvc") injectEnvConfig("DD_TAGS", "team:apm,component:web") @@ -96,6 +97,7 @@ apm_configuration_rules: "environment_variables" | ["svc"] | "contains" | "DD_SERVICE" | true "environment_variables" | ["other"] | "contains" | "DD_SERVICE" | false "environment_variables" | [null] | "contains" | "DD_SERVICE" | false + // "process_arguments" | ["true"] | "equals" | "some.property" | true } def "test duplicate entries"() { From 1ac75d9c8293047542a61331ec1f331554f32bee Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Mon, 24 Mar 2025 13:58:54 -0400 Subject: [PATCH 71/98] Rebase with mtoff/jvm-args --- .../src/main/java/datadog.cli/CLIHelper.java | 84 +++---------------- .../trace/bootstrap/AgentBootstrap.java | 24 +++--- .../config/provider/StableConfigParser.java | 40 ++++----- .../provider/StableConfigParserTest.groovy | 1 - 4 files changed, 45 insertions(+), 104 deletions(-) diff --git a/components/cli/src/main/java/datadog.cli/CLIHelper.java b/components/cli/src/main/java/datadog.cli/CLIHelper.java index 4cd47f119ee..4fdfcc92e7d 100644 --- a/components/cli/src/main/java/datadog.cli/CLIHelper.java +++ b/components/cli/src/main/java/datadog.cli/CLIHelper.java @@ -6,25 +6,26 @@ import java.io.IOException; import java.lang.management.ManagementFactory; import java.lang.reflect.Field; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.HashMap; +import java.util.HashSet; import java.util.List; -import java.util.Map; public class CLIHelper { - public static final CLIHelper ARGS = new CLIHelper(); + public static final CLIHelper ARGS = new CLIHelper(initJvmArgs()); - private final Map> args; + private final HashSet args; - public CLIHelper() { - this.args = parseJvmArgs(initJvmArgs()); + public CLIHelper(List args) { + this.args = new HashSet<>(args); } - public List getValues(String jvmArg) { - System.out.println("MTOFF: arg IS " + jvmArg); - return this.args.get(jvmArg); + public HashSet getJvmArgs() { + return this.args; + } + + public boolean contains(String argument) { + return this.args.contains(argument); } @SuppressForbidden @@ -98,67 +99,4 @@ private static List getJvmArgsFromProcCmdline() throws IOException { return null; } } - - /** - * Parses JVM arguments into a Map where the key is the argument name and the value is a List of - * values. This allows for multiple values for the same key. - * - *

Handles the following formats: - -Dkey=value (system properties) - -X flags (like -Xmx2g) - - * -XX flags (like -XX:+UseG1GC) - -javaagent with values - Other flags like -jar, -cp, etc. - * - * @param args List of JVM arguments to parse - * @return Map containing parsed arguments with lists of values - */ - public static Map> parseJvmArgs(List args) { - Map> parsedArgs = new HashMap<>(); - if (args == null) { - return parsedArgs; - } - - for (String arg : args) { - if (arg == null || arg.isEmpty()) { - continue; - } - - // Handle system properties (-Dkey=value) - if (arg.startsWith("-D")) { - addEntryToMap('=', arg, parsedArgs); - continue; - } - - // Handle -XX flags - if (arg.startsWith("-XX:")) { - // -XX flags can have values after = (like -XX:MaxMetaspaceSize=128m) - addEntryToMap('=', arg, parsedArgs); - continue; - } - - // Handle -javaagent - if (arg.startsWith("-javaagent:")) { - addEntryToMap(':', arg, parsedArgs); - continue; - } - - // Handle other flags that might have values - // Note that -X flags will not be parsed into key-vals; they'll be caught by the value-less - // case and stored as a key. Therefore, duplicate keys are not supported for -X flags - if (arg.startsWith("-")) { - addEntryToMap('=', arg, parsedArgs); - } - } - - return parsedArgs; - } - - private static void addEntryToMap( - char equalsOperator, String arg, Map> parsedArgs) { - int equalsIndex = arg.indexOf(equalsOperator); - if (equalsIndex >= 0 && equalsIndex < (arg.length() - 1)) { - String key = arg.substring(0, equalsIndex); - String value = arg.substring(equalsIndex + 1); - parsedArgs.computeIfAbsent(key, k -> new ArrayList<>()).add(value); - } else { - parsedArgs.computeIfAbsent(arg, k -> new ArrayList<>()).add(null); - } - } } 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 3c09987c53c..d715c1f3277 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 @@ -381,16 +381,20 @@ private static List getAgentFilesFromVMArguments() { // - On IBM-based JDKs since at least 1.7 // This prevents custom log managers from working correctly // Use reflection to bypass the loading of the class~ - for (final String argument : CLIHelper.ARGS.getValues(JAVA_AGENT_ARGUMENT)) { - int index = argument.indexOf('='); - String agentPathname = argument.substring(0, index == -1 ? argument.length() : index); - File agentFile = new File(agentPathname); - if (agentFile.exists() && agentFile.isFile()) { - agentFiles.add(agentFile); - } else { - System.err.println( - "Could not get bootstrap jar from -javaagent arg: unable to find javaagent file: " - + agentFile); + for (final String argument : CLIHelper.ARGS.getJvmArgs()) { + if (argument.startsWith(JAVA_AGENT_ARGUMENT)) { + int index = argument.indexOf('=', JAVA_AGENT_ARGUMENT.length()); + String agentPathname = + argument.substring( + JAVA_AGENT_ARGUMENT.length(), index == -1 ? argument.length() : index); + File agentFile = new File(agentPathname); + if (agentFile.exists() && agentFile.isFile()) { + agentFiles.add(agentFile); + } else { + System.err.println( + "Could not get bootstrap jar from -javaagent arg: unable to find javaagent file: " + + agentFile); + } } } } diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java index 893085b523e..bc56575610e 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java @@ -1,6 +1,5 @@ package datadog.trace.bootstrap.config.provider; -import datadog.cli.CLIHelper; import datadog.trace.bootstrap.config.provider.stableconfigyaml.ConfigurationMap; import datadog.trace.bootstrap.config.provider.stableconfigyaml.Rule; import datadog.trace.bootstrap.config.provider.stableconfigyaml.Selector; @@ -162,25 +161,26 @@ public static boolean selectorMatch( return false; } case "process_arguments": - List vals = CLIHelper.ARGS.getValues(key); - if (vals == null || vals.isEmpty()) { - return false; - } - switch (operator.toLowerCase()) { - case "exists": - // We don't care about the value - return true; - case "equals": - return checkMatches(vals, matches, String::equalsIgnoreCase); - case "starts_with": - return checkMatches(vals, matches, String::startsWith); - case "ends_with": - return checkMatches(vals, matches, String::endsWith); - case "contains": - return checkMatches(vals, matches, String::contains); - default: - return false; - } + return true; + // List vals = CLIHelper.ARGS.getValues(key); + // if (vals == null || vals.isEmpty()) { + // return false; + // } + // switch (operator.toLowerCase()) { + // case "exists": + // // We don't care about the value + // return true; + // case "equals": + // return checkMatches(vals, matches, String::equalsIgnoreCase); + // case "starts_with": + // return checkMatches(vals, matches, String::startsWith); + // case "ends_with": + // return checkMatches(vals, matches, String::endsWith); + // case "contains": + // return checkMatches(vals, matches, String::contains); + // default: + // return false; + // } case "tags": // TODO: Support this down the line (Must define the source of "tags" first) return false; diff --git a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy index 469e00873cc..a778dc83da5 100644 --- a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy +++ b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy @@ -97,7 +97,6 @@ apm_configuration_rules: "environment_variables" | ["svc"] | "contains" | "DD_SERVICE" | true "environment_variables" | ["other"] | "contains" | "DD_SERVICE" | false "environment_variables" | [null] | "contains" | "DD_SERVICE" | false - // "process_arguments" | ["true"] | "equals" | "some.property" | true } def "test duplicate entries"() { From 94c6d539cc96bbd8fbeaac612e753b383ee2c58a Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Mon, 24 Mar 2025 14:21:47 -0400 Subject: [PATCH 72/98] remove unused components/cli test dir --- .../groovy/datadog/cli/CLIHelperTest.groovy | 52 ------------------- 1 file changed, 52 deletions(-) delete mode 100644 components/cli/src/test/groovy/datadog/cli/CLIHelperTest.groovy diff --git a/components/cli/src/test/groovy/datadog/cli/CLIHelperTest.groovy b/components/cli/src/test/groovy/datadog/cli/CLIHelperTest.groovy deleted file mode 100644 index 1fe7d5a894b..00000000000 --- a/components/cli/src/test/groovy/datadog/cli/CLIHelperTest.groovy +++ /dev/null @@ -1,52 +0,0 @@ -package datadog.cli -import spock.lang.Specification - -class CLIHelperTest extends Specification { - def "test parseJvmArgs"() { - when: - List input = [ - "-XX:MaxMetaspaceSize=128m", - "-XX:+UseG1GC", - "-Dkey=value1", - "-Dkey=value2", - "-DdisableFeature", - "-javaagent:/path/to/dd-java-agent.jar", - "-javaagent", - "-Xmx256", - "-Xdebug", - ] - Map> args = CLIHelper.parseJvmArgs(input) - - then: - // -Xdebug - args.containsKey("-Xdebug") - args.get("-Xdebug") == [null] - - // -Xmx256 - args.containsKey("-Xmx256") - args.get("-Xmx256") == [null] - - // -javaagent - args.containsKey("-javaagent") - args.get("-javaagent") == ["/path/to/dd-java-agent.jar", null] - - // -DdisableFeature - args.containsKey("-DdisableFeature") - args.get("-DdisableFeature") == [null] - - // -Dkey - args.containsKey("-Dkey") - // The data structure does not discriminate against what types of jvm args are allowed to have duplicate keys; even though typically `javaagent` is the only jvm arg that supports multiple entries - // Therefore, system properties `-Dkey=value -Dkey=value2` will be respected by CLIHelper - args.get("-Dkey") == ["value1", "value2"] - - //-XX:+UseG1GC - args.containsKey("-XX:+UseG1GC") - args.get("-XX:+UseG1GC") == [null] - - //-XX:MaxMetaspaceSize=128m - args.containsKey("-XX:MaxMetaspaceSize") - args.get("-XX:MaxMetaspaceSize") == ["128m"] - - } -} From 73af08727964bacf5fbf4d01e56931c4d5fa4ac1 Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Mon, 24 Mar 2025 14:45:42 -0400 Subject: [PATCH 73/98] Cleanup --- components/cli/src/main/java/datadog.cli/CLIHelper.java | 2 ++ .../trace/bootstrap/config/provider/StableConfigParser.java | 5 ++++- .../bootstrap/config/provider/StableConfigParserTest.groovy | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/components/cli/src/main/java/datadog.cli/CLIHelper.java b/components/cli/src/main/java/datadog.cli/CLIHelper.java index 4fdfcc92e7d..1f00f5be92f 100644 --- a/components/cli/src/main/java/datadog.cli/CLIHelper.java +++ b/components/cli/src/main/java/datadog.cli/CLIHelper.java @@ -24,6 +24,8 @@ public HashSet getJvmArgs() { return this.args; } + // Returns true if argument is part of the current process' JVM Args. `contains` is + // case-sensitive. public boolean contains(String argument) { return this.args.contains(argument); } diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java index bc56575610e..17b41e1eb68 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java @@ -1,5 +1,6 @@ package datadog.trace.bootstrap.config.provider; +import datadog.cli.CLIHelper; import datadog.trace.bootstrap.config.provider.stableconfigyaml.ConfigurationMap; import datadog.trace.bootstrap.config.provider.stableconfigyaml.Rule; import datadog.trace.bootstrap.config.provider.stableconfigyaml.Selector; @@ -161,7 +162,9 @@ public static boolean selectorMatch( return false; } case "process_arguments": - return true; + // For now, always return true if `key` exists in the JVM Args + // TODO: flesh out the meaning of each operator for process_arguments + return CLIHelper.ARGS.contains(key); // List vals = CLIHelper.ARGS.getValues(key); // if (vals == null || vals.isEmpty()) { // return false; diff --git a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy index a778dc83da5..4596ea4a516 100644 --- a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy +++ b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy @@ -71,6 +71,7 @@ apm_configuration_rules: injectEnvConfig("DD_PROFILING_ENABLED", "true") injectEnvConfig("DD_SERVICE", "mysvc") injectEnvConfig("DD_TAGS", "team:apm,component:web") + // injectSysConfig("--DCustomKey", "value") def match = StableConfigParser.selectorMatch(origin, matches, operator, key) then: @@ -97,6 +98,7 @@ apm_configuration_rules: "environment_variables" | ["svc"] | "contains" | "DD_SERVICE" | true "environment_variables" | ["other"] | "contains" | "DD_SERVICE" | false "environment_variables" | [null] | "contains" | "DD_SERVICE" | false + // "process_arguments" | null | "equals" | "-DCustomKey" | true } def "test duplicate entries"() { From 4ab687fa00f2c55e72c921101b890f90a6097ade Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Mon, 24 Mar 2025 15:21:21 -0400 Subject: [PATCH 74/98] nits/cleanup --- .../java/datadog.yaml/ConfigurationMap.java | 1 - .../yaml/src/main/java/datadog.yaml/Rule.java | 1 - .../agent/tooling/config/ConfigStore.java | 4 ++ .../config/provider/StableConfigParser.java | 39 ++++++------------- .../config/provider/StableConfigSource.java | 3 +- .../stableconfigyaml/ConfigurationMap.java | 1 - .../provider/stableconfigyaml/Rule.java | 1 - 7 files changed, 16 insertions(+), 34 deletions(-) create mode 100644 dd-trace-java/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/config/ConfigStore.java diff --git a/components/yaml/src/main/java/datadog.yaml/ConfigurationMap.java b/components/yaml/src/main/java/datadog.yaml/ConfigurationMap.java index c7b75bd6e25..af522cc1c2e 100644 --- a/components/yaml/src/main/java/datadog.yaml/ConfigurationMap.java +++ b/components/yaml/src/main/java/datadog.yaml/ConfigurationMap.java @@ -3,7 +3,6 @@ import java.util.HashMap; import java.util.Map; -// TODO: Update this comment from "stable configuration" to whatever product decides on for the name // ConfigurationMap represents configuration key-values found in stable configuration files public class ConfigurationMap extends HashMap { public ConfigurationMap() { diff --git a/components/yaml/src/main/java/datadog.yaml/Rule.java b/components/yaml/src/main/java/datadog.yaml/Rule.java index d6be3b646f1..c79f27b4b5d 100644 --- a/components/yaml/src/main/java/datadog.yaml/Rule.java +++ b/components/yaml/src/main/java/datadog.yaml/Rule.java @@ -3,7 +3,6 @@ import java.util.ArrayList; import java.util.List; -// TODO: Update this comment from "stable configuration" to whatever product decides on for the name // Rule represents a set of selectors and their corresponding configurations found in stable // configuration files public class Rule { diff --git a/dd-trace-java/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/config/ConfigStore.java b/dd-trace-java/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/config/ConfigStore.java new file mode 100644 index 00000000000..1f6895cb0c0 --- /dev/null +++ b/dd-trace-java/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/config/ConfigStore.java @@ -0,0 +1,4 @@ +public String get(String key) { + Object value = this.apmConfiguration.get(key); + return String.valueOf(value); +} \ No newline at end of file diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java index 17b41e1eb68..755fa65acb4 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java @@ -41,8 +41,10 @@ public static StableConfigSource.StableConfig parse(String filePath) throws IOEx if (!rules.isEmpty()) { for (Rule rule : rules) { + // Use the first matching rule if (doesRuleMatch(rule)) { - // Merge configs found in apm_configuration_default and apm_configuration_rules + // Merge configs found in apm_configuration_rules with those found in + // apm_configuration_default configMap.putAll(rule.getConfiguration()); return createStableConfig(configId, configMap); } @@ -53,14 +55,12 @@ public static StableConfigSource.StableConfig parse(String filePath) throws IOEx return createStableConfig(configId, configMap); } - // If there's a configId but no configMap, return an empty map + // If there's a configId but no configMap, use configId but return an empty map if (configId != null) { return new StableConfigSource.StableConfig(configId, Collections.emptyMap()); } } catch (IOException e) { - // TODO: Update this log from "stable configuration" to the official name of the feature, once - // determined log.debug( "Stable configuration file either not found or not readable at filepath {}", filePath); } @@ -89,6 +89,7 @@ private static StableConfigSource.StableConfig createStableConfig( private static boolean validOperatorForLanguageOrigin(String operator) { operator = operator.toLowerCase(); + // "exists" is not valid switch (operator) { case "equals": case "starts_with": @@ -100,7 +101,7 @@ private static boolean validOperatorForLanguageOrigin(String operator) { } } - private static boolean checkMatches( + private static boolean checkEnvMatches( List values, List matches, BiPredicate compareFunc) { // envValue shouldn't be null, but doing an extra check to avoid NullPointerException on // compareFunc.test @@ -150,14 +151,15 @@ public static boolean selectorMatch( // We don't care about the value return true; case "equals": - return checkMatches( + return checkEnvMatches( Collections.singletonList(envValue), matches, String::equalsIgnoreCase); case "starts_with": - return checkMatches(Collections.singletonList(envValue), matches, String::startsWith); + return checkEnvMatches( + Collections.singletonList(envValue), matches, String::startsWith); case "ends_with": - return checkMatches(Collections.singletonList(envValue), matches, String::endsWith); + return checkEnvMatches(Collections.singletonList(envValue), matches, String::endsWith); case "contains": - return checkMatches(Collections.singletonList(envValue), matches, String::contains); + return checkEnvMatches(Collections.singletonList(envValue), matches, String::contains); default: return false; } @@ -165,25 +167,6 @@ public static boolean selectorMatch( // For now, always return true if `key` exists in the JVM Args // TODO: flesh out the meaning of each operator for process_arguments return CLIHelper.ARGS.contains(key); - // List vals = CLIHelper.ARGS.getValues(key); - // if (vals == null || vals.isEmpty()) { - // return false; - // } - // switch (operator.toLowerCase()) { - // case "exists": - // // We don't care about the value - // return true; - // case "equals": - // return checkMatches(vals, matches, String::equalsIgnoreCase); - // case "starts_with": - // return checkMatches(vals, matches, String::startsWith); - // case "ends_with": - // return checkMatches(vals, matches, String::endsWith); - // case "contains": - // return checkMatches(vals, matches, String::contains); - // default: - // return false; - // } case "tags": // TODO: Support this down the line (Must define the source of "tags" first) return false; diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java index 313d2bfc29a..49531fd6806 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java @@ -81,8 +81,7 @@ public StableConfig(String configId, Map configMap) { public String get(String key) { Object value = this.apmConfiguration.get(key); - // TODO: Handle this more safely, e.g. for an array - return (value == null) ? null : value.toString(); + return (value == null) ? null : String.valueOf(value); } public Set getKeys() { diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/ConfigurationMap.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/ConfigurationMap.java index d6b6911a1fe..27fa866fe05 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/ConfigurationMap.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/ConfigurationMap.java @@ -3,7 +3,6 @@ import java.util.HashMap; import java.util.Map; -// TODO: Update this comment from "stable configuration" to whatever product decides on for the name // ConfigurationMap represents configuration key-values found in stable configuration files public class ConfigurationMap extends HashMap { public ConfigurationMap() { diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/Rule.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/Rule.java index 105e9919c97..dbcca5792e3 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/Rule.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/Rule.java @@ -3,7 +3,6 @@ import java.util.ArrayList; import java.util.List; -// TODO: Update this comment from "stable configuration" to whatever product decides on for the name // Rule represents a set of selectors and their corresponding configurations found in stable // configuration files public class Rule { From 253e5e4aff84aa6a71387a78da6c8ef3816236bd Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Tue, 25 Mar 2025 12:35:53 +0000 Subject: [PATCH 75/98] Fix package directory --- .../cli/src/main/java/{datadog.cli => datadog/cli}/CLIHelper.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename components/cli/src/main/java/{datadog.cli => datadog/cli}/CLIHelper.java (100%) diff --git a/components/cli/src/main/java/datadog.cli/CLIHelper.java b/components/cli/src/main/java/datadog/cli/CLIHelper.java similarity index 100% rename from components/cli/src/main/java/datadog.cli/CLIHelper.java rename to components/cli/src/main/java/datadog/cli/CLIHelper.java From e67ae7a5bc5ac7392a8d3185f79cc5838c8618b4 Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Tue, 25 Mar 2025 13:23:11 +0000 Subject: [PATCH 76/98] Cleanup code: * store args in static field, make available via static getter * use list of strings as storage type to begin with * prefer NIO methods to read content (defaults to UTF8) * use try-with-resources to ensure reader is closed * check file exists as a quick short-circuit --- .../src/main/java/datadog/cli/CLIHelper.java | 58 ++++++++----------- .../trace/bootstrap/AgentBootstrap.java | 2 +- 2 files changed, 24 insertions(+), 36 deletions(-) diff --git a/components/cli/src/main/java/datadog/cli/CLIHelper.java b/components/cli/src/main/java/datadog/cli/CLIHelper.java index 4fdfcc92e7d..9dafb3089c4 100644 --- a/components/cli/src/main/java/datadog/cli/CLIHelper.java +++ b/components/cli/src/main/java/datadog/cli/CLIHelper.java @@ -2,44 +2,39 @@ import de.thetaphi.forbiddenapis.SuppressForbidden; import java.io.BufferedReader; -import java.io.FileReader; -import java.io.IOException; import java.lang.management.ManagementFactory; import java.lang.reflect.Field; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.Collections; -import java.util.HashSet; import java.util.List; +import java.util.Locale; -public class CLIHelper { - public static final CLIHelper ARGS = new CLIHelper(initJvmArgs()); +public final class CLIHelper { + private static final List VM_ARGS = findVmArgs(); - private final HashSet args; - - public CLIHelper(List args) { - this.args = new HashSet<>(args); - } - - public HashSet getJvmArgs() { - return this.args; - } - - public boolean contains(String argument) { - return this.args.contains(argument); + public static List getVmArgs() { + return VM_ARGS; } @SuppressForbidden - private static List initJvmArgs() { - // If linux OS, use procfs - // TODO: equals, or contains? - if (System.getProperty("os.name").equalsIgnoreCase("linux")) { - try { - // Get the JVM arguments from /proc/self/cmdline - return getJvmArgsFromProcCmdline(); - } catch (IOException e) { - // ignore exception, try other methods + private static List findVmArgs() { + // Try ProcFS on Linux + try { + if (isLinux()) { + Path cmdlinePath = Paths.get("/proc/self/cmdline"); + if (Files.exists(cmdlinePath)) { + try (BufferedReader in = Files.newBufferedReader(cmdlinePath)) { + return Arrays.asList(in.readLine().split("\0")); + } + } } + } catch (Throwable ignored) { + // Ignored exception } + // Try Oracle-based // IBM Semeru Runtime 1.8.0_345-b01 will throw UnsatisfiedLinkError here. try { @@ -89,14 +84,7 @@ private static List initJvmArgs() { return Collections.emptyList(); } - private static List getJvmArgsFromProcCmdline() throws IOException { - BufferedReader argsReader = new BufferedReader(new FileReader("/proc/self/cmdline")); - String cmdLine = argsReader.readLine(); - if (cmdLine != null) { - // Return JVM arguments as a list of strings split by null characters - return Arrays.asList(cmdLine.split("\0")); - } else { - return null; - } + private static boolean isLinux() { + return System.getProperty("os.name").toLowerCase(Locale.ROOT).contains("linux"); } } 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 d715c1f3277..f70038f26ba 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 @@ -381,7 +381,7 @@ private static List getAgentFilesFromVMArguments() { // - On IBM-based JDKs since at least 1.7 // This prevents custom log managers from working correctly // Use reflection to bypass the loading of the class~ - for (final String argument : CLIHelper.ARGS.getJvmArgs()) { + for (final String argument : CLIHelper.getVmArgs()) { if (argument.startsWith(JAVA_AGENT_ARGUMENT)) { int index = argument.indexOf('=', JAVA_AGENT_ARGUMENT.length()); String agentPathname = From b8446073e89813d05bee7db20c055212819ecfc1 Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Tue, 25 Mar 2025 13:29:59 +0000 Subject: [PATCH 77/98] Remove warning when reflection fails --- components/cli/src/main/java/datadog/cli/CLIHelper.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/components/cli/src/main/java/datadog/cli/CLIHelper.java b/components/cli/src/main/java/datadog/cli/CLIHelper.java index 9dafb3089c4..0f37953a92f 100644 --- a/components/cli/src/main/java/datadog/cli/CLIHelper.java +++ b/components/cli/src/main/java/datadog/cli/CLIHelper.java @@ -73,8 +73,6 @@ private static List findVmArgs() { // Fallback to default try { - System.err.println( - "WARNING: Unable to get VM args through reflection. A custom java.util.logging.LogManager may not work correctly"); return ManagementFactory.getRuntimeMXBean().getInputArguments(); } catch (final Throwable t) { // Throws InvocationTargetException on modularized applications From 8837a21358853134281d98d81072842feedbd89c Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Tue, 25 Mar 2025 13:54:27 +0000 Subject: [PATCH 78/98] Expose components:cli from internal-api --- .../src/main/java/datadog/trace/bootstrap/Constants.java | 1 + .../src/main/groovy/datadog/trace/agent/test/SpockRunner.java | 1 + gradle/dependencies.gradle | 1 + internal-api/build.gradle | 1 + 4 files changed, 4 insertions(+) diff --git a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/Constants.java b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/Constants.java index c017f331181..0ed02193072 100644 --- a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/Constants.java +++ b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/Constants.java @@ -17,6 +17,7 @@ public final class Constants { "datadog.slf4j", "datadog.json", "datadog.context", + "datadog.cli", "datadog.appsec.api", "datadog.trace.api", "datadog.trace.bootstrap", diff --git a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/SpockRunner.java b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/SpockRunner.java index 684b5c4b11a..eda9e4d86d4 100644 --- a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/SpockRunner.java +++ b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/SpockRunner.java @@ -40,6 +40,7 @@ public class SpockRunner extends JUnitPlatform { "datadog.slf4j", "datadog.json", "datadog.context", + "datadog.cli", "datadog.appsec.api", "datadog.trace.api", "datadog.trace.bootstrap", diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index 2fd95f2c4af..76e8061f5d8 100644 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -18,6 +18,7 @@ final class CachedData { exclude(project(':communication')) exclude(project(':components:context')) exclude(project(':components:json')) + exclude(project(':components:cli')) exclude(project(':remote-config:remote-config-api')) exclude(project(':remote-config:remote-config-core')) exclude(project(':telemetry')) diff --git a/internal-api/build.gradle b/internal-api/build.gradle index 947fe5d0ea8..9d0107ae991 100644 --- a/internal-api/build.gradle +++ b/internal-api/build.gradle @@ -234,6 +234,7 @@ dependencies { api project(':dd-trace-api') api libs.slf4j api project(':components:context') + api project(':components:cli') api project(":utils:time-utils") // has to be loaded by system classloader: From 2a2012c553f5132974eadf4e715ceb91a08e608f Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Tue, 25 Mar 2025 14:05:50 +0000 Subject: [PATCH 79/98] Fix package directory --- .../java/{datadog.yaml => datadog/yaml}/ConfigurationMap.java | 0 .../yaml/src/main/java/{datadog.yaml => datadog/yaml}/Rule.java | 0 .../src/main/java/{datadog.yaml => datadog/yaml}/Selector.java | 0 .../java/{datadog.yaml => datadog/yaml}/StableConfigYaml.java | 0 .../src/main/java/{datadog.yaml => datadog/yaml}/YamlParser.java | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename components/yaml/src/main/java/{datadog.yaml => datadog/yaml}/ConfigurationMap.java (100%) rename components/yaml/src/main/java/{datadog.yaml => datadog/yaml}/Rule.java (100%) rename components/yaml/src/main/java/{datadog.yaml => datadog/yaml}/Selector.java (100%) rename components/yaml/src/main/java/{datadog.yaml => datadog/yaml}/StableConfigYaml.java (100%) rename components/yaml/src/main/java/{datadog.yaml => datadog/yaml}/YamlParser.java (100%) diff --git a/components/yaml/src/main/java/datadog.yaml/ConfigurationMap.java b/components/yaml/src/main/java/datadog/yaml/ConfigurationMap.java similarity index 100% rename from components/yaml/src/main/java/datadog.yaml/ConfigurationMap.java rename to components/yaml/src/main/java/datadog/yaml/ConfigurationMap.java diff --git a/components/yaml/src/main/java/datadog.yaml/Rule.java b/components/yaml/src/main/java/datadog/yaml/Rule.java similarity index 100% rename from components/yaml/src/main/java/datadog.yaml/Rule.java rename to components/yaml/src/main/java/datadog/yaml/Rule.java diff --git a/components/yaml/src/main/java/datadog.yaml/Selector.java b/components/yaml/src/main/java/datadog/yaml/Selector.java similarity index 100% rename from components/yaml/src/main/java/datadog.yaml/Selector.java rename to components/yaml/src/main/java/datadog/yaml/Selector.java diff --git a/components/yaml/src/main/java/datadog.yaml/StableConfigYaml.java b/components/yaml/src/main/java/datadog/yaml/StableConfigYaml.java similarity index 100% rename from components/yaml/src/main/java/datadog.yaml/StableConfigYaml.java rename to components/yaml/src/main/java/datadog/yaml/StableConfigYaml.java diff --git a/components/yaml/src/main/java/datadog.yaml/YamlParser.java b/components/yaml/src/main/java/datadog/yaml/YamlParser.java similarity index 100% rename from components/yaml/src/main/java/datadog.yaml/YamlParser.java rename to components/yaml/src/main/java/datadog/yaml/YamlParser.java From f00b0f46347950856c26fab693707ddadab94348 Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Tue, 25 Mar 2025 14:07:54 +0000 Subject: [PATCH 80/98] Expose components:yaml from internal-api --- .../src/main/java/datadog/trace/bootstrap/Constants.java | 1 + .../src/main/groovy/datadog/trace/agent/test/SpockRunner.java | 1 + 2 files changed, 2 insertions(+) diff --git a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/Constants.java b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/Constants.java index 0ed02193072..d6ddee8410d 100644 --- a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/Constants.java +++ b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/Constants.java @@ -16,6 +16,7 @@ public final class Constants { public static final String[] BOOTSTRAP_PACKAGE_PREFIXES = { "datadog.slf4j", "datadog.json", + "datadog.yaml", "datadog.context", "datadog.cli", "datadog.appsec.api", diff --git a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/SpockRunner.java b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/SpockRunner.java index eda9e4d86d4..83bf7732644 100644 --- a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/SpockRunner.java +++ b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/SpockRunner.java @@ -39,6 +39,7 @@ public class SpockRunner extends JUnitPlatform { public static final String[] BOOTSTRAP_PACKAGE_PREFIXES_COPY = { "datadog.slf4j", "datadog.json", + "datadog.yaml", "datadog.context", "datadog.cli", "datadog.appsec.api", From e3ad9959316941047c5b141275760660a184fdd5 Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Tue, 25 Mar 2025 14:15:03 +0000 Subject: [PATCH 81/98] Domain classes should not exist in component module --- .../java/datadog/yaml/ConfigurationMap.java | 28 --------- .../yaml/src/main/java/datadog/yaml/Rule.java | 38 ------------ .../src/main/java/datadog/yaml/Selector.java | 58 ------------------- .../java/datadog/yaml/StableConfigYaml.java | 41 ------------- 4 files changed, 165 deletions(-) delete mode 100644 components/yaml/src/main/java/datadog/yaml/ConfigurationMap.java delete mode 100644 components/yaml/src/main/java/datadog/yaml/Rule.java delete mode 100644 components/yaml/src/main/java/datadog/yaml/Selector.java delete mode 100644 components/yaml/src/main/java/datadog/yaml/StableConfigYaml.java diff --git a/components/yaml/src/main/java/datadog/yaml/ConfigurationMap.java b/components/yaml/src/main/java/datadog/yaml/ConfigurationMap.java deleted file mode 100644 index af522cc1c2e..00000000000 --- a/components/yaml/src/main/java/datadog/yaml/ConfigurationMap.java +++ /dev/null @@ -1,28 +0,0 @@ -package datadog.yaml; - -import java.util.HashMap; -import java.util.Map; - -// ConfigurationMap represents configuration key-values found in stable configuration files -public class ConfigurationMap extends HashMap { - public ConfigurationMap() { - return; - } - - public ConfigurationMap(Map map) { - super(map); - } -} - -class ConfigurationValue { - private final String value; - - public ConfigurationValue(String value) { - this.value = value; - } - - @Override - public String toString() { - return value; - } -} diff --git a/components/yaml/src/main/java/datadog/yaml/Rule.java b/components/yaml/src/main/java/datadog/yaml/Rule.java deleted file mode 100644 index c79f27b4b5d..00000000000 --- a/components/yaml/src/main/java/datadog/yaml/Rule.java +++ /dev/null @@ -1,38 +0,0 @@ -package datadog.yaml; - -import java.util.ArrayList; -import java.util.List; - -// Rule represents a set of selectors and their corresponding configurations found in stable -// configuration files -public class Rule { - private List selectors; - private ConfigurationMap configuration; - - public Rule() { - this.selectors = new ArrayList<>(); - this.configuration = new ConfigurationMap(); - } - - public Rule(List selectors, ConfigurationMap configuration) { - this.selectors = selectors; - this.configuration = configuration; - } - - // Getters and setters - public List getSelectors() { - return selectors; - } - - public void setSelectors(List selectors) { - this.selectors = selectors; - } - - public ConfigurationMap getConfiguration() { - return configuration; - } - - public void setConfiguration(ConfigurationMap configuration) { - this.configuration = configuration; - } -} diff --git a/components/yaml/src/main/java/datadog/yaml/Selector.java b/components/yaml/src/main/java/datadog/yaml/Selector.java deleted file mode 100644 index 2fb694a5a54..00000000000 --- a/components/yaml/src/main/java/datadog/yaml/Selector.java +++ /dev/null @@ -1,58 +0,0 @@ -package datadog.yaml; - -import java.util.ArrayList; -import java.util.List; - -public class Selector { - private String origin; - private String key; - private List matches; - private String operator; - - public Selector() { - this.origin = null; - this.key = null; - this.matches = new ArrayList<>(); - this.operator = null; - } - - public Selector(String origin, String key, List matches, String operator) { - this.origin = origin; - this.key = key; - this.matches = matches; - this.operator = operator; - } - - // Getters and setters - public String getOrigin() { - return origin; - } - - public void setOrigin(String origin) { - this.origin = origin; - } - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - public List getMatches() { - return matches; - } - - public void setMatches(List matches) { - this.matches = matches; - } - - public String getOperator() { - return operator; - } - - public void setOperator(String operator) { - this.operator = operator; - } -} diff --git a/components/yaml/src/main/java/datadog/yaml/StableConfigYaml.java b/components/yaml/src/main/java/datadog/yaml/StableConfigYaml.java deleted file mode 100644 index ccf7615c60a..00000000000 --- a/components/yaml/src/main/java/datadog/yaml/StableConfigYaml.java +++ /dev/null @@ -1,41 +0,0 @@ -package datadog.yaml; - -import java.util.ArrayList; -import java.util.List; - -public class StableConfigYaml { - private String config_id; // optional - private ConfigurationMap apm_configuration_default; - private List apm_configuration_rules; // optional - - public StableConfigYaml() { - this.config_id = null; - this.apm_configuration_default = new ConfigurationMap(); - this.apm_configuration_rules = new ArrayList<>(); - } - - // Getters and setters - public String getConfig_id() { - return config_id; - } - - public void setConfig_id(String config_id) { - this.config_id = config_id; - } - - public ConfigurationMap getApm_configuration_default() { - return apm_configuration_default; - } - - public void setApm_configuration_default(ConfigurationMap apm_configuration_default) { - this.apm_configuration_default = apm_configuration_default; - } - - public List getApm_configuration_rules() { - return apm_configuration_rules; - } - - public void setApm_configuration_rules(List apm_configuration_rules) { - this.apm_configuration_rules = apm_configuration_rules; - } -} From 8324c3a6ca4d4b897baecbb2e3011e1ac3e0b66b Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Tue, 25 Mar 2025 14:16:59 +0000 Subject: [PATCH 82/98] Cleanup relocation --- dd-java-agent/build.gradle | 2 -- 1 file changed, 2 deletions(-) diff --git a/dd-java-agent/build.gradle b/dd-java-agent/build.gradle index f2db3451b5d..d03ea2e440e 100644 --- a/dd-java-agent/build.gradle +++ b/dd-java-agent/build.gradle @@ -64,8 +64,6 @@ ext.generalShadowJarConfig = { relocate 'org.yaml.snakeyaml', 'datadog.snakeyaml' relocate 'okhttp3', 'datadog.okhttp3' relocate 'okio', 'datadog.okio' - // Include the YAML config classes in bootstrap - relocate 'datadog.trace.bootstrap.config.provider.StableConfigYaml', 'datadog.trace.bootstrap.config.provider.stableconfigyaml' } if (!project.hasProperty("disableShadowRelocate") || !disableShadowRelocate) { From 83b2f7e361b02ee694f78c387772e466c47480f9 Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Tue, 25 Mar 2025 14:21:18 +0000 Subject: [PATCH 83/98] Fix --- .../trace/bootstrap/config/provider/StableConfigParser.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java index 755fa65acb4..e92f764ec34 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java @@ -9,7 +9,9 @@ import java.io.IOException; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.function.BiPredicate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -17,6 +19,8 @@ public class StableConfigParser { private static final Logger log = LoggerFactory.getLogger(StableConfigParser.class); + private static final Set VM_ARGS = new HashSet<>(CLIHelper.getVmArgs()); + /** * Parses a configuration file and returns a stable configuration object. * @@ -166,7 +170,7 @@ public static boolean selectorMatch( case "process_arguments": // For now, always return true if `key` exists in the JVM Args // TODO: flesh out the meaning of each operator for process_arguments - return CLIHelper.ARGS.contains(key); + return VM_ARGS.contains(key); case "tags": // TODO: Support this down the line (Must define the source of "tags" first) return false; From b0f4c5539ce6bd9c0d666cf2ef797f1bbaca45e4 Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Tue, 25 Mar 2025 14:45:07 +0000 Subject: [PATCH 84/98] Cleanup --- .../java/datadog/trace/agent/tooling/config/ConfigStore.java | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 dd-trace-java/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/config/ConfigStore.java diff --git a/dd-trace-java/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/config/ConfigStore.java b/dd-trace-java/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/config/ConfigStore.java deleted file mode 100644 index 1f6895cb0c0..00000000000 --- a/dd-trace-java/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/config/ConfigStore.java +++ /dev/null @@ -1,4 +0,0 @@ -public String get(String key) { - Object value = this.apmConfiguration.get(key); - return String.valueOf(value); -} \ No newline at end of file From f085bafeed11a985ce1f8a3f4218772768292454 Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Wed, 26 Mar 2025 12:30:01 -0400 Subject: [PATCH 85/98] Remove unused ConfigurationValue.toString; hopefully pass Jacoco test coverage tests --- .../config/provider/stableconfigyaml/ConfigurationMap.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/ConfigurationMap.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/ConfigurationMap.java index 27fa866fe05..f50d8dd7495 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/ConfigurationMap.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/ConfigurationMap.java @@ -20,9 +20,4 @@ class ConfigurationValue { public ConfigurationValue(String value) { this.value = value; } - - @Override - public String toString() { - return value; - } } From 3b861435414b0bdba88cd4f246d71d3c7d7ce89a Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Thu, 27 Mar 2025 09:25:50 -0400 Subject: [PATCH 86/98] reset to f085bafeed --- dd-smoke-tests/spring-boot-2.6-webmvc/build.gradle | 5 +++++ dd-smoke-tests/springboot-java-11/build.gradle | 5 +++++ dd-smoke-tests/springboot-java-17/build.gradle | 5 +++++ dd-smoke-tests/springboot/build.gradle | 5 +++++ .../config/provider/stableconfigyaml/ConfigurationMap.java | 5 +++++ 5 files changed, 25 insertions(+) diff --git a/dd-smoke-tests/spring-boot-2.6-webmvc/build.gradle b/dd-smoke-tests/spring-boot-2.6-webmvc/build.gradle index a9970816ed6..69466c43eab 100644 --- a/dd-smoke-tests/spring-boot-2.6-webmvc/build.gradle +++ b/dd-smoke-tests/spring-boot-2.6-webmvc/build.gradle @@ -48,6 +48,11 @@ dependencies { testImplementation project(':dd-smoke-tests') implementation project(':dd-smoke-tests:iast-util') testImplementation(testFixtures(project(":dd-smoke-tests:iast-util"))) + testImplementation('org.yaml:snakeyaml') { + version { + strictly '1.33' + } + } implementation 'jakarta.mail:jakarta.mail-api:2.0.1' implementation 'com.sun.mail:jakarta.mail:2.0.1' diff --git a/dd-smoke-tests/springboot-java-11/build.gradle b/dd-smoke-tests/springboot-java-11/build.gradle index 031e6615c5c..506246242b8 100644 --- a/dd-smoke-tests/springboot-java-11/build.gradle +++ b/dd-smoke-tests/springboot-java-11/build.gradle @@ -22,6 +22,11 @@ dependencies { testImplementation project(':dd-smoke-tests') testImplementation testFixtures(project(":dd-smoke-tests:iast-util:iast-util-11")) testImplementation testFixtures(project(':dd-smoke-tests:iast-util')) + testImplementation('org.yaml:snakeyaml') { + version { + strictly '1.33' + } + } implementation project(':dd-smoke-tests:iast-util:iast-util-11') } diff --git a/dd-smoke-tests/springboot-java-17/build.gradle b/dd-smoke-tests/springboot-java-17/build.gradle index c6d99c2de64..9f56ea87acc 100644 --- a/dd-smoke-tests/springboot-java-17/build.gradle +++ b/dd-smoke-tests/springboot-java-17/build.gradle @@ -22,6 +22,11 @@ dependencies { testImplementation project(':dd-smoke-tests') testImplementation testFixtures(project(":dd-smoke-tests:iast-util:iast-util-17")) testImplementation testFixtures(project(':dd-smoke-tests:iast-util')) + testImplementation('org.yaml:snakeyaml') { + version { + strictly '1.33' + } + } implementation project(':dd-smoke-tests:iast-util:iast-util-17') } diff --git a/dd-smoke-tests/springboot/build.gradle b/dd-smoke-tests/springboot/build.gradle index 3e0161aa2cb..1c83919d02b 100644 --- a/dd-smoke-tests/springboot/build.gradle +++ b/dd-smoke-tests/springboot/build.gradle @@ -38,6 +38,11 @@ dependencies { testImplementation project(':dd-smoke-tests') testImplementation(testFixtures(project(":dd-smoke-tests:iast-util"))) + testImplementation('org.yaml:snakeyaml') { + version { + strictly '1.33' + } + } implementation project(':dd-smoke-tests:iast-util') implementation 'jakarta.mail:jakarta.mail-api:2.0.1' diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/ConfigurationMap.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/ConfigurationMap.java index f50d8dd7495..27fa866fe05 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/ConfigurationMap.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/ConfigurationMap.java @@ -20,4 +20,9 @@ class ConfigurationValue { public ConfigurationValue(String value) { this.value = value; } + + @Override + public String toString() { + return value; + } } From 1a48f84605c55cd169faa83de5dd539391b75fed Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Thu, 27 Mar 2025 09:30:27 -0400 Subject: [PATCH 87/98] manually remove testImplementation snakeyaml 1.33 changes in dd-smoke-tests --- dd-smoke-tests/spring-boot-2.6-webmvc/build.gradle | 5 ----- dd-smoke-tests/springboot-java-11/build.gradle | 5 ----- dd-smoke-tests/springboot-java-17/build.gradle | 5 ----- dd-smoke-tests/springboot/build.gradle | 5 ----- 4 files changed, 20 deletions(-) diff --git a/dd-smoke-tests/spring-boot-2.6-webmvc/build.gradle b/dd-smoke-tests/spring-boot-2.6-webmvc/build.gradle index 69466c43eab..a9970816ed6 100644 --- a/dd-smoke-tests/spring-boot-2.6-webmvc/build.gradle +++ b/dd-smoke-tests/spring-boot-2.6-webmvc/build.gradle @@ -48,11 +48,6 @@ dependencies { testImplementation project(':dd-smoke-tests') implementation project(':dd-smoke-tests:iast-util') testImplementation(testFixtures(project(":dd-smoke-tests:iast-util"))) - testImplementation('org.yaml:snakeyaml') { - version { - strictly '1.33' - } - } implementation 'jakarta.mail:jakarta.mail-api:2.0.1' implementation 'com.sun.mail:jakarta.mail:2.0.1' diff --git a/dd-smoke-tests/springboot-java-11/build.gradle b/dd-smoke-tests/springboot-java-11/build.gradle index 506246242b8..031e6615c5c 100644 --- a/dd-smoke-tests/springboot-java-11/build.gradle +++ b/dd-smoke-tests/springboot-java-11/build.gradle @@ -22,11 +22,6 @@ dependencies { testImplementation project(':dd-smoke-tests') testImplementation testFixtures(project(":dd-smoke-tests:iast-util:iast-util-11")) testImplementation testFixtures(project(':dd-smoke-tests:iast-util')) - testImplementation('org.yaml:snakeyaml') { - version { - strictly '1.33' - } - } implementation project(':dd-smoke-tests:iast-util:iast-util-11') } diff --git a/dd-smoke-tests/springboot-java-17/build.gradle b/dd-smoke-tests/springboot-java-17/build.gradle index 9f56ea87acc..c6d99c2de64 100644 --- a/dd-smoke-tests/springboot-java-17/build.gradle +++ b/dd-smoke-tests/springboot-java-17/build.gradle @@ -22,11 +22,6 @@ dependencies { testImplementation project(':dd-smoke-tests') testImplementation testFixtures(project(":dd-smoke-tests:iast-util:iast-util-17")) testImplementation testFixtures(project(':dd-smoke-tests:iast-util')) - testImplementation('org.yaml:snakeyaml') { - version { - strictly '1.33' - } - } implementation project(':dd-smoke-tests:iast-util:iast-util-17') } diff --git a/dd-smoke-tests/springboot/build.gradle b/dd-smoke-tests/springboot/build.gradle index 1c83919d02b..3e0161aa2cb 100644 --- a/dd-smoke-tests/springboot/build.gradle +++ b/dd-smoke-tests/springboot/build.gradle @@ -38,11 +38,6 @@ dependencies { testImplementation project(':dd-smoke-tests') testImplementation(testFixtures(project(":dd-smoke-tests:iast-util"))) - testImplementation('org.yaml:snakeyaml') { - version { - strictly '1.33' - } - } implementation project(':dd-smoke-tests:iast-util') implementation 'jakarta.mail:jakarta.mail-api:2.0.1' From a99d01630267287ca44a8ea047bbbb226e833c80 Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Thu, 27 Mar 2025 13:54:19 -0400 Subject: [PATCH 88/98] exclude org.yaml.snakeyaml dependency from dd-smoke-tests --- dd-smoke-tests/build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dd-smoke-tests/build.gradle b/dd-smoke-tests/build.gradle index b53825da025..29f0568e4a1 100644 --- a/dd-smoke-tests/build.gradle +++ b/dd-smoke-tests/build.gradle @@ -2,6 +2,10 @@ apply from: "$rootDir/gradle/java.gradle" description = 'dd-smoke-tests' +configurations.all { + exclude group: 'org.yaml', module: 'snakeyaml' +} + dependencies { api libs.bundles.spock api libs.okhttp From 1a8cee40408cafbe13145ac4a833a4d14f3d4a51 Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Fri, 28 Mar 2025 11:09:59 -0400 Subject: [PATCH 89/98] Remove unused ConfigurationValue.toString (again..) --- .../config/provider/stableconfigyaml/ConfigurationMap.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/ConfigurationMap.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/ConfigurationMap.java index 27fa866fe05..f50d8dd7495 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/ConfigurationMap.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/ConfigurationMap.java @@ -20,9 +20,4 @@ class ConfigurationValue { public ConfigurationValue(String value) { this.value = value; } - - @Override - public String toString() { - return value; - } } From 679c4ca9fa43a629ffb237d13c9e714dcee9285f Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Sat, 29 Mar 2025 00:03:34 +0000 Subject: [PATCH 90/98] Attempt to fix muzzle --- dd-java-agent/instrumentation/snakeyaml/build.gradle | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/dd-java-agent/instrumentation/snakeyaml/build.gradle b/dd-java-agent/instrumentation/snakeyaml/build.gradle index 8894e9b8ed2..33a281221a9 100644 --- a/dd-java-agent/instrumentation/snakeyaml/build.gradle +++ b/dd-java-agent/instrumentation/snakeyaml/build.gradle @@ -16,17 +16,17 @@ muzzle { apply from: "$rootDir/gradle/java.gradle" addTestSuiteForDir('latestDepTest', 'test') +configurations.muzzleBootstrap { + exclude group: 'org.yaml', module : 'snakeyaml' +} + dependencies { compileOnly group: 'org.yaml', name: 'snakeyaml', version: '1.33' testImplementation('org.yaml:snakeyaml') { version { - strictly '1.33' - } - } - muzzleBootstrap('org.yaml:snakeyaml') { - version { - strictly '1.33' + strictly "[1.4, 2.0)" + prefer '1.33' } } From 9e905b5959188b4cdcb06c16c91558cb32aa0d01 Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Sat, 29 Mar 2025 00:57:24 +0000 Subject: [PATCH 91/98] Attempt to fix muzzle --- dd-java-agent/instrumentation/build.gradle | 3 +++ dd-java-agent/instrumentation/snakeyaml/build.gradle | 4 ---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/dd-java-agent/instrumentation/build.gradle b/dd-java-agent/instrumentation/build.gradle index 777de23d76f..2b9e0215945 100644 --- a/dd-java-agent/instrumentation/build.gradle +++ b/dd-java-agent/instrumentation/build.gradle @@ -45,6 +45,9 @@ subprojects { Project subProj -> def name = "java$version.majorVersion" jdkCompile = "main_${name}Implementation" } + configurations.muzzleBootstrap { + exclude group: 'org.yaml', module : 'snakeyaml' + } dependencies { // Apply common dependencies for instrumentation. implementation project(':dd-trace-api') diff --git a/dd-java-agent/instrumentation/snakeyaml/build.gradle b/dd-java-agent/instrumentation/snakeyaml/build.gradle index 33a281221a9..5decb514c66 100644 --- a/dd-java-agent/instrumentation/snakeyaml/build.gradle +++ b/dd-java-agent/instrumentation/snakeyaml/build.gradle @@ -16,10 +16,6 @@ muzzle { apply from: "$rootDir/gradle/java.gradle" addTestSuiteForDir('latestDepTest', 'test') -configurations.muzzleBootstrap { - exclude group: 'org.yaml', module : 'snakeyaml' -} - dependencies { compileOnly group: 'org.yaml', name: 'snakeyaml', version: '1.33' From 29c19258b52ce7635fd2311b2c6b995be8c74f93 Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Sat, 29 Mar 2025 14:07:42 +0000 Subject: [PATCH 92/98] comment --- dd-java-agent/instrumentation/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dd-java-agent/instrumentation/build.gradle b/dd-java-agent/instrumentation/build.gradle index 2b9e0215945..30581097020 100644 --- a/dd-java-agent/instrumentation/build.gradle +++ b/dd-java-agent/instrumentation/build.gradle @@ -46,7 +46,7 @@ subprojects { Project subProj -> jdkCompile = "main_${name}Implementation" } configurations.muzzleBootstrap { - exclude group: 'org.yaml', module : 'snakeyaml' + exclude group: 'org.yaml', module : 'snakeyaml' // we vendor this in the agent jar } dependencies { // Apply common dependencies for instrumentation. From 10a10286dcdc96c34490686fe7f4a05715c7a15c Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Sat, 29 Mar 2025 14:18:54 +0000 Subject: [PATCH 93/98] cleanup --- dd-java-agent/testing/build.gradle | 4 ++++ dd-smoke-tests/build.gradle | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dd-java-agent/testing/build.gradle b/dd-java-agent/testing/build.gradle index f5f1039ebe2..6131b36560c 100644 --- a/dd-java-agent/testing/build.gradle +++ b/dd-java-agent/testing/build.gradle @@ -45,6 +45,10 @@ excludedClassesCoverage += [ 'datadog.trace.agent.test.TestProfilingContextIntegration.TestQueueTiming' ] +configurations.api { + exclude group: 'org.yaml', module: 'snakeyaml' // we vendor this in the agent jar +} + dependencies { api libs.bytebuddy api libs.bytebuddyagent diff --git a/dd-smoke-tests/build.gradle b/dd-smoke-tests/build.gradle index 29f0568e4a1..b53825da025 100644 --- a/dd-smoke-tests/build.gradle +++ b/dd-smoke-tests/build.gradle @@ -2,10 +2,6 @@ apply from: "$rootDir/gradle/java.gradle" description = 'dd-smoke-tests' -configurations.all { - exclude group: 'org.yaml', module: 'snakeyaml' -} - dependencies { api libs.bundles.spock api libs.okhttp From d9b68369d12a46cff376e15c2d20adab4688efa5 Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Sat, 29 Mar 2025 14:31:43 +0000 Subject: [PATCH 94/98] log when we find stable config. rather than when we don't (also reduce parsing log message to warn as application will still function) --- .../trace/bootstrap/config/provider/StableConfigSource.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java index 49531fd6806..423167cbc43 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java @@ -24,22 +24,21 @@ public final class StableConfigSource extends ConfigProvider.Source { StableConfigSource.FLEET_STABLE_CONFIG_PATH, ConfigOrigin.FLEET_STABLE_CONFIG); private final ConfigOrigin fileOrigin; - private final StableConfig config; StableConfigSource(String filePath, ConfigOrigin origin) { this.fileOrigin = origin; File file = new File(filePath); if (!file.exists()) { - log.debug("Stable configuration file not available at specified path: {}", file); this.config = StableConfig.EMPTY; return; } StableConfig cfg; try { + log.debug("Stable configuration file found at path: {}", file); cfg = StableConfigParser.parse(filePath); } catch (Throwable e) { - log.error( + log.warn( "Encountered the following exception when attempting to read stable configuration file at path: {}, dropping configs.\n", file, e); From b8283a981f31435916eda0c36a76fc84156661d8 Mon Sep 17 00:00:00 2001 From: Mikayla Toffler <46911781+mtoffl01@users.noreply.github.com> Date: Wed, 2 Apr 2025 11:46:33 -0400 Subject: [PATCH 95/98] Update internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/ConfigurationMap.java Co-authored-by: Stuart McCulloch --- .../config/provider/stableconfigyaml/ConfigurationMap.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/ConfigurationMap.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/ConfigurationMap.java index f50d8dd7495..20940733fb2 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/ConfigurationMap.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/stableconfigyaml/ConfigurationMap.java @@ -6,7 +6,7 @@ // ConfigurationMap represents configuration key-values found in stable configuration files public class ConfigurationMap extends HashMap { public ConfigurationMap() { - return; + super(); } public ConfigurationMap(Map map) { From dd40811ad094965921d857112385414247af3d3a Mon Sep 17 00:00:00 2001 From: Mikayla Toffler <46911781+mtoffl01@users.noreply.github.com> Date: Wed, 2 Apr 2025 11:46:43 -0400 Subject: [PATCH 96/98] Update internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java Co-authored-by: Stuart McCulloch --- .../trace/bootstrap/config/provider/StableConfigSource.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java index 423167cbc43..ab634b6fc14 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigSource.java @@ -39,7 +39,7 @@ public final class StableConfigSource extends ConfigProvider.Source { cfg = StableConfigParser.parse(filePath); } catch (Throwable e) { log.warn( - "Encountered the following exception when attempting to read stable configuration file at path: {}, dropping configs.\n", + "Encountered the following exception when attempting to read stable configuration file at path: {}, dropping configs.", file, e); cfg = StableConfig.EMPTY; From ccc18c6f2fe6ebd9a2c3e56e8422f03387afe002 Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Wed, 2 Apr 2025 13:01:06 -0400 Subject: [PATCH 97/98] Make selector match package-private --- .../trace/bootstrap/config/provider/StableConfigParser.java | 4 +--- .../bootstrap/config/provider/StableConfigParserTest.groovy | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java index e92f764ec34..0c7554f2e0e 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java @@ -125,11 +125,9 @@ private static boolean checkEnvMatches( return false; } - // TODO: Make this private again after testing? // We do all of the case insensitivity modifications in this function, because each selector will // be viewed just once - public static boolean selectorMatch( - String origin, List matches, String operator, String key) { + static boolean selectorMatch(String origin, List matches, String operator, String key) { switch (origin.toLowerCase()) { case "language": if (!validOperatorForLanguageOrigin(operator)) { diff --git a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy index 4596ea4a516..7ae368aa87f 100644 --- a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy +++ b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy @@ -64,7 +64,6 @@ apm_configuration_rules: Files.delete(filePath) } - // TODO: This test will fail if we make selectorMatch private again def "test selectorMatch"() { when: // Env vars From cffcc17581cf5abf2f4c7d59fc387073dd41f833 Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Thu, 3 Apr 2025 15:03:57 -0400 Subject: [PATCH 98/98] remove comment reminder about process_arguments test --- .../bootstrap/config/provider/StableConfigParserTest.groovy | 1 - 1 file changed, 1 deletion(-) diff --git a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy index 7ae368aa87f..2df560a0eeb 100644 --- a/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy +++ b/internal-api/src/test/groovy/datadog/trace/bootstrap/config/provider/StableConfigParserTest.groovy @@ -70,7 +70,6 @@ apm_configuration_rules: injectEnvConfig("DD_PROFILING_ENABLED", "true") injectEnvConfig("DD_SERVICE", "mysvc") injectEnvConfig("DD_TAGS", "team:apm,component:web") - // injectSysConfig("--DCustomKey", "value") def match = StableConfigParser.selectorMatch(origin, matches, operator, key) then: