Skip to content

Commit

Permalink
Add SymDB report for any jar scanning failures (#8300)
Browse files Browse the repository at this point in the history
Any bail out when resolving or scanning for jars will be reported
into SymDBReport and logged as a single INFO log line at the end
of SYMDB extraction process from SymDB enablement
  • Loading branch information
jpbempel authored Jan 29, 2025
1 parent e078e8a commit a41d151
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ public class JarScanner {
private static final String SPRING_CLASSES_PREFIX = "BOOT-INF/classes/";
private static final String SPRING_DEPS_PREFIX = "BOOT-INF/lib/";

public static Path extractJarPath(Class<?> clazz) throws URISyntaxException {
return extractJarPath(clazz.getProtectionDomain());
public static Path extractJarPath(Class<?> clazz, SymDBReport symDBReport)
throws URISyntaxException {
return extractJarPath(clazz.getProtectionDomain(), symDBReport);
}

public static Path extractJarPath(ProtectionDomain protectionDomain) throws URISyntaxException {
public static Path extractJarPath(ProtectionDomain protectionDomain, SymDBReport symDBReport) {
if (protectionDomain == null) {
return null;
}
Expand All @@ -50,6 +51,9 @@ public static Path extractJarPath(ProtectionDomain protectionDomain) throws URIS
} else if (locationStr.startsWith(FILE_PREFIX)) {
return getPathFromPrefixedFileName(locationStr, FILE_PREFIX, locationStr.length());
}
if (symDBReport != null) {
symDBReport.addLocationError(locationStr);
}
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,9 @@ public void startSymbolExtraction() {
symbolExtractionTransformer =
new SymbolExtractionTransformer(symbolAggregator, classNameFilter);
instrumentation.addTransformer(symbolExtractionTransformer);
extractSymbolForLoadedClasses();
SymDBReport symDBReport = new SymDBReport();
extractSymbolForLoadedClasses(symDBReport);
symDBReport.report();
lastUploadTimestamp = System.currentTimeMillis();
} catch (Throwable ex) {
// catch all Throwables because LinkageError is possible (duplicate class definition)
Expand All @@ -130,7 +132,7 @@ public void startSymbolExtraction() {
}
}

private void extractSymbolForLoadedClasses() {
private void extractSymbolForLoadedClasses(SymDBReport symDBReport) {
Class<?>[] classesToExtract;
try {
classesToExtract =
Expand All @@ -148,19 +150,21 @@ private void extractSymbolForLoadedClasses() {
for (Class<?> clazz : classesToExtract) {
Path jarPath;
try {
jarPath = JarScanner.extractJarPath(clazz);
jarPath = JarScanner.extractJarPath(clazz, symDBReport);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
if (jarPath == null) {
continue;
}
if (!Files.exists(jarPath)) {
symDBReport.addMissingJar(jarPath.toString());
continue;
}
File jarPathFile = jarPath.toFile();
if (jarPathFile.isDirectory()) {
// we are not supporting class directories (classpath) but only jar files
symDBReport.addDirectoryJar(jarPath.toString());
continue;
}
if (alreadyScannedJars.contains(jarPath.toString())) {
Expand All @@ -178,6 +182,7 @@ private void extractSymbolForLoadedClasses() {
}
alreadyScannedJars.add(jarPath.toString());
} catch (IOException e) {
symDBReport.addIOException(jarPath.toString(), e);
throw new RuntimeException(e);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.datadog.debugger.symbol;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SymDBReport {
private static final Logger LOGGER = LoggerFactory.getLogger(SymDBReport.class);

private final Set<String> missingJars = new HashSet<>();
private final Set<String> directoryJars = new HashSet<>();
private final Map<String, String> ioExceptions = new HashMap<>();
private final List<String> locationErrors = new ArrayList<>();

public void addMissingJar(String jarPath) {
missingJars.add(jarPath);
}

public void addDirectoryJar(String jarPath) {
directoryJars.add(jarPath);
}

public void addIOException(String jarPath, IOException e) {
ioExceptions.put(jarPath, e.toString());
}

public void addLocationError(String locationStr) {
locationErrors.add(locationStr);
}

public void report() {
String content =
"== SymDB Report == Location errors:"
+ locationErrors
+ " Missing jars: "
+ missingJars
+ " Directory jars: "
+ directoryJars
+ " IOExceptions: "
+ ioExceptions;
LOGGER.info(content);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public void parseClass(
String className, byte[] classfileBuffer, ProtectionDomain protectionDomain) {
try {
String jarName = "DEFAULT";
Path jarPath = JarScanner.extractJarPath(protectionDomain);
Path jarPath = JarScanner.extractJarPath(protectionDomain, null);
if (jarPath != null && Files.exists(jarPath)) {
LOGGER.debug("jarpath: {}", jarPath);
jarName = jarPath.toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ public void extractJarPathFromJar()
URL jarUrl = new URL("jar:file:" + jarFileUrl.getFile() + "!/");
URLClassLoader urlClassLoader = new URLClassLoader(new URL[] {jarUrl}, null);
Class<?> testClass = urlClassLoader.loadClass(CLASS_NAME);
assertEquals(jarFileUrl.getFile(), JarScanner.extractJarPath(testClass).toString());
assertEquals(jarFileUrl.getFile(), JarScanner.extractJarPath(testClass, null).toString());
assertEquals(
jarFileUrl.getFile(),
JarScanner.extractJarPath(testClass.getProtectionDomain()).toString());
JarScanner.extractJarPath(testClass.getProtectionDomain(), null).toString());
}

@Test
Expand All @@ -34,7 +34,7 @@ public void extractJarPathFromFile() throws ClassNotFoundException, URISyntaxExc
URL jarFileUrl = getClass().getResource("/debugger-symbol.jar");
URLClassLoader urlClassLoader = new URLClassLoader(new URL[] {jarFileUrl}, null);
Class<?> testClass = urlClassLoader.loadClass(CLASS_NAME);
assertEquals(jarFileUrl.getFile(), JarScanner.extractJarPath(testClass).toString());
assertEquals(jarFileUrl.getFile(), JarScanner.extractJarPath(testClass, null).toString());
}

@Test
Expand All @@ -45,6 +45,7 @@ public void extractJarPathFromNestedJar() throws URISyntaxException {
.thenReturn("jar:nested:" + jarFileUrl.getFile() + "/!BOOT-INF/classes/!");
CodeSource codeSource = new CodeSource(mockLocation, (Certificate[]) null);
ProtectionDomain protectionDomain = new ProtectionDomain(codeSource, null);
assertEquals(jarFileUrl.getFile(), JarScanner.extractJarPath(protectionDomain).toString());
assertEquals(
jarFileUrl.getFile(), JarScanner.extractJarPath(protectionDomain, null).toString());
}
}

0 comments on commit a41d151

Please sign in to comment.