diff --git a/README.md b/README.md index c9442b4..8c36e86 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,19 @@ Datadog library for Java to enable tracing and custom metric submission from [Azure Functions](https://azure.microsoft.com/en-us/products/functions) and [Google Cloud Run Functions (1st gen)](https://cloud.google.com/functions/1stgendocs/concepts/overview). +## Inventory version metadata + +With `DD_SERVERLESS_COMPAT_METADATA_ENABLED=true`, inventory reports the wrapper package as +`serverless_compat_runtime_version`, the embedded binary release as +`serverless_compat_binary_version`, and the language engine in `runtime`. +`DD_SERVERLESS_COMPAT_PATH` selects a custom binary but does not change the wrapper package version. +The binary must supply its own embedded version; an unversioned binary must not inherit the wrapper version. + +The wrapper passes a combined language and version hint (for example, `python3.13.7`) +through `DD_SERVERLESS_COMPAT_RUNTIME` +to the child binary without overwriting platform-owned version variables. This requires a +binary that supports this contract; older binaries retain their platform-based runtime detection. + # Getting Started - [Install Serverless Monitoring for Azure Functions](https://docs.datadoghq.com/serverless/azure_functions/?code-lang=java) diff --git a/src/main/java/com/datadog/ServerlessCompatAgent.java b/src/main/java/com/datadog/ServerlessCompatAgent.java index 97abbae..eef1526 100644 --- a/src/main/java/com/datadog/ServerlessCompatAgent.java +++ b/src/main/java/com/datadog/ServerlessCompatAgent.java @@ -169,12 +169,24 @@ public static void premain(String agentArgs, Instrumentation instrumentation) { String packageVersion = getPackageVersion(); log.debug("Found package version {}", packageVersion); - ProcessBuilder processBuilder = new ProcessBuilder(executableFile.getAbsolutePath()); - processBuilder.environment().put("DD_SERVERLESS_COMPAT_VERSION", packageVersion); + ProcessBuilder processBuilder = createProcessBuilder(executableFile, packageVersion); processBuilder.inheritIO(); processBuilder.start(); } catch (Exception e) { log.error("Exception when starting {}", fileName, e); } } + + static ProcessBuilder createProcessBuilder(File executable, String packageVersion) { + ProcessBuilder processBuilder = new ProcessBuilder(executable.getAbsolutePath()); + Map childEnvironment = processBuilder.environment(); + childEnvironment.put("DD_SERVERLESS_COMPAT_VERSION", packageVersion); + String javaVersion = System.getProperty("java.version"); + if (javaVersion != null && !javaVersion.trim().isEmpty()) { + childEnvironment.put("DD_SERVERLESS_COMPAT_RUNTIME", "java" + javaVersion.trim()); + } else { + childEnvironment.remove("DD_SERVERLESS_COMPAT_RUNTIME"); + } + return processBuilder; + } } diff --git a/src/test/java/com/datadog/ServerlessCompatAgentTest.java b/src/test/java/com/datadog/ServerlessCompatAgentTest.java index 8f20a84..a1926f5 100644 --- a/src/test/java/com/datadog/ServerlessCompatAgentTest.java +++ b/src/test/java/com/datadog/ServerlessCompatAgentTest.java @@ -1,6 +1,7 @@ package com.datadog; import java.lang.reflect.Method; +import java.io.File; import java.util.HashMap; import java.util.Map; import org.junit.jupiter.api.Test; @@ -13,6 +14,43 @@ class ServerlessCompatAgentTest { + @Test + void childReceivesWrapperAndEngineVersionsForCustomBinary() { + File executable = new File("/custom/compat"); + String inheritedWorkerVersion = System.getenv("FUNCTIONS_WORKER_RUNTIME_VERSION"); + ProcessBuilder child = ServerlessCompatAgent.createProcessBuilder( + executable, "0.25.0"); + assertEquals(executable.getAbsolutePath(), child.command().get(0)); + assertEquals("0.25.0", child.environment().get("DD_SERVERLESS_COMPAT_VERSION")); + assertEquals("java" + System.getProperty("java.version"), child.environment().get("DD_SERVERLESS_COMPAT_RUNTIME")); + assertEquals(System.getenv("JAVA_VERSION"), child.environment().get("JAVA_VERSION")); + assertEquals(inheritedWorkerVersion, child.environment().get("FUNCTIONS_WORKER_RUNTIME_VERSION")); + assertEquals(inheritedWorkerVersion, System.getenv("FUNCTIONS_WORKER_RUNTIME_VERSION")); + assertEquals(System.getenv("DD_SERVICE"), child.environment().get("DD_SERVICE")); + } + + @Test + void missingJavaVersionDoesNotSupplyRuntimeHint() { + String originalVersion = System.getProperty("java.version"); + try { + for (String version : new String[] {null, "", " "}) { + if (version == null) { + System.clearProperty("java.version"); + } else { + System.setProperty("java.version", version); + } + ProcessBuilder child = ServerlessCompatAgent.createProcessBuilder(new File("/custom/compat"), "0.25.0"); + assertFalse(child.environment().containsKey("DD_SERVERLESS_COMPAT_RUNTIME")); + } + } finally { + if (originalVersion == null) { + System.clearProperty("java.version"); + } else { + System.setProperty("java.version", originalVersion); + } + } + } + @ParameterizedTest @CsvSource({ "TRACE, TRACE",