From 589eadf154cc988c150a1667207c604e48a6c01f Mon Sep 17 00:00:00 2001 From: jean-philippe bempel Date: Fri, 24 Apr 2026 17:27:26 +0200 Subject: [PATCH 1/3] cleanup --- .../debugger/agent/DebuggerTransformer.java | 60 +------------------ 1 file changed, 3 insertions(+), 57 deletions(-) diff --git a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/agent/DebuggerTransformer.java b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/agent/DebuggerTransformer.java index ffcb5a006f0..3f883b0bba2 100644 --- a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/agent/DebuggerTransformer.java +++ b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/agent/DebuggerTransformer.java @@ -85,7 +85,6 @@ public class DebuggerTransformer implements ClassFileTransformer { private static final Logger LOGGER = LoggerFactory.getLogger(DebuggerTransformer.class); private static final String CANNOT_FIND_METHOD = "Cannot find method %s::%s%s"; private static final String INSTRUMENTATION_FAILS = "Instrumentation failed for %s: %s"; - private static final String CANNOT_FIND_LINE = "No executable code was found at %s:L%s"; private static final Pattern COMMA_PATTERN = Pattern.compile(","); private static final List> PROBE_ORDER = Arrays.asList( @@ -258,7 +257,7 @@ public byte[] transform( if (instrumentTheWorld) { return transformTheWorld(loader, classFilePath, protectionDomain, classfileBuffer); } - if (skipInstrumentation(loader, classFilePath)) { + if (skipInstrumentation(classFilePath)) { return null; } List definitions = Collections.emptyList(); @@ -375,7 +374,7 @@ private boolean checkRecordTypeAnnotation( return true; } - private boolean skipInstrumentation(ClassLoader loader, String classFilePath) { + private boolean skipInstrumentation(String classFilePath) { if (definitionMatcher.isEmpty()) { LOGGER.debug("No debugger definitions present."); return true; @@ -892,7 +891,6 @@ private static ProbeDefinition selectReferenceDefinition( LogProbe.Capture capture = null; boolean captureSnapshot = false; ProbeCondition probeCondition = null; - List captureExpressions = null; Where where = capturedContextProbes.get(0).getWhere(); ProbeId probeId = capturedContextProbes.get(0).getProbeId(); for (ProbeDefinition definition : capturedContextProbes) { @@ -904,8 +902,6 @@ private static ProbeDefinition selectReferenceDefinition( LogProbe logProbe = (LogProbe) definition; captureSnapshot = captureSnapshot | logProbe.isCaptureSnapshot(); capture = mergeCapture(capture, logProbe.getCapture()); - // captureExpressions = mergeCaptureExpressions(captureExpressions, - // logProbe.getCaptureExpressions()); if (probeCondition == null) { probeCondition = logProbe.getProbeCondition(); } @@ -951,19 +947,6 @@ private static LogProbe.Capture mergeCapture( Math.max(current.getMaxFieldCount(), newCapture.getMaxFieldCount())); } - private static List mergeCaptureExpressions( - List captureExpressions, - List newCaptureExpressions) { - if (captureExpressions == null) { - return newCaptureExpressions; - } - if (newCaptureExpressions == null) { - return captureExpressions; - } - captureExpressions.addAll(newCaptureExpressions); - return captureExpressions; - } - private InstrumentationResult.Status preCheckInstrumentation( Map> diagnostics, MethodInfo methodInfo) { if ((methodInfo.getMethodNode().access & (Opcodes.ACC_NATIVE | Opcodes.ACC_ABSTRACT)) != 0) { @@ -1002,43 +985,6 @@ private static void addDiagnosticForAllProbes( diagnostics.forEach((probeId, diagnosticMessages) -> diagnosticMessages.add(diagnosticMessage)); } - private List matchMethodDescription( - ClassNode classNode, Where where, ClassFileLines classFileLines) { - List result = new ArrayList<>(); - try { - for (MethodNode methodNode : classNode.methods) { - if (where.isMethodMatching(methodNode, classFileLines) == Where.MethodMatching.MATCH) { - result.add(methodNode); - } - } - } catch (Exception ex) { - LOGGER.warn("Cannot match method: {}", ex.toString()); - } - return result; - } - - private MethodNode matchSourceFile( - ClassNode classNode, Where where, ClassFileLines classFileLines) { - Where.SourceLine[] lines = where.getSourceLines(); - if (lines == null || lines.length == 0) { - return null; - } - Where.SourceLine sourceLine = lines[0]; // assume only 1 range - int matchingLine = sourceLine.getFrom(); - List matchingMethods = classFileLines.getMethodsByLine(matchingLine); - if (matchingMethods != null) { - matchingMethods.forEach( - methodNode -> { - LOGGER.debug("Found lineNode {} method: {}", matchingLine, methodNode.name); - }); - // pick the first matching method. - // TODO need a way to disambiguate if multiple methods match the same line - return matchingMethods.isEmpty() ? null : matchingMethods.get(0); - } - LOGGER.debug("Cannot find line: {} in class {}", matchingLine, classNode.name); - return null; - } - private void dumpInstrumentedClassFile(String className, byte[] data) { if (config.isDynamicInstrumentationClassFileDumpEnabled()) { LOGGER.debug("Generated bytecode len: {}", data.length); @@ -1125,7 +1071,7 @@ protected String getCommonSuperClass(String type1, String type2) { try { TypeDescription td1 = tpDatadogClassLoader.describe(type1.replace('/', '.')).resolve(); TypeDescription td2 = tpDatadogClassLoader.describe(type2.replace('/', '.')).resolve(); - TypeDescription common = null; + TypeDescription common; if (td1.isAssignableFrom(td2)) { common = td1; } else if (td2.isAssignableFrom(td1)) { From 00e1844b54a3586303087758cd207cb6ba92e6fc Mon Sep 17 00:00:00 2001 From: jean-philippe bempel Date: Fri, 24 Apr 2026 19:04:37 +0200 Subject: [PATCH 2/3] Add support for case insensitivity file names Add support for case-insensitive path matching for line probes. When a probe path contains different casing (e.g., Controllers/DebuggerController.java vs actual controllers/DebuggerController.java), we should match them case-insensitively. this allows to support case-insensitive filesystem (Windows, MacOs) --- .../agent/TransformerDefinitionMatcher.java | 3 +++ .../TransformerDefinitionMatcherTest.java | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/agent/TransformerDefinitionMatcher.java b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/agent/TransformerDefinitionMatcher.java index 3c02b745a12..e8395ccc3d4 100644 --- a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/agent/TransformerDefinitionMatcher.java +++ b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/agent/TransformerDefinitionMatcher.java @@ -60,6 +60,7 @@ private void populateDefinitionFileNamesMap(Collection definiti continue; } fileName = normalizeWindowsToUnixPath(fileName); + fileName = fileName.toLowerCase(); Map> targetMap = fileName.indexOf('/') != -1 ? definitionsByQualifiedFileNames @@ -139,6 +140,7 @@ private List matchProbeDefinitionsBySourceFile( sb.append(reversedPackageName); } String reversedFileName = sb.toString(); + reversedFileName = reversedFileName.toLowerCase(); List bySourceFileDefinitions = new ArrayList<>(); // try match qualified filenames Collection matchingFileNames = @@ -153,6 +155,7 @@ private List matchProbeDefinitionsBySourceFile( } } // try match simple filenames + sourceFileName = sourceFileName.toLowerCase(); List definitions = definitionsBySimpleFileNames.get("/" + sourceFileName); if (definitions != null) { bySourceFileDefinitions.addAll(definitions); diff --git a/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/agent/TransformerDefinitionMatcherTest.java b/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/agent/TransformerDefinitionMatcherTest.java index 283dd87cfec..b0149097800 100644 --- a/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/agent/TransformerDefinitionMatcherTest.java +++ b/dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/agent/TransformerDefinitionMatcherTest.java @@ -64,6 +64,15 @@ public void sourceFileFullFileName() { assertEquals(PROBE_ID1, probeDefinitions.get(0).getProbeId()); } + @Test + public void sourceFileFullFileNameCaseInsensitive() { + LogProbe probe = createProbe(PROBE_ID1, "Src/Main/Java/Java/LanG/STRING.jAvA", 23); + TransformerDefinitionMatcher matcher = createMatcher(probe); + List probeDefinitions = match(matcher, String.class); + assertEquals(1, probeDefinitions.size()); + assertEquals(PROBE_ID1, probeDefinitions.get(0).getProbeId()); + } + @Test public void sourceFileAbsoluteFileName() { LogProbe probe = @@ -103,6 +112,15 @@ public void sourceFileSimpleFileName() { assertEquals(PROBE_ID1, probeDefinitions.get(0).getProbeId()); } + @Test + public void sourceFileSimpleFileNameCaseInsensitive() { + LogProbe probe = createProbe(PROBE_ID1, "sTRINg.JAVA", 23); + TransformerDefinitionMatcher matcher = createMatcher(probe); + List probeDefinitions = match(matcher, String.class); + assertEquals(1, probeDefinitions.size()); + assertEquals(PROBE_ID1, probeDefinitions.get(0).getProbeId()); + } + @Test public void multiProbesFQN() { LogProbe probe1 = createProbe(PROBE_ID1, "java.lang.String", "indexOf"); From 883b8d14d08eefb3a44f56fd3b43ec5e79fce13a Mon Sep 17 00:00:00 2001 From: jean-philippe bempel Date: Wed, 29 Apr 2026 14:24:22 +0200 Subject: [PATCH 3/3] add Locale.ROOT --- .../debugger/agent/TransformerDefinitionMatcher.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/agent/TransformerDefinitionMatcher.java b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/agent/TransformerDefinitionMatcher.java index e8395ccc3d4..64158a27c28 100644 --- a/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/agent/TransformerDefinitionMatcher.java +++ b/dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/agent/TransformerDefinitionMatcher.java @@ -9,6 +9,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -60,7 +61,7 @@ private void populateDefinitionFileNamesMap(Collection definiti continue; } fileName = normalizeWindowsToUnixPath(fileName); - fileName = fileName.toLowerCase(); + fileName = fileName.toLowerCase(Locale.ROOT); Map> targetMap = fileName.indexOf('/') != -1 ? definitionsByQualifiedFileNames @@ -140,7 +141,7 @@ private List matchProbeDefinitionsBySourceFile( sb.append(reversedPackageName); } String reversedFileName = sb.toString(); - reversedFileName = reversedFileName.toLowerCase(); + reversedFileName = reversedFileName.toLowerCase(Locale.ROOT); List bySourceFileDefinitions = new ArrayList<>(); // try match qualified filenames Collection matchingFileNames = @@ -155,7 +156,7 @@ private List matchProbeDefinitionsBySourceFile( } } // try match simple filenames - sourceFileName = sourceFileName.toLowerCase(); + sourceFileName = sourceFileName.toLowerCase(Locale.ROOT); List definitions = definitionsBySimpleFileNames.get("/" + sourceFileName); if (definitions != null) { bySourceFileDefinitions.addAll(definitions);