From 2df85acac1bfd75e0502d254760479cc89ddc5f7 Mon Sep 17 00:00:00 2001 From: paullegranddc Date: Fri, 18 Jul 2025 17:02:37 +0200 Subject: [PATCH 01/16] feat: match stable config java properties on other operator than 'contains' --- .../config/provider/StableConfigParser.java | 85 ++++++------------- 1 file changed, 28 insertions(+), 57 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 3b43ad47457..975868aac85 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 @@ -104,35 +104,27 @@ private static boolean doesRuleMatch(Rule rule) { return true; // Return true if all selectors match } - private static boolean validOperatorForLanguageOrigin(String operator) { - operator = operator.toLowerCase(); - // "exists" is not valid - switch (operator) { - case "equals": - case "starts_with": - case "ends_with": - case "contains": - return true; - default: - return false; - } - } - - 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 - if (values == null) { + private static boolean matchOperator(String value, String operator, List matches, String match) { + // not sure if these are nullable, but the semantics make sense + // and that will save us from a NPE + if (value == null || matches == null || operator == null) { return false; } + value = value.toLowerCase(); for (String match : matches) { - if (match == null) { - continue; - } - for (String value : values) { - if (compareFunc.test(value, match.toLowerCase())) { + switch (operator) { + case "equals": + return value == match; + case "starts_with": + return value.startsWith(match); + case "ends_with": + return value.endsWith(match); + case "contains": + return value.contains(match); + case "exists": return true; - } + default: + return false; } } return false; @@ -141,44 +133,23 @@ private static boolean checkEnvMatches( // We do all of the case insensitivity modifications in this function, because each selector will // be viewed just once static boolean selectorMatch(String origin, List matches, String operator, String key) { + operator = operator.toLowerCase(); switch (origin.toLowerCase()) { case "language": - if (!validOperatorForLanguageOrigin(operator)) { - return false; - } - for (String entry : matches) { - // loose match on any reference to "*java*" - if (entry.toLowerCase().contains("java")) { - return true; - } - } + return matchOperator("java", operator, matches); case "environment_variables": if (key == null) { - return false; + return false; } - String envValue = System.getenv(key.toUpperCase()); - if (envValue == null) { + String value = System.getenv(key.toUpperCase()); + if (value == null) { return false; } - envValue = envValue.toLowerCase(); - switch (operator.toLowerCase()) { - case "exists": - // We don't care about the value - return true; - case "equals": - return checkEnvMatches( - Collections.singletonList(envValue), matches, String::equalsIgnoreCase); - case "starts_with": - return checkEnvMatches( - Collections.singletonList(envValue), matches, String::startsWith); - case "ends_with": - return checkEnvMatches(Collections.singletonList(envValue), matches, String::endsWith); - case "contains": - return checkEnvMatches(Collections.singletonList(envValue), matches, String::contains); - default: - return false; - } + return matchOperator(value, operator, matches, key); case "process_arguments": + if (key == null) { + return false; + } // TODO: flesh out the meaning of each operator for process_arguments if (!key.startsWith("-D")) { log.warn( @@ -186,8 +157,8 @@ static boolean selectorMatch(String origin, List matches, String operato key); return false; } - // Cut the -D prefix - return System.getProperty(key.substring(2)) != null; + String value = System.getProperty(key.substring(2)); + return matchOperator(value, operator, matches, key); case "tags": // TODO: Support this down the line (Must define the source of "tags" first) return false; From 314525a3edfd1e9cc04a5e4008871ef277a8c24b Mon Sep 17 00:00:00 2001 From: paullegranddc Date: Fri, 18 Jul 2025 17:06:10 +0200 Subject: [PATCH 02/16] fix: lowercase match value --- .../trace/bootstrap/config/provider/StableConfigParser.java | 4 ++++ 1 file changed, 4 insertions(+) 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 975868aac85..155bc7a71de 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 @@ -112,6 +112,10 @@ private static boolean matchOperator(String value, String operator, List } value = value.toLowerCase(); for (String match : matches) { + if (match == null) { + continue; + } + matches = match.toLowerCase(); switch (operator) { case "equals": return value == match; From b051555e62adf53f7058864c0c527848b4ddaf39 Mon Sep 17 00:00:00 2001 From: paullegranddc Date: Fri, 18 Jul 2025 17:14:44 +0200 Subject: [PATCH 03/16] fix: extra parameter --- .../trace/bootstrap/config/provider/StableConfigParser.java | 6 +++--- 1 file changed, 3 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 155bc7a71de..cf5f96d53de 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 @@ -104,7 +104,7 @@ private static boolean doesRuleMatch(Rule rule) { return true; // Return true if all selectors match } - private static boolean matchOperator(String value, String operator, List matches, String match) { + private static boolean matchOperator(String value, String operator, List matches) { // not sure if these are nullable, but the semantics make sense // and that will save us from a NPE if (value == null || matches == null || operator == null) { @@ -149,7 +149,7 @@ static boolean selectorMatch(String origin, List matches, String operato if (value == null) { return false; } - return matchOperator(value, operator, matches, key); + return matchOperator(value, operator, matches); case "process_arguments": if (key == null) { return false; @@ -162,7 +162,7 @@ static boolean selectorMatch(String origin, List matches, String operato return false; } String value = System.getProperty(key.substring(2)); - return matchOperator(value, operator, matches, key); + return matchOperator(value, operator, matches); case "tags": // TODO: Support this down the line (Must define the source of "tags" first) return false; From c0941768e4c5ab1a647c5ca80b0febf7d3f211a3 Mon Sep 17 00:00:00 2001 From: paullegranddc Date: Fri, 18 Jul 2025 17:16:49 +0200 Subject: [PATCH 04/16] fix: remove duplicate values --- .../trace/bootstrap/config/provider/StableConfigParser.java | 2 +- 1 file changed, 1 insertion(+), 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 cf5f96d53de..57c6fc5d0bb 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 @@ -161,7 +161,7 @@ static boolean selectorMatch(String origin, List matches, String operato key); return false; } - String value = System.getProperty(key.substring(2)); + value = System.getProperty(key.substring(2)); return matchOperator(value, operator, matches); case "tags": // TODO: Support this down the line (Must define the source of "tags" first) From a58bd09fb2f8478e1a72cdc17c9993a30b8a7db4 Mon Sep 17 00:00:00 2001 From: paullegranddc Date: Fri, 18 Jul 2025 17:17:13 +0200 Subject: [PATCH 05/16] fix: lint --- .../trace/bootstrap/config/provider/StableConfigParser.java | 2 +- 1 file changed, 1 insertion(+), 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 57c6fc5d0bb..5336e2dfc8a 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 @@ -143,7 +143,7 @@ static boolean selectorMatch(String origin, List matches, String operato return matchOperator("java", operator, matches); case "environment_variables": if (key == null) { - return false; + return false; } String value = System.getenv(key.toUpperCase()); if (value == null) { From db6e5c73a28a0c920f3eec26d2e93a37001961c6 Mon Sep 17 00:00:00 2001 From: paullegranddc Date: Fri, 18 Jul 2025 18:16:43 +0200 Subject: [PATCH 06/16] fi: wrong variable --- .../trace/bootstrap/config/provider/StableConfigParser.java | 2 +- 1 file changed, 1 insertion(+), 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 5336e2dfc8a..79f2601dcca 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 @@ -115,7 +115,7 @@ private static boolean matchOperator(String value, String operator, List if (match == null) { continue; } - matches = match.toLowerCase(); + match = match.toLowerCase(); switch (operator) { case "equals": return value == match; From 5865dc810c4032561334cec5de8d341b755fc43d Mon Sep 17 00:00:00 2001 From: paullegranddc Date: Fri, 18 Jul 2025 19:31:13 +0200 Subject: [PATCH 07/16] fix lint --- .../trace/bootstrap/config/provider/StableConfigParser.java | 3 +-- 1 file changed, 1 insertion(+), 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 79f2601dcca..1586e08b9b3 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 @@ -13,7 +13,6 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.function.BiPredicate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -162,7 +161,7 @@ static boolean selectorMatch(String origin, List matches, String operato return false; } value = System.getProperty(key.substring(2)); - return matchOperator(value, operator, matches); + return matchOperator(value, operator, matches); case "tags": // TODO: Support this down the line (Must define the source of "tags" first) return false; From 2f93fad5eaf4762b6d94df5860c3546d66436b43 Mon Sep 17 00:00:00 2001 From: paullegranddc Date: Fri, 18 Jul 2025 19:39:17 +0200 Subject: [PATCH 08/16] fix: tests --- .../bootstrap/config/provider/StableConfigParser.java | 10 +++++++--- 1 file changed, 7 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 1586e08b9b3..dbc2cf9b784 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 @@ -109,6 +109,9 @@ private static boolean matchOperator(String value, String operator, List if (value == null || matches == null || operator == null) { return false; } + if (operator == "exists") { + return true; + } value = value.toLowerCase(); for (String match : matches) { if (match == null) { @@ -117,15 +120,13 @@ private static boolean matchOperator(String value, String operator, List match = match.toLowerCase(); switch (operator) { case "equals": - return value == match; + return value.equals(match); case "starts_with": return value.startsWith(match); case "ends_with": return value.endsWith(match); case "contains": return value.contains(match); - case "exists": - return true; default: return false; } @@ -139,6 +140,9 @@ static boolean selectorMatch(String origin, List matches, String operato operator = operator.toLowerCase(); switch (origin.toLowerCase()) { case "language": + if (operator == "exists") { + return false; + } return matchOperator("java", operator, matches); case "environment_variables": if (key == null) { From ebf333bc2bd7d780081ab330b82b9a61062cc8a8 Mon Sep 17 00:00:00 2001 From: paullegranddc Date: Fri, 18 Jul 2025 20:02:29 +0200 Subject: [PATCH 09/16] fix: null matches with exist should work --- .../config/provider/StableConfigParser.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 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 dbc2cf9b784..2ed6d6f2eae 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 @@ -106,12 +106,15 @@ private static boolean doesRuleMatch(Rule rule) { private static boolean matchOperator(String value, String operator, List matches) { // not sure if these are nullable, but the semantics make sense // and that will save us from a NPE - if (value == null || matches == null || operator == null) { + if (value == null || operator == null) { return false; } if (operator == "exists") { return true; } + if (matches == null) { + return false; + } value = value.toLowerCase(); for (String match : matches) { if (match == null) { @@ -148,11 +151,11 @@ static boolean selectorMatch(String origin, List matches, String operato if (key == null) { return false; } - String value = System.getenv(key.toUpperCase()); - if (value == null) { + String envValue = System.getenv(key.toUpperCase()); + if (envValue == null) { return false; } - return matchOperator(value, operator, matches); + return matchOperator(envValue, operator, matches); case "process_arguments": if (key == null) { return false; @@ -164,8 +167,8 @@ static boolean selectorMatch(String origin, List matches, String operato key); return false; } - value = System.getProperty(key.substring(2)); - return matchOperator(value, operator, matches); + String argValue = System.getProperty(key.substring(2)); + return matchOperator(argValue, operator, matches); case "tags": // TODO: Support this down the line (Must define the source of "tags" first) return false; From 75f6daeaab4acdc731e18c25fb03cf7cdca990d3 Mon Sep 17 00:00:00 2001 From: paullegranddc Date: Sat, 19 Jul 2025 00:16:58 +0200 Subject: [PATCH 10/16] feat: add tests for equal operator on arguments --- .../bootstrap/config/provider/StableConfigParser.java | 8 ++++---- .../config/provider/StableConfigParserTest.groovy | 10 ++++++++++ 2 files changed, 14 insertions(+), 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 2ed6d6f2eae..928f1950ce7 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 @@ -104,7 +104,7 @@ private static boolean doesRuleMatch(Rule rule) { } private static boolean matchOperator(String value, String operator, List matches) { - // not sure if these are nullable, but the semantics make sense + // not sure if these are nullable, but the semantics makes sense // and that will save us from a NPE if (value == null || operator == null) { return false; @@ -140,6 +140,9 @@ private static boolean matchOperator(String value, String operator, List // We do all of the case insensitivity modifications in this function, because each selector will // be viewed just once static boolean selectorMatch(String origin, List matches, String operator, String key) { + if (operator == null) { + return false; + } operator = operator.toLowerCase(); switch (origin.toLowerCase()) { case "language": @@ -152,9 +155,6 @@ static boolean selectorMatch(String origin, List matches, String operato return false; } String envValue = System.getenv(key.toUpperCase()); - if (envValue == null) { - return false; - } return matchOperator(envValue, operator, matches); case "process_arguments": if (key == null) { 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 636f76d69a0..c4a78eac108 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 @@ -68,6 +68,8 @@ apm_configuration_rules: injectEnvConfig("DD_PROFILING_ENABLED", "true") injectEnvConfig("DD_SERVICE", "mysvc") injectEnvConfig("DD_TAGS", "team:apm,component:web") + System.setProperty("arg1", "value1") + def match = StableConfigParser.selectorMatch(origin, matches, operator, key) then: @@ -83,6 +85,7 @@ apm_configuration_rules: "language" | ["java"] | "exists" | "" | false "language" | ["java"] | "something unexpected" | "" | false "environment_variables" | [] | "exists" | "DD_TAGS" | true + "environment_variables" | null | "exists" | "DD_TAGS" | true "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 @@ -96,6 +99,13 @@ apm_configuration_rules: "environment_variables" | ["svc"] | "contains" | "DD_SERVICE" | true "environment_variables" | ["other"] | "contains" | "DD_SERVICE" | false "environment_variables" | [null] | "contains" | "DD_SERVICE" | false + "environment_variables" | [] | "equals" | null | false + "environment_variables" | null | "equals" | "DD_SERVICE" | false + "language" | ["java"] | null | "" | false + "process_arguments" | null | "exists" | "-Darg1" | true + "process_arguments" | null | "exists" | "-Darg2" | false + "process_arguments" | ["value1"] | "equals" | "-Darg1" | true + "process_arguments" | ["value2"] | "equals" | "-Darg1" | false } def "test duplicate entries not allowed"() { From cfb37dba407c2bc518d0b1adf3694ebedc15f8a5 Mon Sep 17 00:00:00 2001 From: paullegranddc Date: Sun, 20 Jul 2025 16:39:28 +0200 Subject: [PATCH 11/16] fix: use equal method instead of operator --- .../config/provider/StableConfigParser.java | 4 +-- .../provider/StableConfigParserTest.groovy | 36 ++++++++++++++++--- 2 files changed, 33 insertions(+), 7 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 928f1950ce7..f13fba28d35 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 @@ -109,7 +109,7 @@ private static boolean matchOperator(String value, String operator, List if (value == null || operator == null) { return false; } - if (operator == "exists") { + if (operator.equals("exists")) { return true; } if (matches == null) { @@ -146,7 +146,7 @@ static boolean selectorMatch(String origin, List matches, String operato operator = operator.toLowerCase(); switch (origin.toLowerCase()) { case "language": - if (operator == "exists") { + if (operator.equals("exists")) { return false; } return matchOperator("java", operator, matches); 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 c4a78eac108..cd36709ef7d 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 @@ -62,14 +62,40 @@ apm_configuration_rules: Files.delete(filePath) } + def "test parse and template"() { + when: + Path filePath = Files.createTempFile("testFile_", ".yaml") + then: + if (filePath == null) { + throw new AssertionError("Failed to create: " + filePath) + } + + when: + String yaml = """ + apm_configuration_rules: + - selectors: + - origin: process_arguments + key: "-Dtest_parse_and_template" + operator: exists + configuration: + DD_SERVICE: {{process_arguments['-Dtest_parse_and_template']}} +""" + System.setProperty("test_parse_and_template", "myservice") + Files.write(filePath, yaml.getBytes()) + StableConfigSource.StableConfig cfg = StableConfigParser.parse(filePath.toString()) + + then: + cfg.get("DD_SERVICE") == "myservice" + } + def "test selectorMatch"() { when: // Env vars injectEnvConfig("DD_PROFILING_ENABLED", "true") injectEnvConfig("DD_SERVICE", "mysvc") injectEnvConfig("DD_TAGS", "team:apm,component:web") - System.setProperty("arg1", "value1") - + System.setProperty("test_selectorMatch", "value1") + def match = StableConfigParser.selectorMatch(origin, matches, operator, key) then: @@ -102,10 +128,10 @@ apm_configuration_rules: "environment_variables" | [] | "equals" | null | false "environment_variables" | null | "equals" | "DD_SERVICE" | false "language" | ["java"] | null | "" | false - "process_arguments" | null | "exists" | "-Darg1" | true + "process_arguments" | null | "exists" | "-Dtest_selectorMatch" | true "process_arguments" | null | "exists" | "-Darg2" | false - "process_arguments" | ["value1"] | "equals" | "-Darg1" | true - "process_arguments" | ["value2"] | "equals" | "-Darg1" | false + "process_arguments" | ["value1"] | "equals" | "-Dtest_selectorMatch" | true + "process_arguments" | ["value2"] | "equals" | "-Dtest_selectorMatch" | false } def "test duplicate entries not allowed"() { From a8ff1528ca13e480d4cc13fdc331f724308112f2 Mon Sep 17 00:00:00 2001 From: Mikayla Toffler <46911781+mtoffl01@users.noreply.github.com> Date: Mon, 21 Jul 2025 12:01:05 -0400 Subject: [PATCH 12/16] Update internal-api/src/main/java/datadog/trace/bootstrap/config/provider/StableConfigParser.java Co-authored-by: Bruce Bujon --- .../trace/bootstrap/config/provider/StableConfigParser.java | 2 +- 1 file changed, 1 insertion(+), 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 f13fba28d35..7c51737051c 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 @@ -109,7 +109,7 @@ private static boolean matchOperator(String value, String operator, List if (value == null || operator == null) { return false; } - if (operator.equals("exists")) { + if ("exist".equals(operator)) { return true; } if (matches == null) { From 6f1ea89a1ef76f047d65725555e92c367aa0559b Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Mon, 21 Jul 2025 13:55:45 -0400 Subject: [PATCH 13/16] apply PR suggestions --- .../bootstrap/config/provider/StableConfigParser.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 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 7c51737051c..8e82f219ad8 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 @@ -12,6 +12,7 @@ import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -104,23 +105,21 @@ private static boolean doesRuleMatch(Rule rule) { } private static boolean matchOperator(String value, String operator, List matches) { - // not sure if these are nullable, but the semantics makes sense - // and that will save us from a NPE if (value == null || operator == null) { return false; } if ("exist".equals(operator)) { return true; } - if (matches == null) { + if (matches.isEmpty()) { return false; } - value = value.toLowerCase(); + value = value.toLowerCase(Locale.ROOT); for (String match : matches) { if (match == null) { continue; } - match = match.toLowerCase(); + match = match.toLowerCase(Locale.ROOT); switch (operator) { case "equals": return value.equals(match); @@ -146,7 +145,7 @@ static boolean selectorMatch(String origin, List matches, String operato operator = operator.toLowerCase(); switch (origin.toLowerCase()) { case "language": - if (operator.equals("exists")) { + if ("exists".equals(operator)) { return false; } return matchOperator("java", operator, matches); From db73932ef82143d9e72dd8a9737e5320724b0651 Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Mon, 21 Jul 2025 14:02:59 -0400 Subject: [PATCH 14/16] fix typo --- .../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 8e82f219ad8..a99ea59e9e1 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 @@ -108,7 +108,7 @@ private static boolean matchOperator(String value, String operator, List if (value == null || operator == null) { return false; } - if ("exist".equals(operator)) { + if ("exists".equals(operator)) { return true; } if (matches.isEmpty()) { @@ -136,7 +136,7 @@ private static boolean matchOperator(String value, String operator, List return false; } - // We do all of the case insensitivity modifications in this function, because each selector will + // We do all the case insensitivity modifications in this function, because each selector will // be viewed just once static boolean selectorMatch(String origin, List matches, String operator, String key) { if (operator == null) { From 12c673d8825ec58412aef8822ab0ee3f660fcfb8 Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Mon, 21 Jul 2025 14:08:22 -0400 Subject: [PATCH 15/16] Add missing locale --- .../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 a99ea59e9e1..1b219ec2748 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 @@ -142,8 +142,8 @@ static boolean selectorMatch(String origin, List matches, String operato if (operator == null) { return false; } - operator = operator.toLowerCase(); - switch (origin.toLowerCase()) { + operator = operator.toLowerCase(Locale.ROOT); + switch (origin.toLowerCase(Locale.ROOT)) { case "language": if ("exists".equals(operator)) { return false; From 4f4c5bc91cc9a32bd6a86e2682e17a455d15445e Mon Sep 17 00:00:00 2001 From: Mikayla Toffler Date: Tue, 22 Jul 2025 10:21:26 -0400 Subject: [PATCH 16/16] add matches == null check back in to avoid NPE --- .../trace/bootstrap/config/provider/StableConfigParser.java | 6 +++--- 1 file changed, 3 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 1b219ec2748..90a17667c56 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 @@ -111,7 +111,7 @@ private static boolean matchOperator(String value, String operator, List if ("exists".equals(operator)) { return true; } - if (matches.isEmpty()) { + if (matches == null || matches.isEmpty()) { return false; } value = value.toLowerCase(Locale.ROOT); @@ -153,7 +153,7 @@ static boolean selectorMatch(String origin, List matches, String operato if (key == null) { return false; } - String envValue = System.getenv(key.toUpperCase()); + String envValue = System.getenv(key.toUpperCase(Locale.ROOT)); return matchOperator(envValue, operator, matches); case "process_arguments": if (key == null) { @@ -229,7 +229,7 @@ private static String processTemplateVar(String templateVar) throws IOException if (envVar.isEmpty()) { throw new IOException("Empty environment variable name in template"); } - String value = System.getenv(envVar.toUpperCase()); + String value = System.getenv(envVar.toUpperCase(Locale.ROOT)); if (value == null || value.isEmpty()) { return UNDEFINED_VALUE; }