diff --git a/src/main/java/com/datadog/ServerlessCompatAgent.java b/src/main/java/com/datadog/ServerlessCompatAgent.java index b3732f4..97abbae 100644 --- a/src/main/java/com/datadog/ServerlessCompatAgent.java +++ b/src/main/java/com/datadog/ServerlessCompatAgent.java @@ -7,6 +7,8 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -16,6 +18,7 @@ enum CloudEnvironment { AZURE_FUNCTION, AZURE_SPRING_APP, GOOGLE_CLOUD_RUN_FUNCTION_1ST_GEN, + GOOGLE_CLOUD_RUN_FUNCTION_2ND_GEN, UNKNOWN } @@ -50,23 +53,39 @@ public static boolean isLinux() { } public static CloudEnvironment getEnvironment() { - Map env = System.getenv(); + return getEnvironment(System.getenv()); + } + + static CloudEnvironment getEnvironment(Map env) { + List detected = new ArrayList<>(); - if (env.get("FUNCTIONS_EXTENSION_VERSION") != null && - env.get("FUNCTIONS_WORKER_RUNTIME") != null) { - return CloudEnvironment.AZURE_FUNCTION; + if (env.get("FUNCTIONS_EXTENSION_VERSION") != null + && env.get("FUNCTIONS_WORKER_RUNTIME") != null) { + detected.add(CloudEnvironment.AZURE_FUNCTION); } if (env.get("ASCSVCRT_SPRING__APPLICATION__NAME") != null) { - return CloudEnvironment.AZURE_SPRING_APP; + detected.add(CloudEnvironment.AZURE_SPRING_APP); } - if (env.get("FUNCTION_NAME") != null && - env.get("GCP_PROJECT") != null) { - return CloudEnvironment.GOOGLE_CLOUD_RUN_FUNCTION_1ST_GEN; + if (env.get("FUNCTION_NAME") != null && env.get("GCP_PROJECT") != null) { + // Set by Google Cloud Functions for older runtimes + detected.add(CloudEnvironment.GOOGLE_CLOUD_RUN_FUNCTION_1ST_GEN); + } else if (env.get("K_SERVICE") != null && env.get("FUNCTION_TARGET") != null) { + // Set by Google Cloud Functions for newer runtimes + detected.add(CloudEnvironment.GOOGLE_CLOUD_RUN_FUNCTION_2ND_GEN); + } + + if (detected.isEmpty()) { + return CloudEnvironment.UNKNOWN; + } + if (detected.size() > 1) { + log.error("Multiple cloud environments detected: {}", detected); + return CloudEnvironment.UNKNOWN; } - return CloudEnvironment.UNKNOWN; + CloudEnvironment environment = detected.get(0); + return environment; } public static String getPackageVersion() { diff --git a/src/test/java/com/datadog/ServerlessCompatAgentTest.java b/src/test/java/com/datadog/ServerlessCompatAgentTest.java new file mode 100644 index 0000000..8f20a84 --- /dev/null +++ b/src/test/java/com/datadog/ServerlessCompatAgentTest.java @@ -0,0 +1,116 @@ +package com.datadog; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.slf4j.Logger; +import org.slf4j.helpers.NOPLogger; + +import static org.junit.jupiter.api.Assertions.*; + +class ServerlessCompatAgentTest { + + @ParameterizedTest + @CsvSource({ + "TRACE, TRACE", + "DEBUG, DEBUG", + "INFO, INFO", + "WARN, WARN", + "ERROR, ERROR", + "CRITICAL, ERROR", + "OFF, null" + }) + void testInitLogger(String ddLogLevel, String expectedSlf4jLevel) throws Exception { + Method initLoggerMethod = ServerlessCompatAgent.class.getDeclaredMethod("initLogger", String.class); + initLoggerMethod.setAccessible(true); + Logger logger = (Logger) initLoggerMethod.invoke(null, ddLogLevel); + + if ("OFF".equals(ddLogLevel)) { + assertTrue(logger instanceof NOPLogger); + } else { + assertEquals(expectedSlf4jLevel, + System.getProperty("org.slf4j.simpleLogger.defaultLogLevel")); + } + } + + @Test + void getEnvironment_returnsUnknownWhenNoVarsSet() { + assertEquals(CloudEnvironment.UNKNOWN, + ServerlessCompatAgent.getEnvironment(new HashMap<>())); + } + + @Test + void getEnvironment_detectsAzureFunction() { + Map env = new HashMap<>(); + env.put("FUNCTIONS_EXTENSION_VERSION", "~4"); + env.put("FUNCTIONS_WORKER_RUNTIME", "java"); + assertEquals(CloudEnvironment.AZURE_FUNCTION, + ServerlessCompatAgent.getEnvironment(env)); + } + + @Test + void getEnvironment_requiresBothAzureFunctionVars() { + Map env = new HashMap<>(); + env.put("FUNCTIONS_EXTENSION_VERSION", "~4"); + assertEquals(CloudEnvironment.UNKNOWN, + ServerlessCompatAgent.getEnvironment(env)); + } + + @Test + void getEnvironment_detectsAzureSpringApp() { + Map env = new HashMap<>(); + env.put("ASCSVCRT_SPRING__APPLICATION__NAME", "my-app"); + assertEquals(CloudEnvironment.AZURE_SPRING_APP, + ServerlessCompatAgent.getEnvironment(env)); + } + + @Test + void getEnvironment_detectsGcpOlderRuntimes() { + Map env = new HashMap<>(); + env.put("FUNCTION_NAME", "my-function"); + env.put("GCP_PROJECT", "my-project"); + assertEquals(CloudEnvironment.GOOGLE_CLOUD_RUN_FUNCTION_1ST_GEN, + ServerlessCompatAgent.getEnvironment(env)); + } + + @Test + void getEnvironment_requiresBothGcpOlderRuntimesVars() { + Map env = new HashMap<>(); + env.put("FUNCTION_NAME", "my-function"); + assertEquals(CloudEnvironment.UNKNOWN, + ServerlessCompatAgent.getEnvironment(env)); + } + + @Test + void getEnvironment_detectsGcpNewerRuntimes() { + Map env = new HashMap<>(); + env.put("K_SERVICE", "my-service"); + env.put("FUNCTION_TARGET", "handler"); + assertEquals(CloudEnvironment.GOOGLE_CLOUD_RUN_FUNCTION_2ND_GEN, + ServerlessCompatAgent.getEnvironment(env)); + } + + @Test + void getEnvironment_returnsUnknownWhenMultipleEnvironmentsDetected() { + Map env = new HashMap<>(); + env.put("FUNCTIONS_EXTENSION_VERSION", "~4"); + env.put("FUNCTIONS_WORKER_RUNTIME", "java"); + env.put("FUNCTION_NAME", "my-function"); + env.put("GCP_PROJECT", "my-project"); + assertEquals(CloudEnvironment.UNKNOWN, + ServerlessCompatAgent.getEnvironment(env)); + } + + @Test + void getEnvironment_bareFunctionNameDoesNotTriggerGcpDetection() { + Map env = new HashMap<>(); + env.put("FUNCTION_NAME", "my-function"); + env.put("FUNCTIONS_EXTENSION_VERSION", "~4"); + env.put("FUNCTIONS_WORKER_RUNTIME", "java"); + assertEquals(CloudEnvironment.AZURE_FUNCTION, + ServerlessCompatAgent.getEnvironment(env)); + } +} diff --git a/src/test/java/test.java b/src/test/java/test.java deleted file mode 100644 index 60078b5..0000000 --- a/src/test/java/test.java +++ /dev/null @@ -1,34 +0,0 @@ -import com.datadog.ServerlessCompatAgent; -import java.lang.reflect.Method; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; -import org.slf4j.Logger; -import org.slf4j.helpers.NOPLogger; - -import static org.junit.jupiter.api.Assertions.*; - -class ServerlessCompatAgentTest { - - @ParameterizedTest - @CsvSource({ - "TRACE, TRACE", - "DEBUG, DEBUG", - "INFO, INFO", - "WARN, WARN", - "ERROR, ERROR", - "CRITICAL, ERROR", - "OFF, null" - }) - void testInitLogger(String ddLogLevel, String expectedSlf4jLevel) throws Exception { - Method initLoggerMethod = ServerlessCompatAgent.class.getDeclaredMethod("initLogger", String.class); - initLoggerMethod.setAccessible(true); - Logger logger = (Logger) initLoggerMethod.invoke(null, ddLogLevel); - - if ("OFF".equals(ddLogLevel)) { - assertTrue(logger instanceof NOPLogger); - } else { - assertEquals(expectedSlf4jLevel, - System.getProperty("org.slf4j.simpleLogger.defaultLogLevel")); - } - } -}