From 63bfe247d7d13bcc94b8269d821e927c50e920f4 Mon Sep 17 00:00:00 2001 From: Andrea Marziali Date: Fri, 23 Jan 2026 17:10:15 +0100 Subject: [PATCH 1/4] Improve crashtracking payload and add build_id and relative address --- .../agent-crashtracking/build.gradle | 3 + .../buildid/BuildIdCollector.java | 100 +++++++ .../buildid/BuildIdExtractor.java | 42 +++ .../crashtracking/buildid/BuildInfo.java | 23 ++ .../buildid/ElfBuildIdExtractor.java | 202 ++++++++++++++ .../buildid/NoOpBuildIdExtractor.java | 24 ++ .../buildid/PeBuildIdExtractor.java | 108 ++++++++ .../datadog/crashtracking/dto/CrashLog.java | 2 +- .../datadog/crashtracking/dto/ErrorData.java | 2 +- .../datadog/crashtracking/dto/ProcInfo.java | 10 +- .../datadog/crashtracking/dto/SigInfo.java | 26 +- .../datadog/crashtracking/dto/StackFrame.java | 36 ++- .../parsers/HotspotCrashLogParser.java | 254 ++++++++++++++---- .../buildid/BuildIdCollectorTest.java | 88 ++++++ .../BuildIdExtractorIntegrationTest.java | 153 +++++++++++ .../sample-crash-for-telemetry-2.txt | 2 +- .../sample-crash-for-telemetry-3.txt | 2 +- .../sample-crash-for-telemetry.txt | 2 +- .../golden/errortracking/sample_oom.txt | 2 +- .../sample-crash-for-telemetry-2.txt | 2 +- .../sample-crash-for-telemetry-3.txt | 2 +- .../telemetry/sample-crash-for-telemetry.txt | 2 +- .../resources/golden/telemetry/sample_oom.txt | 2 +- 23 files changed, 1012 insertions(+), 77 deletions(-) create mode 100644 dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/BuildIdCollector.java create mode 100644 dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/BuildIdExtractor.java create mode 100644 dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/BuildInfo.java create mode 100644 dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/ElfBuildIdExtractor.java create mode 100644 dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/NoOpBuildIdExtractor.java create mode 100644 dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/PeBuildIdExtractor.java create mode 100644 dd-java-agent/agent-crashtracking/src/test/java/datadog/crashtracking/buildid/BuildIdCollectorTest.java create mode 100644 dd-java-agent/agent-crashtracking/src/test/java/datadog/crashtracking/buildid/BuildIdExtractorIntegrationTest.java diff --git a/dd-java-agent/agent-crashtracking/build.gradle b/dd-java-agent/agent-crashtracking/build.gradle index 132fe43aa81..2f0f4113ca0 100644 --- a/dd-java-agent/agent-crashtracking/build.gradle +++ b/dd-java-agent/agent-crashtracking/build.gradle @@ -16,6 +16,7 @@ dependencies { implementation project(':internal-api') implementation project(':products:metrics:metrics-lib') implementation project(':utils:container-utils') + implementation project(':utils:queue-utils') implementation project(':utils:version-utils') implementation project(path: ':dd-java-agent:ddprof-lib', configuration: 'shadow') @@ -23,8 +24,10 @@ dependencies { implementation libs.moshi testImplementation libs.bundles.junit5 + testImplementation libs.junit.jupiter testImplementation libs.bundles.mockito testImplementation libs.jackson.databind + testImplementation libs.testcontainers testImplementation group: 'com.squareup.okhttp3', name: 'mockwebserver', version: libs.versions.okhttp.legacy.get() } diff --git a/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/BuildIdCollector.java b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/BuildIdCollector.java new file mode 100644 index 00000000000..ee5749aaf91 --- /dev/null +++ b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/BuildIdCollector.java @@ -0,0 +1,100 @@ +package datadog.crashtracking.buildid; + +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; + +import datadog.common.queue.Queues; +import datadog.trace.util.AgentTaskScheduler; +import java.nio.file.Path; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.LockSupport; +import org.jctools.queues.MessagePassingQueue; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class BuildIdCollector { + static final Logger LOGGER = LoggerFactory.getLogger(BuildIdCollector.class); + static final BuildInfo EMPTY = new BuildInfo(null, null, null); + + private final Map libraryBuildInfo = new ConcurrentHashMap<>(); + private final Set processed = new HashSet<>(); + private final AtomicBoolean collecting = new AtomicBoolean(false); + private final MessagePassingQueue workQueue = Queues.spscArrayQueue(Short.MAX_VALUE); + private final CountDownLatch latch = new CountDownLatch(1); + + class Collector implements Runnable { + private final BuildIdExtractor extractor = BuildIdExtractor.create(); + + Collector() {} + + @Override + public void run() { + while (true) { + final Path path = workQueue.poll(); + if (path == null) { + if (!collecting.get()) { + break; + } + LockSupport.parkNanos(MILLISECONDS.toNanos(50)); + continue; + } + final String fileName = path.getFileName().toString(); + LOGGER.debug("Resolving build id for {} against {}", fileName, path); + final String buildId = extractor.extractBuildId(path); + if (buildId != null) { + LOGGER.debug("Found build id {} for library {}", buildId, fileName); + libraryBuildInfo.put( + fileName, new BuildInfo(buildId, extractor.buildIdType(), extractor.fileType())); + } + } + latch.countDown(); + } + } + + public void addUnprocessedLibrary(String filename) { + if (!collecting.get()) { + libraryBuildInfo.putIfAbsent(filename, EMPTY); + } + } + + public void resolveBuildId(Path path) { + if (collecting.compareAndSet(false, true)) { + AgentTaskScheduler.get().execute(new Collector()); + } + final String filename = path.getFileName().toString(); + if (!processed.add(filename)) { + return; + } + if (libraryBuildInfo.remove(filename) == null) { + // the library is not present in the collected ones part of the stackframe + LOGGER.debug( + "Skipping build id resolution for {} as it was not added to unprocessed", filename); + + } else { + workQueue.offer(path); + } + } + + public void awaitCollectionDone(final int timeoutSeconds) { + if (!collecting.compareAndSet(true, false)) { + return; + } + try { + if (!latch.await(timeoutSeconds, SECONDS)) { + LOGGER.warn("Build id collection incomplete."); + } + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + LOGGER.warn("Interrupted while waiting for build id collection to finish"); + } + } + + public BuildInfo getBuildInfo(String filename) { + return libraryBuildInfo.get(filename); + } +} diff --git a/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/BuildIdExtractor.java b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/BuildIdExtractor.java new file mode 100644 index 00000000000..859a62b10f9 --- /dev/null +++ b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/BuildIdExtractor.java @@ -0,0 +1,42 @@ +package datadog.crashtracking.buildid; + +import datadog.environment.OperatingSystem; +import java.nio.file.Path; + +/** + * Interface for extracting build IDs from native library binaries. Build IDs help identify exact + * library versions for symbolization of native stack traces. + */ +public interface BuildIdExtractor { + /** + * Extracts build ID from a binary file. + * + * @param file Path to the library file + * @return Build ID as hex string, or null if not found or on error + */ + String extractBuildId(Path file); + + /** + * @return the file type this extractor operates for. + */ + BuildInfo.FileType fileType(); + + /** + * @return the build id type this extractor is able to provide. + */ + BuildInfo.BuildIdType buildIdType(); + + /** + * Factory method that returns appropriate extractor for the platform. + * + * @return Platform-specific build ID extractor + */ + static BuildIdExtractor create() { + if (OperatingSystem.isLinux()) { + return new ElfBuildIdExtractor(); + } else if (OperatingSystem.isWindows()) { + return new PeBuildIdExtractor(); + } + return new NoOpBuildIdExtractor(); + } +} diff --git a/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/BuildInfo.java b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/BuildInfo.java new file mode 100644 index 00000000000..070676251fb --- /dev/null +++ b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/BuildInfo.java @@ -0,0 +1,23 @@ +package datadog.crashtracking.buildid; + +public class BuildInfo { + public enum BuildIdType { + SHA1, // ELF + PE // WIN + } + + public enum FileType { + ELF, + PE, + } + + public final String buildId; + public final BuildIdType buildIdType; + public final FileType fileType; + + public BuildInfo(final String buildId, final BuildIdType buildIdType, final FileType fileType) { + this.buildId = buildId; + this.buildIdType = buildIdType; + this.fileType = fileType; + } +} diff --git a/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/ElfBuildIdExtractor.java b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/ElfBuildIdExtractor.java new file mode 100644 index 00000000000..d22e354c2df --- /dev/null +++ b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/ElfBuildIdExtractor.java @@ -0,0 +1,202 @@ +package datadog.crashtracking.buildid; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.file.Path; +import java.util.Arrays; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Extracts build IDs from ELF (Executable and Linkable Format) binaries. Supports both 32-bit and + * 64-bit ELF files with little-endian and big-endian byte ordering. + */ +public class ElfBuildIdExtractor implements BuildIdExtractor { + private static final Logger log = LoggerFactory.getLogger(ElfBuildIdExtractor.class); + + // ELF magic: 0x7f 'E' 'L' 'F' + private static final byte[] ELF_MAGIC = {0x7f, 0x45, 0x4c, 0x46}; + + // ELF header constants + private static final int ELFCLASS32 = 1; + private static final int ELFCLASS64 = 2; + + private static final int ELFDATA2LSB = 1; // Little endian + private static final int ELFDATA2MSB = 2; // Big endian + + // Program header constants + private static final int PT_NOTE = 4; + + // Note header constants + private static final int NT_GNU_BUILD_ID = 3; + private static final byte[] GNU_NOTE_NAME = "GNU\0".getBytes(); + + @Override + public String extractBuildId(Path file) { + try (RandomAccessFile raf = new RandomAccessFile(file.toFile(), "r")) { + // 1. Read and verify ELF magic (first 4 bytes) + byte[] magic = new byte[4]; + if (raf.read(magic) != 4 || !Arrays.equals(magic, ELF_MAGIC)) { + log.debug("Not an ELF file: {}", file); + return null; + } + + // 2. Determine file class (32 or 64 bit) + int elfClass = raf.read(); + boolean is64Bit = (elfClass == ELFCLASS64); + if (elfClass != ELFCLASS32 && elfClass != ELFCLASS64) { + log.debug("Invalid ELF class in file: {}", file); + return null; + } + + // 3. Determine endianness + int elfData = raf.read(); + boolean isLittleEndian = (elfData == ELFDATA2LSB); + if (elfData != ELFDATA2LSB && elfData != ELFDATA2MSB) { + log.debug("Invalid ELF data encoding in file: {}", file); + return null; + } + + // 4. Read ELF header to get program header table offset and size + raf.seek(is64Bit ? 32 : 28); // Offset to e_phoff + long phoff = is64Bit ? readLong(raf, isLittleEndian) : readInt(raf, isLittleEndian); + + raf.seek(is64Bit ? 54 : 42); // Offset to e_phnum + int phnum = readShort(raf, isLittleEndian); + + // 5. Iterate through program headers to find PT_NOTE segments + for (int i = 0; i < phnum; i++) { + long phEntryOffset = phoff + ((long) i * (is64Bit ? 56 : 32)); + raf.seek(phEntryOffset); + + int pType = (int) readInt(raf, isLittleEndian); + if (pType != PT_NOTE) { + continue; + } + + // Read PT_NOTE segment offset and size + long pOffset, pSize; + if (is64Bit) { + raf.seek(phEntryOffset + 8); + pOffset = readLong(raf, isLittleEndian); + raf.seek(phEntryOffset + 32); + pSize = readLong(raf, isLittleEndian); + } else { + raf.seek(phEntryOffset + 4); + pOffset = readInt(raf, isLittleEndian); + raf.seek(phEntryOffset + 16); + pSize = readInt(raf, isLittleEndian); + } + + // 6. Parse notes in this PT_NOTE segment + String buildId = parseNoteSegment(raf, pOffset, pSize, isLittleEndian); + if (buildId != null) { + return buildId; + } + } + + log.debug("No build ID found in ELF file: {}", file); + return null; + + } catch (IOException | SecurityException e) { + log.debug("Failed to extract ELF build ID from {}: {}", file, e.getMessage()); + return null; + } catch (Throwable t) { + log.debug("Unexpected error extracting ELF build ID from {}: {}", file, t.getMessage()); + return null; + } + } + + @Override + public BuildInfo.FileType fileType() { + return BuildInfo.FileType.ELF; + } + + @Override + public BuildInfo.BuildIdType buildIdType() { + return BuildInfo.BuildIdType.SHA1; + } + + private String parseNoteSegment( + RandomAccessFile raf, long offset, long size, boolean isLittleEndian) throws IOException { + raf.seek(offset); + long end = offset + size; + + while (raf.getFilePointer() < end) { + long currentPos = raf.getFilePointer(); + + // Ensure we don't read beyond segment + if (currentPos + 12 > end) { + break; + } + + int namesz = (int) readInt(raf, isLittleEndian); + int descsz = (int) readInt(raf, isLittleEndian); + int type = (int) readInt(raf, isLittleEndian); + + // Align to 4-byte boundary + int nameLen = (namesz + 3) & ~3; + int descLen = (descsz + 3) & ~3; + + // Bounds check + if (currentPos + 12 + nameLen + descLen > end) { + break; + } + + // Read note name + byte[] name = new byte[namesz]; + raf.read(name); + raf.skipBytes(nameLen - namesz); + + // Check if this is the GNU build ID note + if (type == NT_GNU_BUILD_ID && Arrays.equals(name, GNU_NOTE_NAME)) { + // Read build ID + byte[] buildIdBytes = new byte[descsz]; + raf.read(buildIdBytes); + + // Convert to hex string + StringBuilder hex = new StringBuilder(descsz * 2); + for (byte b : buildIdBytes) { + hex.append(String.format("%02x", b & 0xff)); + } + return hex.toString(); + } else { + // Skip descriptor + raf.skipBytes(descLen); + } + } + return null; + } + + private int readShort(RandomAccessFile raf, boolean isLittleEndian) throws IOException { + byte[] bytes = new byte[2]; + if (raf.read(bytes) != 2) { + throw new IOException("Failed to read short"); + } + ByteBuffer buf = ByteBuffer.wrap(bytes); + buf.order(isLittleEndian ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN); + return buf.getShort() & 0xFFFF; + } + + private long readInt(RandomAccessFile raf, boolean isLittleEndian) throws IOException { + byte[] bytes = new byte[4]; + if (raf.read(bytes) != 4) { + throw new IOException("Failed to read int"); + } + ByteBuffer buf = ByteBuffer.wrap(bytes); + buf.order(isLittleEndian ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN); + return buf.getInt() & 0xFFFFFFFFL; + } + + private long readLong(RandomAccessFile raf, boolean isLittleEndian) throws IOException { + byte[] bytes = new byte[8]; + if (raf.read(bytes) != 8) { + throw new IOException("Failed to read long"); + } + ByteBuffer buf = ByteBuffer.wrap(bytes); + buf.order(isLittleEndian ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN); + return buf.getLong(); + } +} diff --git a/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/NoOpBuildIdExtractor.java b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/NoOpBuildIdExtractor.java new file mode 100644 index 00000000000..71bf8e8c31f --- /dev/null +++ b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/NoOpBuildIdExtractor.java @@ -0,0 +1,24 @@ +package datadog.crashtracking.buildid; + +import java.nio.file.Path; + +/** + * No-op build ID extractor for unsupported platforms. Always returns null to indicate build IDs are + * not available. + */ +public class NoOpBuildIdExtractor implements BuildIdExtractor { + @Override + public String extractBuildId(Path file) { + return null; // No build ID on this platform + } + + @Override + public BuildInfo.FileType fileType() { + return null; + } + + @Override + public BuildInfo.BuildIdType buildIdType() { + return null; + } +} diff --git a/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/PeBuildIdExtractor.java b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/PeBuildIdExtractor.java new file mode 100644 index 00000000000..15f6c09eca4 --- /dev/null +++ b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/PeBuildIdExtractor.java @@ -0,0 +1,108 @@ +package datadog.crashtracking.buildid; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.file.Path; +import java.util.Arrays; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Extracts build IDs from PE (Portable Executable) binaries used on Windows. Uses the TimeDateStamp + * from the COFF header as the build ID. + */ +public class PeBuildIdExtractor implements BuildIdExtractor { + private static final Logger log = LoggerFactory.getLogger(PeBuildIdExtractor.class); + + // DOS header magic: 'M' 'Z' + private static final byte[] MZ_MAGIC = {0x4d, 0x5a}; + + // PE signature: 'P' 'E' 0x00 0x00 + private static final byte[] PE_SIGNATURE = {0x50, 0x45, 0x00, 0x00}; + + @Override + public String extractBuildId(Path file) { + try (RandomAccessFile raf = new RandomAccessFile(file.toFile(), "r")) { + long size = raf.length(); + + // 1. Verify DOS header magic (first 2 bytes) + byte[] magic = new byte[2]; + if (raf.read(magic) != 2 || !Arrays.equals(magic, MZ_MAGIC)) { + log.debug("Not a PE file (missing MZ magic): {}", file); + return null; + } + + // 2. Read PE header offset from DOS header (at offset 0x3C) + raf.seek(0x3C); + byte[] offsetBytes = new byte[4]; + if (raf.read(offsetBytes) != 4) { + log.debug("Failed to read PE header offset from: {}", file); + return null; + } + ByteBuffer buf = ByteBuffer.wrap(offsetBytes); + buf.order(ByteOrder.LITTLE_ENDIAN); // PE is always little-endian + long peOffset = buf.getInt() & 0xFFFFFFFFL; + + // Bounds check + if (peOffset > size - 4) { + log.debug("Invalid PE header offset in file: {}", file); + return null; + } + + // 3. Verify PE signature + raf.seek(peOffset); + byte[] peSig = new byte[4]; + if (raf.read(peSig) != 4 || !Arrays.equals(peSig, PE_SIGNATURE)) { + log.debug("Invalid PE signature in file: {}", file); + return null; + } + + // 4. Read COFF header TimeDateStamp + // COFF header starts right after PE signature + // Layout: + // +0: Machine (2 bytes) + // +2: NumberOfSections (2 bytes) + // +4: TimeDateStamp (4 bytes) + long coffHeaderOffset = peOffset + 4; + + // Bounds check + if (coffHeaderOffset + 8 > size) { + log.debug("Invalid COFF header position in file: {}", file); + return null; + } + + raf.seek(coffHeaderOffset + 4); // Skip Machine and NumberOfSections + + byte[] timestampBytes = new byte[4]; + if (raf.read(timestampBytes) != 4) { + log.debug("Failed to read TimeDateStamp from: {}", file); + return null; + } + buf = ByteBuffer.wrap(timestampBytes); + buf.order(ByteOrder.LITTLE_ENDIAN); + long timestamp = buf.getInt() & 0xFFFFFFFFL; + + // 5. Return TimeDateStamp as 8-character hex string + return String.format("%08x", timestamp); + + } catch (IOException | SecurityException e) { + log.debug("Failed to extract PE build ID from {}: {}", file, e.getMessage()); + return null; + } catch (Throwable t) { + log.debug("Unexpected error extracting PE build ID from {}: {}", file, t.getMessage()); + return null; + } + } + + @Override + public BuildInfo.FileType fileType() { + return BuildInfo.FileType.PE; + } + + @Override + public BuildInfo.BuildIdType buildIdType() { + return BuildInfo.BuildIdType.PE; + } +} diff --git a/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/dto/CrashLog.java b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/dto/CrashLog.java index aa3a672ac9c..cd339934782 100644 --- a/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/dto/CrashLog.java +++ b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/dto/CrashLog.java @@ -10,7 +10,7 @@ public final class CrashLog { private static final int VERSION = 0; - private static final JsonAdapter ADAPTER; + public static final JsonAdapter ADAPTER; static { Moshi moshi = new Moshi.Builder().add(new SemanticVersion.SemanticVersionAdapter()).build(); diff --git a/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/dto/ErrorData.java b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/dto/ErrorData.java index 9ccb9a96e0d..5e94a500e6f 100644 --- a/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/dto/ErrorData.java +++ b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/dto/ErrorData.java @@ -11,7 +11,7 @@ public final class ErrorData { public final String message; @Json(name = "source_type") - public final String sourceType = "crashtracking"; + public final String sourceType = "Crashtracking"; public final StackTrace stack; diff --git a/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/dto/ProcInfo.java b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/dto/ProcInfo.java index 36dd8f5b3b3..22b5b822f17 100644 --- a/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/dto/ProcInfo.java +++ b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/dto/ProcInfo.java @@ -1,11 +1,9 @@ package datadog.crashtracking.dto; -import java.util.Objects; - public final class ProcInfo { - public final String pid; + public final int pid; - public ProcInfo(String pid) { + public ProcInfo(int pid) { this.pid = pid; } @@ -18,11 +16,11 @@ public boolean equals(Object o) { return false; } ProcInfo procInfo = (ProcInfo) o; - return Objects.equals(pid, procInfo.pid); + return pid == procInfo.pid; } @Override public int hashCode() { - return Objects.hashCode(pid); + return pid; } } diff --git a/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/dto/SigInfo.java b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/dto/SigInfo.java index c4cb00d6b65..f95167e6ef5 100644 --- a/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/dto/SigInfo.java +++ b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/dto/SigInfo.java @@ -1,29 +1,45 @@ package datadog.crashtracking.dto; +import com.squareup.moshi.Json; import java.util.Objects; public class SigInfo { - public final int number; + @Json(name = "si_signo") + public final Integer number; + + @Json(name = "si_code") + public final Integer code; + + @Json(name = "si_signo_human_readable") public final String name; + + @Json(name = "si_code_human_readable") + public final String action; + + @Json(name = "si_addr") public final String address; - public SigInfo(int number, String name, String address) { + public SigInfo(Integer number, String name, Integer code, String action, String address) { this.number = number; this.name = name; this.address = address; + this.code = code; + this.action = action; } @Override public boolean equals(Object o) { if (!(o instanceof SigInfo)) return false; SigInfo sigInfo = (SigInfo) o; - return number == sigInfo.number + return Objects.equals(number, sigInfo.number) && Objects.equals(name, sigInfo.name) - && Objects.equals(address, sigInfo.address); + && Objects.equals(address, sigInfo.address) + && Objects.equals(code, sigInfo.code) + && Objects.equals(action, sigInfo.action); } @Override public int hashCode() { - return Objects.hash(number, name, address); + return Objects.hash(number, name, address, code, action); } } diff --git a/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/dto/StackFrame.java b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/dto/StackFrame.java index e4232936935..10b87aab0a6 100644 --- a/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/dto/StackFrame.java +++ b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/dto/StackFrame.java @@ -1,16 +1,42 @@ package datadog.crashtracking.dto; +import com.squareup.moshi.Json; +import datadog.crashtracking.buildid.BuildInfo; import java.util.Objects; public final class StackFrame { + public final String file; public final Integer line; public final String function; - public StackFrame(String file, Integer line, String function) { + @Json(name = "build_id") + public final String buildId; + + @Json(name = "build_id_type") + public final BuildInfo.BuildIdType buildIdType; + + @Json(name = "file_type") + public final BuildInfo.FileType fileType; + + @Json(name = "relative_address") + public String relativeAddress; + + public StackFrame( + String file, + Integer line, + String function, + String buildId, + BuildInfo.BuildIdType buildIdType, + BuildInfo.FileType fileType, + String relativeAddress) { this.file = file; this.line = line; this.function = function; + this.buildId = buildId; + this.buildIdType = buildIdType; + this.fileType = fileType; + this.relativeAddress = relativeAddress; } @Override @@ -24,11 +50,15 @@ public boolean equals(Object o) { StackFrame that = (StackFrame) o; return Objects.equals(file, that.file) && Objects.equals(line, that.line) - && Objects.equals(function, that.function); + && Objects.equals(function, that.function) + && Objects.equals(buildId, that.buildId) + && buildIdType == that.buildIdType + && fileType == that.fileType + && Objects.equals(relativeAddress, that.relativeAddress); } @Override public int hashCode() { - return Objects.hash(file, line, function); + return Objects.hash(file, line, function, buildId, buildIdType, fileType, relativeAddress); } } diff --git a/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/parsers/HotspotCrashLogParser.java b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/parsers/HotspotCrashLogParser.java index fd142f9f01e..266d867095b 100644 --- a/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/parsers/HotspotCrashLogParser.java +++ b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/parsers/HotspotCrashLogParser.java @@ -3,6 +3,8 @@ import static java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME; import datadog.common.version.VersionInfo; +import datadog.crashtracking.buildid.BuildIdCollector; +import datadog.crashtracking.buildid.BuildInfo; import datadog.crashtracking.dto.CrashLog; import datadog.crashtracking.dto.ErrorData; import datadog.crashtracking.dto.Metadata; @@ -11,6 +13,9 @@ import datadog.crashtracking.dto.SigInfo; import datadog.crashtracking.dto.StackFrame; import datadog.crashtracking.dto.StackTrace; +import java.nio.file.InvalidPathException; +import java.nio.file.Path; +import java.nio.file.Paths; import java.time.OffsetDateTime; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; @@ -31,6 +36,8 @@ public final class HotspotCrashLogParser { // all lowercased private static final String[] KNOWN_LIBRARY_NAMES = {"libjavaprofiler", "libddwaf", "libsqreen"}; + private final BuildIdCollector buildIdCollector; + enum State { NEW, HEADER, @@ -38,39 +45,85 @@ enum State { SUMMARY, THREAD, STACKTRACE, + SEEK_DYNAMIC_LIBRARIES, + DYNAMIC_LIBRARIES, DONE } private State state = State.NEW; + public HotspotCrashLogParser() { + this.buildIdCollector = new BuildIdCollector(); + } + private static final Pattern PLUS_SPLITTER = Pattern.compile("\\+"); private static final Pattern SPACE_SPLITTER = Pattern.compile("\\s+"); private static final Pattern NEWLINE_SPLITTER = Pattern.compile("\n"); private static final Pattern SIGNAL_PARSER = Pattern.compile("\\s*(\\w+) \\((\\w+)\\).*"); + private static final Pattern SIGINFO_PARSER = + Pattern.compile( + "siginfo:\\s+si_signo:\\s+(\\d+)\\s+\\((\\w+)\\),\\s+si_code:\\s+(\\d+)\\s+\\(([^)]+)\\),\\s+si_addr:\\s+(0x[0-9a-fA-F]+)"); + private static final Pattern DYNAMIC_LIBS_PATH_PARSER = + Pattern.compile("^(?:0x)?[0-9a-fA-F]+(?:-[0-9a-fA-F]+)?\\s+(?:[^\\s/\\[]+\\s+)*(.*)$"); private StackFrame parseLine(String line) { + if (line == null || line.isEmpty()) { + return null; + } + String functionName = null; Integer functionLine = null; String filename = null; + String relAddress = null; char firstChar = line.charAt(0); + if (line.length() > 1 && !Character.isSpaceChar(line.charAt(1))) { + // with can found kind of that in between the frames that we need to skip + // Java frames: (J=compiled Java code, j=interpreted, Vv=VM code) + return null; + } switch (firstChar) { case 'J': { // J 36572 c2 datadog.trace.util.AgentTaskScheduler$PeriodicTask.run()V (25 bytes) @ // 0x00007f2fd0198488 [0x00007f2fd0198420+0x0000000000000068] + // J 3896 c2 java.nio.ByteBuffer.allocate(I)Ljava/nio/ByteBuffer; java.base@21.0.1 (20 + // bytes) @ 0x0000000112ad51e8 [0x0000000112ad4fc0+0x0000000000000228] String[] parts = SPACE_SPLITTER.split(line); - functionName = parts[3]; + if (parts.length > 3) { + functionName = parts[3]; + + // Extract module name (e.g., java.base@21.0.1) + if (parts.length > 4 && parts[4].contains("@")) { + int atIdx = parts[4].indexOf('@'); + filename = parts[4].substring(0, atIdx); + } + + // Extract relative address from bracket [0x...+0x...] + int bracketStart = line.indexOf('['); + if (bracketStart > 0) { + int bracketEnd = line.indexOf(']', bracketStart); + if (bracketEnd > 0) { + String bracketContent = line.substring(bracketStart + 1, bracketEnd); + int plusIdx = bracketContent.indexOf('+'); + if (plusIdx > 0 && plusIdx + 1 < bracketContent.length()) { + relAddress = bracketContent.substring(plusIdx + 1); + } + } + } + } break; } case 'j': { // j one.profiler.AsyncProfiler.stop()V+1 String[] parts = PLUS_SPLITTER.split(line, 2); - functionName = parts[0].substring(3); - if (parts.length > 1) { - try { - functionLine = Integer.parseInt(parts[1]); - } catch (Throwable ignored) { + if (parts.length > 0 && parts[0].length() > 3) { + functionName = parts[0].substring(3); + if (parts.length > 1) { + try { + functionLine = Integer.parseInt(parts[1]); + } catch (NumberFormatException ignored) { + } } } break; @@ -79,23 +132,26 @@ private StackFrame parseLine(String line) { case 'V': { // V [libjvm.so+0x8fc20a] thread_entry(JavaThread*, JavaThread*)+0x8a - if (line.endsWith("]")) { - // C [libpthread.so.0+0x13d60] - functionName = line.substring(4, line.length() - 1); - } else { - int plusIdx = line.lastIndexOf('+'); - functionName = - plusIdx > -1 - ? line.substring(line.indexOf(']') + 3, plusIdx) - : line.substring(line.indexOf(']') + 3); - } + // C [libpthread.so.0+0x13d60] int libstart = line.indexOf('['); if (libstart > 0) { int libend = line.indexOf(']', libstart + 1); if (libend > 0) { - String[] parts = PLUS_SPLITTER.split(line.substring(libstart + 1, libend), 2); - filename = normalizeFilename(parts[0]); - // TODO: extract relative address for second part and send to the intake + String libAndRelAddress = line.substring(libstart + 1, libend); + String[] parts = PLUS_SPLITTER.split(libAndRelAddress, 2); + filename = parts[0]; + if (parts.length > 1) { + relAddress = parts[1]; + } + + // Extract function name if present (after the bracket) + if (libend + 3 < line.length() && !line.endsWith("]")) { + int plusIdx = line.lastIndexOf('+'); + functionName = + plusIdx > libend + ? line.substring(libend + 3, plusIdx).trim() + : line.substring(libend + 3).trim(); + } } } break; @@ -103,23 +159,57 @@ private StackFrame parseLine(String line) { case 'v': { // v ~StubRoutines::call_stub - int plusIdx = line.lastIndexOf('+'); - functionName = - plusIdx > -1 - ? line.substring(line.indexOf(']') + 3, plusIdx) - : line.substring(line.indexOf(']') + 3); + // v ~RuntimeStub::_new_array_Java 0x00000001124cb638 + if (line.length() > 3) { + String remaining = line.substring(3).trim(); + // Check for address at the end (0x...) + int lastSpace = remaining.lastIndexOf(' '); + if (lastSpace > 0 && lastSpace + 1 < remaining.length()) { + String possibleAddress = remaining.substring(lastSpace + 1); + if (possibleAddress.startsWith("0x")) { + relAddress = possibleAddress; + remaining = remaining.substring(0, lastSpace).trim(); + } + } + // Check for + offset + int plusIdx = remaining.lastIndexOf('+'); + functionName = plusIdx > -1 ? remaining.substring(0, plusIdx).trim() : remaining; + } break; } default: // do nothing break; } - if (functionName != null) { - return new StackFrame(filename, functionLine, functionName); + if (filename != null && !filename.isEmpty()) { + buildIdCollector.addUnprocessedLibrary(filename); + } + + if (functionName != null || filename != null) { + return new StackFrame( + filename, + functionLine, + stripCompilerAnnotations(functionName), + null, + null, + null, + relAddress); } return null; } + private static String stripCompilerAnnotations(String functionName) { + if (functionName == null) { + return null; + } + // Strip compiler annotations like [clone .isra.531], [clone .constprop.0], etc. + int bracketIdx = functionName.lastIndexOf(" ["); + if (bracketIdx > 0 && functionName.endsWith("]")) { + return functionName.substring(0, bracketIdx); + } + return functionName; + } + private static String knownLibraryPrefix(String filename) { final String lowerCased = filename.toLowerCase(Locale.ROOT); for (String prefix : KNOWN_LIBRARY_NAMES) { @@ -130,7 +220,7 @@ private static String knownLibraryPrefix(String filename) { return null; } - private String normalizeFilename(String filename) { + private static String normalizeFilename(String filename) { if (filename == null) { return null; } @@ -177,28 +267,6 @@ public CrashLog parse(String uuid, String crashLog) { if (oomIdx > 0) { oomMessage = line.substring(oomIdx + OOM_MARKER.length()); } else { - String name = null, address = null; - int number = 0; - // first non-empty line after the message is the signal - final Matcher signalMatcher = SIGNAL_PARSER.matcher(line.substring(3)); - // # SIGSEGV (0xb) at pc=0x00007f8b1c0b3d7d, pid=1, tid=1 - if (signalMatcher.matches()) { - name = signalMatcher.group(1); - try { - number = Integer.decode(signalMatcher.group(2)); - } catch (Throwable ignored) { - } - } - - int pcIdx = line.indexOf("pc="); - if (pcIdx > -1) { - int endIdx = line.indexOf(',', pcIdx); - address = line.substring(pcIdx + 3, endIdx); - } - if (name != null) { - sigInfo = new SigInfo(number, name, address); - } - int pidIdx = line.indexOf("pid="); if (pidIdx > -1) { int endIdx = line.indexOf(',', pidIdx); @@ -229,8 +297,20 @@ public CrashLog parse(String uuid, String crashLog) { } break; case STACKTRACE: - if (line.isEmpty()) { - state = State.DONE; + if (line.startsWith("siginfo:")) { + // siginfo: si_signo: 11 (SIGSEGV), si_code: 1 (SEGV_MAPERR), si_addr: + // 0x0000000000000070 + final Matcher siginfoMatcher = SIGINFO_PARSER.matcher(line); + if (siginfoMatcher.matches()) { + Integer number = safelyParseInt(siginfoMatcher.group(1)); + String name = siginfoMatcher.group(2); + Integer siCode = safelyParseInt(siginfoMatcher.group(3)); + String sigAction = siginfoMatcher.group(4); + String address = siginfoMatcher.group(5); + sigInfo = new SigInfo(number, name, siCode, sigAction, address); + } + } else if (line.contains("P R O C E S S")) { + state = State.SEEK_DYNAMIC_LIBRARIES; } else { // Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code) final StackFrame frame = parseLine(line); @@ -239,8 +319,32 @@ public CrashLog parse(String uuid, String crashLog) { } } break; + case SEEK_DYNAMIC_LIBRARIES: + if (line.startsWith("Dynamic libraries:")) { + state = State.DYNAMIC_LIBRARIES; + } else if (line.equals("END.")) { + state = State.DONE; + } + break; + case DYNAMIC_LIBRARIES: + if (line.isEmpty()) { + state = State.DONE; + } + final Matcher matcher = DYNAMIC_LIBS_PATH_PARSER.matcher(line); + if (matcher.matches()) { + final String pathString = matcher.group(1); + if (pathString != null && !pathString.isEmpty()) { + try { + final Path path = Paths.get(pathString); + buildIdCollector.resolveBuildId(path); + } catch (InvalidPathException ignored) { + } + } + } + break; case DONE: // skip + buildIdCollector.awaitCollectionDone(5); break outer; default: // unexpected parser state; bail out @@ -262,12 +366,45 @@ public CrashLog parse(String uuid, String crashLog) { message = "Process terminated by signal " + kind; } + final List enrichedFrames = new ArrayList<>(frames.size()); + + for (StackFrame frame : frames) { + // enrich with the build id if collected (best effort) + if (frame.file == null) { + enrichedFrames.add(frame); + continue; + } + final BuildInfo buildInfo = buildIdCollector.getBuildInfo(frame.file); + if (buildInfo != null) { + enrichedFrames.add( + new StackFrame( + normalizeFilename(frame.file), + frame.line, + frame.function, + buildInfo.buildId, + buildInfo.buildIdType, + buildInfo.fileType, + frame.relativeAddress)); + } else { + enrichedFrames.add( + new StackFrame( + normalizeFilename(frame.file), + frame.line, + frame.function, + null, + null, + null, + frame.relativeAddress)); + } + } + ErrorData error = - new ErrorData(kind, message, new StackTrace(frames.toArray(new StackFrame[0]))); + new ErrorData(kind, message, new StackTrace(enrichedFrames.toArray(new StackFrame[0]))); // We can not really extract the full metadata and os info from the crash log // This code assumes the parser is run on the same machine as the crash happened Metadata metadata = new Metadata("dd-trace-java", VersionInfo.VERSION, "java", null); - ProcInfo procInfo = pid != null ? new ProcInfo(pid) : null; + Integer parsedPid = safelyParseInt(pid); + ProcInfo procInfo = parsedPid != null ? new ProcInfo(parsedPid) : null; return new CrashLog( uuid, incomplete, datetime, error, metadata, OSInfo.current(), procInfo, sigInfo, "1.0"); } @@ -285,4 +422,15 @@ static String dateTimeToISO(String datetime) { } } } + + static Integer safelyParseInt(String value) { + if (value == null) { + return null; + } + try { + return Integer.parseInt(value); + } catch (NumberFormatException e) { + return null; + } + } } diff --git a/dd-java-agent/agent-crashtracking/src/test/java/datadog/crashtracking/buildid/BuildIdCollectorTest.java b/dd-java-agent/agent-crashtracking/src/test/java/datadog/crashtracking/buildid/BuildIdCollectorTest.java new file mode 100644 index 00000000000..a145d09997b --- /dev/null +++ b/dd-java-agent/agent-crashtracking/src/test/java/datadog/crashtracking/buildid/BuildIdCollectorTest.java @@ -0,0 +1,88 @@ +package datadog.crashtracking.buildid; + +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +public class BuildIdCollectorTest { + + @TempDir Path tempDir; + + @Test + void testAwaitCollectionDoneWithinTimeout() throws IOException { + BuildIdCollector collector = new BuildIdCollector(); + + // Add a library to process + String filename = "test-library.so"; + collector.addUnprocessedLibrary(filename); + + // Create a simple test file + Path testFile = tempDir.resolve(filename); + Files.write(testFile, new byte[] {0x7F, 'E', 'L', 'F'}); // ELF magic bytes + + // Start collection + collector.resolveBuildId(testFile); + + // Should complete within timeout + long startTime = System.currentTimeMillis(); + collector.awaitCollectionDone(5); + long elapsedTime = System.currentTimeMillis() - startTime; + + // Verify it completed quickly (well under 5 seconds) + assertTrue(elapsedTime < 5000, "Collection should complete quickly"); + } + + @Test + void testAwaitCollectionDoneWithoutStartingCollection() { + BuildIdCollector collector = new BuildIdCollector(); + + // awaitCollectionDone without starting collection should return immediately + long startTime = System.currentTimeMillis(); + collector.awaitCollectionDone(5); + long elapsedTime = System.currentTimeMillis() - startTime; + + assertTrue(elapsedTime < 100, "Should return immediately when not collecting"); + } + + @Test + void testResolveBuildIdSkipsUnprocessedLibraries() throws IOException { + BuildIdCollector collector = new BuildIdCollector(); + + String filename = "not-added.so"; + Path testFile = tempDir.resolve(filename); + Files.write(testFile, new byte[] {0x7F, 'E', 'L', 'F'}); + + // Resolve without adding first + collector.resolveBuildId(testFile); + collector.awaitCollectionDone(1); + + // Should not be in the map since it wasn't added + BuildInfo info = collector.getBuildInfo(filename); + assertNull(info, "Library should not be processed if not added first"); + } + + @Test + void testMultipleAwaitCollectionDoneCalls() throws IOException { + BuildIdCollector collector = new BuildIdCollector(); + + String filename = "test.so"; + collector.addUnprocessedLibrary(filename); + Path testFile = tempDir.resolve(filename); + Files.write(testFile, new byte[] {0x7F, 'E', 'L', 'F'}); + + collector.resolveBuildId(testFile); + collector.awaitCollectionDone(5); + + // Second call should return immediately since collection is already done + long startTime = System.currentTimeMillis(); + collector.awaitCollectionDone(5); + long elapsedTime = System.currentTimeMillis() - startTime; + + assertTrue(elapsedTime < 100, "Second await should return immediately"); + } +} diff --git a/dd-java-agent/agent-crashtracking/src/test/java/datadog/crashtracking/buildid/BuildIdExtractorIntegrationTest.java b/dd-java-agent/agent-crashtracking/src/test/java/datadog/crashtracking/buildid/BuildIdExtractorIntegrationTest.java new file mode 100644 index 00000000000..d52617b71c1 --- /dev/null +++ b/dd-java-agent/agent-crashtracking/src/test/java/datadog/crashtracking/buildid/BuildIdExtractorIntegrationTest.java @@ -0,0 +1,153 @@ +package datadog.crashtracking.buildid; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.time.Duration; +import java.util.stream.Stream; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.io.TempDir; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.utility.DockerImageName; + +/** + * Integration tests for BuildIdExtractor implementations using Docker containers. Tests validate + * build ID extraction from real ELF (Unix/Linux) and PE (Windows) binaries. + */ +public class BuildIdExtractorIntegrationTest { + private static GenericContainer linuxContainer; + private static GenericContainer dotnetContainer; + @TempDir private static Path tempDir; + private static final Logger logger = + LoggerFactory.getLogger(BuildIdExtractorIntegrationTest.class); + + @BeforeAll + static void startContainers() throws IOException { + // Start Ubuntu container for ELF testing + // Use linux/amd64 platform to ensure x86_64 binaries are available + linuxContainer = + new GenericContainer<>( + DockerImageName.parse("ubuntu:22.04").asCompatibleSubstituteFor("ubuntu")) + .withCommand("sleep", "infinity") + .withStartupTimeout(Duration.ofMinutes(2)) + .withCreateContainerCmdModifier(cmd -> cmd.withPlatform("linux/amd64")); + linuxContainer.start(); + + // Start dotnet SDK container for PE testing + // Use linux/amd64 platform to ensure consistent binary format + dotnetContainer = + new GenericContainer<>( + DockerImageName.parse("mcr.microsoft.com/dotnet/sdk:8.0") + .asCompatibleSubstituteFor("dotnet")) + .withCommand("sleep", "infinity") + .withStartupTimeout(Duration.ofMinutes(2)) + .withCreateContainerCmdModifier(cmd -> cmd.withPlatform("linux/amd64")); + dotnetContainer.start(); + } + + @AfterAll + static void stopContainers() throws IOException { + // Stop containers + if (linuxContainer != null) { + linuxContainer.stop(); + } + if (dotnetContainer != null) { + dotnetContainer.stop(); + } + } + + /** + * Copy a binary file from a container to the local temp directory. + * + * @param container The container to copy from + * @param containerPath Path to the binary inside the container + * @return Path to the copied binary in the local temp directory + */ + private Path copyFromContainer(GenericContainer container, String containerPath) + throws IOException { + String filename = Paths.get(containerPath).getFileName().toString(); + Path localPath = tempDir.resolve(filename + "-" + System.nanoTime()); + + container.copyFileFromContainer(containerPath, localPath.toString()); + + if (!Files.exists(localPath) || Files.size(localPath) == 0) { + throw new IOException("Failed to copy binary: " + containerPath); + } + + return localPath; + } + + private static Stream elfBinaries() { + return Stream.of( + Arguments.of("/lib/x86_64-linux-gnu/libc.so.6", "GNU C Library"), + Arguments.of("/lib/x86_64-linux-gnu/libm.so.6", "Math library"), + Arguments.of("/lib/x86_64-linux-gnu/libpthread.so.0", "POSIX threads library")); + } + + @ParameterizedTest(name = "ELF: {1}") + @MethodSource("elfBinaries") + void testElfBuildIdExtraction(String containerPath, String description) throws Exception { + Path localBinary = copyFromContainer(linuxContainer, containerPath); + + ElfBuildIdExtractor extractor = new ElfBuildIdExtractor(); + String buildId = extractor.extractBuildId(localBinary); + + logger.info("Found build ID: {} for library {}", buildId, localBinary); + + assertNotNull(buildId, "Build ID should be found for " + description); + assertTrue( + buildId.matches("^[0-9a-f]{32,40}$"), "Build ID should be 32-40 hex chars: " + buildId); + assertEquals(BuildInfo.FileType.ELF, extractor.fileType()); + assertEquals(BuildInfo.BuildIdType.SHA1, extractor.buildIdType()); + } + + private static Stream peBinaries() { + return Stream.of( + Arguments.of( + "/usr/share/dotnet/shared/Microsoft.NETCore.App/8.0.23/System.Private.CoreLib.dll", + "Core .NET Library"), + Arguments.of( + "/usr/share/dotnet/shared/Microsoft.NETCore.App/8.0.23/System.Runtime.dll", + ".NET Runtime"), + Arguments.of( + "/usr/share/dotnet/shared/Microsoft.NETCore.App/8.0.23/System.Console.dll", + "Console Library"), + Arguments.of( + "/usr/share/dotnet/shared/Microsoft.NETCore.App/8.0.23/Microsoft.CSharp.dll", + "C# Compiler Library")); + } + + @ParameterizedTest(name = "PE: {1}") + @MethodSource("peBinaries") + void testPeBuildIdExtraction(String containerPath, String description) throws Exception { + Path localBinary = copyFromContainer(dotnetContainer, containerPath); + + PeBuildIdExtractor extractor = new PeBuildIdExtractor(); + String buildId = extractor.extractBuildId(localBinary); + + logger.info("Found build ID: {} for library {}", buildId, localBinary); + + assertNotNull(buildId, "TimeDateStamp should be found for " + description); + assertEquals(8, buildId.length(), "TimeDateStamp should be exactly 8 hex chars"); + assertTrue(buildId.matches("^[0-9a-f]{8}$"), "TimeDateStamp should be hex: " + buildId); + + long timestamp = Long.parseLong(buildId, 16); + assertTrue( + timestamp > 0x386D4380L && timestamp < System.currentTimeMillis(), + "Timestamp should be reasonable (2000-NOW): " + buildId); + + assertEquals(BuildInfo.FileType.PE, extractor.fileType()); + assertEquals(BuildInfo.BuildIdType.PE, extractor.buildIdType()); + } +} diff --git a/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample-crash-for-telemetry-2.txt b/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample-crash-for-telemetry-2.txt index 6020ddd1ee0..c6c384b38cb 100644 --- a/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample-crash-for-telemetry-2.txt +++ b/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample-crash-for-telemetry-2.txt @@ -1 +1 @@ -{"timestamp":"2024-09-20T13:19:06Z","ddsource":"crashtracker","error":{"source_type":"crashtracking","is_crash":true,"type":"SIGSEGV","message":"Process terminated by signal SIGSEGV","stack":{"format":"CrashTrackerV1","frames":[{"file":"libpthread.so.0","function":"__pthread_clockjoin_ex"}]}},"sig_info":{"si_addr":"0x00007f011ab1ccd5 (sent by kill)","si_signo_human_readable":"SIGSEGV","si_signo":11}} +{"timestamp":"2024-09-20T13:19:06Z","ddsource":"crashtracker","error":{"is_crash":true,"type":"UNKNOWN","message":"Process terminated by signal UNKNOWN","source_type":"crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"file":"libpthread.so.0","function":"__pthread_clockjoin_ex","relative_address":"0x9cd5"}]}}} ==> expected: <{data_schema_version=1.0, error={is_crash=true, kind=SIGSEGV, message=Process terminated by signal SIGSEGV, source_type=crashtracking, stack={format=CrashTrackerV1, frames=[{file=libpthread.so.0, function=__pthread_clockjoin_ex, relative_address=0x9cd5}]}}, incomplete=false, metadata={family=java, library_name=dd-trace-java, library_version=1.59.0-SNAPSHOT~83d60598da}, proc_info={pid=576034}, sig_info={si_addr=0x00007f011ab1ccd5 (sent by kill), si_signo=11, si_signo_human_readable=SIGSEGV}, timestamp=2024-09-20T13:19:06Z, uuid=a4194cd6-8cb3-45fd-9bd9-3af83e0a3ad3, version_id=0}> but was: <{timestamp=2024-09-20T13:19:06Z, ddsource=crashtracker, error={is_crash=true, type=UNKNOWN, message=Process terminated by signal UNKNOWN, source_type=crashtracking, stack={format=CrashTrackerV1, frames=[{file=libpthread.so.0, function=__pthread_clockjoin_ex, relative_address=0x9cd5}]}}} diff --git a/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample-crash-for-telemetry-3.txt b/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample-crash-for-telemetry-3.txt index e1000645dcc..b2c3913d910 100644 --- a/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample-crash-for-telemetry-3.txt +++ b/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample-crash-for-telemetry-3.txt @@ -1 +1 @@ -{"ddsource":"crashtracker","error":{"is_crash":true,"type":"OutOfMemory","message":"Java heap space","source_type":"crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"file":"libjvm.dylib","function":"VMError::report_and_die()"},{"file":"libjvm.dylib","function":"report_vm_error(char const*, int, char const*, char const*)"},{"file":"libjvm.dylib","function":"report_java_out_of_memory(char const*)"},{"file":"libjvm.dylib","function":"CollectedHeap::common_mem_allocate_noinit(KlassHandle, unsigned long, Thread*)"},{"file":"libjvm.dylib","function":"TypeArrayKlass::allocate_common(int, bool, Thread*)"},{"file":"libjvm.dylib","function":"InterpreterRuntime::newarray(JavaThread*, BasicType, int)"},{"function":"datadog.smoketest.crashtracking.CrashtrackingTestApplication.main([Ljava/lang/String;)V","line":105},{"function":" ~StubRoutines::call_stub"},{"file":"libjvm.dylib","function":"JavaCalls::call_helper(JavaValue*, methodHandle*, JavaCallArguments*, Thread*)"},{"file":"libjvm.dylib","function":"jni_invoke_static(JNIEnv_*, JavaValue*, _jobject*, JNICallType, _jmethodID*, JNI_ArgumentPusher*, Thread*)"},{"file":"libjvm.dylib","function":"jni_CallStaticVoidMethod"},{"file":"java","function":"JavaMain"},{"file":"libsystem_pthread.dylib","function":"_pthread_start"},{"file":"libsystem_pthread.dylib","function":"thread_start"}]}},"sig_info":{"si_addr":"0x0000000000000000","si_signo_human_readable":"INVALID","si_signo":0}} +{"ddsource":"crashtracker","error":{"is_crash":true,"type":"OutOfMemory","message":"Java heap space","source_type":"crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"file":"libjvm.dylib","function":"VMError::report_and_die()","relative_address":"0x565d30"},{"file":"libjvm.dylib","function":"report_vm_error(char const*, int, char const*, char const*)","relative_address":"0x1941a0"},{"file":"libjvm.dylib","function":"report_java_out_of_memory(char const*)","relative_address":"0x1943d8"},{"file":"libjvm.dylib","function":"CollectedHeap::common_mem_allocate_noinit(KlassHandle, unsigned long, Thread*)","relative_address":"0x70430"},{"file":"libjvm.dylib","function":"TypeArrayKlass::allocate_common(int, bool, Thread*)","relative_address":"0x53eba8"},{"file":"libjvm.dylib","function":"InterpreterRuntime::newarray(JavaThread*, BasicType, int)","relative_address":"0x285b6c"},{"function":"datadog.smoketest.crashtracking.CrashtrackingTestApplication.main([Ljava/lang/String;)V","line":105},{"function":"~StubRoutines::call_stub"},{"file":"libjvm.dylib","function":"JavaCalls::call_helper(JavaValue*, methodHandle*, JavaCallArguments*, Thread*)","relative_address":"0x28f86c"},{"file":"libjvm.dylib","function":"jni_invoke_static(JNIEnv_*, JavaValue*, _jobject*, JNICallType, _jmethodID*, JNI_ArgumentPusher*, Thread*)","relative_address":"0x2d3b44"},{"file":"libjvm.dylib","function":"jni_CallStaticVoidMethod","relative_address":"0x2d7160"},{"file":"java","function":"JavaMain","relative_address":"0x6404"},{"file":"libsystem_pthread.dylib","function":"_pthread_start","relative_address":"0x6f94"},{"file":"libsystem_pthread.dylib","function":"thread_start","relative_address":"0x1d34"},{"function":"datadog.smoketest.crashtracking.CrashtrackingTestApplication.main([Ljava/lang/String;)V","line":105},{"function":"~StubRoutines::call_stub"}]}}} diff --git a/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample-crash-for-telemetry.txt b/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample-crash-for-telemetry.txt index 034c42b7b06..46ca45b4032 100644 --- a/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample-crash-for-telemetry.txt +++ b/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample-crash-for-telemetry.txt @@ -1 +1 @@ -{"timestamp":"2023-10-17T20:25:14+08:00","ddsource":"crashtracker","error":{"is_crash":true,"type":"SIGSEGV","message":"Process terminated by signal SIGSEGV","source_type":"crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"file":"libjvm.so","function":"vframeStreamForte::forte_next()"},{"file":"libjvm.so","function":"forte_fill_call_trace_given_top(JavaThread*, ASGCT_CallTrace*, int, frame) [clone .isra.22]"},{"file":"libjvm.so","function":"AsyncGetCallTrace"},{"file":"libjavaProfiler.so","function":"Profiler::getJavaTraceAsync(void*, ASGCT_CallFrame*, int, StackContext*, bool*) [clone .isra.531]"},{"file":"libjavaProfiler.so","function":"Profiler::recordSample(void*, unsigned long long, int, int, Event*)"},{"file":"libjavaProfiler.so","function":"WallClock::sharedSignalHandler(int, siginfo_t*, void*)"},{"file":"libpthread.so.0","function":"libpthread.so.0+0x12cf0"},{"file":"libjvm.so","function":"JfrStackTrace::record_safe(JavaThread*, int)"},{"file":"libjvm.so","function":"JfrStackTraceRepository::record_for_leak_profiler(JavaThread*, int)"},{"file":"libjvm.so","function":"ObjectSampler::sample(HeapWordImpl**, unsigned long, JavaThread*)"},{"file":"libjvm.so","function":"JfrAllocationTracer::JfrAllocationTracer(Klass const*, HeapWordImpl**, unsigned long, bool, JavaThread*)"},{"file":"libjvm.so","function":"AllocTracer::send_allocation_in_new_tlab(Klass*, HeapWordImpl**, unsigned long, unsigned long, JavaThread*)"},{"file":"libjvm.so","function":"MemAllocator::allocate() const"},{"file":"libjvm.so","function":"InstanceKlass::allocate_objArray(int, int, JavaThread*)"},{"file":"libjvm.so","function":"OptoRuntime::new_array_C(Klass*, int, JavaThread*)"}]}},"sig_info":{"si_addr":"0x00007f37a18bc187","si_signo_human_readable":"SIGSEGV","si_signo":11}} +{"timestamp":"2023-10-17T20:25:14+08:00","ddsource":"crashtracker","error":{"is_crash":true,"type":"SIGSEGV","message":"Process terminated by signal SIGSEGV","source_type":"crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"file":"libjvm.so","function":"vframeStreamForte::forte_next()","relative_address":"0x6b7187"},{"file":"libjvm.so","function":"forte_fill_call_trace_given_top(JavaThread*, ASGCT_CallTrace*, int, frame)","relative_address":"0x6b79ad"},{"file":"libjvm.so","function":"AsyncGetCallTrace","relative_address":"0x6b8123"},{"file":"libjavaProfiler.so","function":"Profiler::getJavaTraceAsync(void*, ASGCT_CallFrame*, int, StackContext*, bool*)","relative_address":"0x146c8"},{"file":"libjavaProfiler.so","function":"Profiler::recordSample(void*, unsigned long long, int, int, Event*)","relative_address":"0x1c18d"},{"file":"libjavaProfiler.so","function":"WallClock::sharedSignalHandler(int, siginfo_t*, void*)","relative_address":"0x1d128"},{"file":"libpthread.so.0","relative_address":"0x12cf0"},{"file":"libjvm.so","function":"JfrStackTrace::record_safe(JavaThread*, int)","relative_address":"0x85f9e9"},{"file":"libjvm.so","function":"JfrStackTraceRepository::record_for_leak_profiler(JavaThread*, int)","relative_address":"0x861650"},{"file":"libjvm.so","function":"ObjectSampler::sample(HeapWordImpl**, unsigned long, JavaThread*)","relative_address":"0xb1ecba"},{"file":"libjvm.so","function":"JfrAllocationTracer::JfrAllocationTracer(Klass const*, HeapWordImpl**, unsigned long, bool, JavaThread*)","relative_address":"0x81abee"},{"file":"libjvm.so","function":"AllocTracer::send_allocation_in_new_tlab(Klass*, HeapWordImpl**, unsigned long, unsigned long, JavaThread*)","relative_address":"0x3afa20"},{"file":"libjvm.so","function":"MemAllocator::allocate() const","relative_address":"0xa8f8ed"},{"file":"libjvm.so","function":"InstanceKlass::allocate_objArray(int, int, JavaThread*)","relative_address":"0x7e443c"},{"file":"libjvm.so","function":"OptoRuntime::new_array_C(Klass*, int, JavaThread*)","relative_address":"0xbe1b59"},{"function":"~RuntimeStub::_new_array_Java"},{"file":"java.base","function":"java.util.HashMap.resize()[Ljava/util/HashMap$Node;","relative_address":"0x00000000000008dc"},{"file":"java.base","function":"java.util.HashMap.putVal(ILjava/lang/Object;Ljava/lang/Object;ZZ)Ljava/lang/Object;","relative_address":"0x0000000000000058"},{"file":"java.base","function":"java.util.HashSet.add(Ljava/lang/Object;)Z","relative_address":"0x000000000000014c"},{"function":"com.REDACT_THIS.util.dom.DOMUtil.doTransform(Lorg/w3c/dom/Node;Ljava/io/PrintStream;IZZZZZ)V","relative_address":"0x0000000000001c40"},{"function":"com.REDACT_THIS.util.dom.DOMUtil.doTransform(Lorg/w3c/dom/Node;Ljava/io/PrintStream;IZZZZZ)V","relative_address":"0x0000000000001ee8"},{"function":"com.REDACT_THIS.util.dom.DOMUtil.doTransform(Lorg/w3c/dom/Node;Ljava/io/PrintStream;IZZZZZ)V","relative_address":"0x0000000000001ee8"},{"function":"com.REDACT_THIS.util.dom.DOMUtil.doTransform(Lorg/w3c/dom/Node;Ljava/io/PrintStream;IZZZZZ)V","relative_address":"0x0000000000003524"},{"function":"com.REDACT_THIS.util.dom.DOMUtil.partToString(Lorg/w3c/dom/Node;)Ljava/lang/String;","relative_address":"0x00000000000003b8"},{"function":"com.REDACT_THIS.message.impl.MessagePartDOMExt.writeExternal(Ljava/io/ObjectOutput;)V","relative_address":"0x0000000000000114"},{"file":"java.base","function":"java.io.ObjectOutputStream.writeOrdinaryObject(Ljava/lang/Object;Ljava/io/ObjectStreamClass;Z)V","relative_address":"0x00000000000005c8"},{"file":"java.base","function":"java.io.ObjectOutputStream.writeObject0(Ljava/lang/Object;Z)V","relative_address":"0x0000000000000a04"},{"file":"java.base","function":"jdk.internal.reflect.GeneratedMethodAccessor173.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;","relative_address":"0x00000000000003d8"},{"file":"java.base","function":"java.io.ObjectOutputStream.writeSerialData(Ljava/lang/Object;Ljava/io/ObjectStreamClass;)V","relative_address":"0x0000000000000434"},{"file":"java.base","function":"java.io.ObjectOutputStream.writeOrdinaryObject(Ljava/lang/Object;Ljava/io/ObjectStreamClass;Z)V","relative_address":"0x0000000000000124"},{"file":"java.base","function":"java.io.ObjectOutputStream.writeObject0(Ljava/lang/Object;Z)V","relative_address":"0x0000000000000a04"},{"function":"com.REDACT_THIS.message.impl.Message.writeExternal(Ljava/io/ObjectOutput;)V","relative_address":"0x00000000000008c4"},{"function":"com.REDACT_THIS.xstream.converters.reflection.ExternalizableConverter.marshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x00000000000003dc"},{"function":"com.REDACT_THIS.xstream.core.TreeMarshaller.convertAnother(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/converters/Converter;)V","relative_address":"0x0000000000000a54"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshallField(Lcom/REDACT_THIS/xstream/converters/MarshallingContext;Ljava/lang/Object;Ljava/lang/reflect/Field;)V","relative_address":"0x00000000000000d0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter$2.writeField(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;)V","relative_address":"0x00000000000009c0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.doMarshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000430"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000354"},{"function":"com.REDACT_THIS.xstream.core.TreeMarshaller.convertAnother(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/converters/Converter;)V","relative_address":"0x0000000000000a54"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshallField(Lcom/REDACT_THIS/xstream/converters/MarshallingContext;Ljava/lang/Object;Ljava/lang/reflect/Field;)V","relative_address":"0x00000000000000d0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter$2.writeField(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;)V","relative_address":"0x00000000000009c0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.doMarshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000430"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000354"},{"function":"com.REDACT_THIS.xstream.core.TreeMarshaller.convertAnother(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/converters/Converter;)V","relative_address":"0x0000000000000a54"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshallField(Lcom/REDACT_THIS/xstream/converters/MarshallingContext;Ljava/lang/Object;Ljava/lang/reflect/Field;)V","relative_address":"0x00000000000000d0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter$2.writeField(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;)V","relative_address":"0x00000000000009c0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.doMarshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000430"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000354"},{"function":"com.REDACT_THIS.xstream.core.TreeMarshaller.convertAnother(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/converters/Converter;)V","relative_address":"0x0000000000000a54"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshallField(Lcom/REDACT_THIS/xstream/converters/MarshallingContext;Ljava/lang/Object;Ljava/lang/reflect/Field;)V","relative_address":"0x00000000000000d0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter$2.writeField(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;)V","relative_address":"0x00000000000009c0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.doMarshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000430"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000354"},{"function":"com.REDACT_THIS.xstream.core.TreeMarshaller.convertAnother(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/converters/Converter;)V","relative_address":"0x0000000000000a54"},{"function":"com.REDACT_THIS.xstream.XStream.toXML(Ljava/lang/Object;Ljava/io/OutputStream;)V","relative_address":"0x00000000000010d8"},{"function":"com.REDACT_THIS.recover.impl.fs.FSJobSerializer.serializeJob(Ljava/lang/String;Lcom/REDACT_THIS/recover/impl/GenericRecoveryJob;)V","relative_address":"0x00000000000010a4"},{"function":"com.REDACT_THIS.recover.impl.db.RecoveryPoolDBImpl.specificSave(Lcom/REDACT_THIS/recover/spi/RecoveryJob;)V","relative_address":"0x0000000000004208"},{"function":"com.REDACT_THIS.recover.impl.REDACT_THIS.saveJob(Lcom/REDACT_THIS/recover/spi/RecoveryJob;ILjava/lang/String;)V","relative_address":"0x0000000000000960"},{"function":"com.REDACT_THIS.frame.core.FrameWorkListener.callbackNewData(Lcom/REDACT_THIS/frame/header/GenericTask;Ljava/util/concurrent/ExecutorService;)V","relative_address":"0x0000000000000f10"},{"function":"com.REDACT_THIS.frame.connection.direct.DirectModeMessageListener.onMessage(Ljavax/jms/Message;)V","relative_address":"0x0000000000001a34"},{"function":"datadog.trace.instrumentation.jms.DatadogMessageListener.onMessage(Ljavax/jms/Message;)V","relative_address":"0x0000000000000440"},{"function":"org.apache.activemq.artemis.jms.client.JMSMessageListenerWrapper.onMessage(Lorg/apache/activemq/artemis/api/core/client/ClientMessage;)V","relative_address":"0x0000000000000908"},{"function":"org.apache.activemq.artemis.core.client.impl.ClientConsumerImpl$Runner.run()V","relative_address":"0x0000000000001018"},{"function":"org.apache.activemq.artemis.utils.actors.ProcessorBase$$Lambda$2929+0x00000007ce44f8f8.run()V","relative_address":"0x00000000000002b4"},{"file":"java.base","function":"java.util.concurrent.ThreadPoolExecutor.runWorker(Ljava/util/concurrent/ThreadPoolExecutor$Worker;)V","relative_address":"0x0000000000000368"},{"file":"java.base","function":"java.util.concurrent.ThreadPoolExecutor$Worker.run()V","relative_address":"0x0000000000000078"},{"function":"org.apache.activemq.artemis.utils.ActiveMQThreadFactory$1.run()V","line":44},{"function":"~StubRoutines::call_stub"}]}},"sig_info":{"si_addr":"0x0000000000000070","si_signo_human_readable":"SIGSEGV","si_signo":11}} diff --git a/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample_oom.txt b/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample_oom.txt index aec5691b6af..dac59403b14 100644 --- a/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample_oom.txt +++ b/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample_oom.txt @@ -1 +1 @@ -{"timestamp":"2025-11-24T09:43:29+01:00","ddsource":"crashtracker","error":{"is_crash":true,"type":"OutOfMemory","message":"Java heap space","source_type":"crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"file":"libjvm.dylib","function":"VMError::report_and_die(int, char const*, char const*, char*, Thread*, unsigned char*, void*, void*, char const*, int, unsigned long)"},{"file":"libjvm.dylib","function":"report_fatal(VMErrorType, char const*, int, char const*, ...)"},{"file":"libjvm.dylib","function":"report_java_out_of_memory(char const*)"},{"file":"libjvm.dylib","function":"MemAllocator::Allocation::check_out_of_memory()"},{"file":"libjvm.dylib","function":"MemAllocator::allocate() const"},{"file":"libjvm.dylib","function":"CollectedHeap::array_allocate(Klass*, unsigned long, int, bool, JavaThread*)"},{"file":"libjvm.dylib","function":"OptoRuntime::new_array_C(Klass*, int, JavaThread*)"},{"function":"Java"},{"function":" ~RuntimeStub::_new_array_Java 0x00000001124cb638"},{"function":"java.nio.ByteBuffer.allocate(I)Ljava/nio/ByteBuffer;"},{"function":"datadog.communication.serialization.FlushingBuffer.(ILdatadog/communication/serialization/ByteBufferConsumer;)V","line":6},{"function":"datadog.trace.agent.common.writer.PayloadDispatcherImpl.selectMapper()V","line":126},{"function":"datadog.trace.agent.common.writer.PayloadDispatcherImpl.addTrace(Ljava/util/List;)V","line":1},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.onEvent(Ljava/lang/Object;)V","line":22},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.consumeFromPrimaryQueue()V","line":21},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.runDutyCycle()V","line":12},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.run()V","line":1},{"function":"java.lang.Thread.runWith(Ljava/lang/Object;Ljava/lang/Runnable;)V"},{"function":"java.lang.Thread.run()V"},{"function":" ~StubRoutines::call_stub 0x00000001123b0140"}]}}} +{"timestamp":"2025-11-24T09:43:29+01:00","ddsource":"crashtracker","error":{"is_crash":true,"type":"OutOfMemory","message":"Java heap space","source_type":"crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"file":"libjvm.dylib","function":"VMError::report_and_die(int, char const*, char const*, char*, Thread*, unsigned char*, void*, void*, char const*, int, unsigned long)","relative_address":"0xaa5f24"},{"file":"libjvm.dylib","function":"report_fatal(VMErrorType, char const*, int, char const*, ...)","relative_address":"0x314c74"},{"file":"libjvm.dylib","function":"report_java_out_of_memory(char const*)","relative_address":"0x315248"},{"file":"libjvm.dylib","function":"MemAllocator::Allocation::check_out_of_memory()","relative_address":"0x7d9764"},{"file":"libjvm.dylib","function":"MemAllocator::allocate() const","relative_address":"0x7da2f4"},{"file":"libjvm.dylib","function":"CollectedHeap::array_allocate(Klass*, unsigned long, int, bool, JavaThread*)","relative_address":"0x2c3de4"},{"file":"libjvm.dylib","function":"OptoRuntime::new_array_C(Klass*, int, JavaThread*)","relative_address":"0x8ea9ec"},{"function":"~RuntimeStub::_new_array_Java","relative_address":"0x00000001124cb638"},{"file":"java.base","function":"java.nio.ByteBuffer.allocate(I)Ljava/nio/ByteBuffer;","relative_address":"0x0000000000000228"},{"function":"datadog.communication.serialization.FlushingBuffer.(ILdatadog/communication/serialization/ByteBufferConsumer;)V","line":6},{"function":"datadog.trace.agent.common.writer.PayloadDispatcherImpl.selectMapper()V","line":126},{"function":"datadog.trace.agent.common.writer.PayloadDispatcherImpl.addTrace(Ljava/util/List;)V","line":1},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.onEvent(Ljava/lang/Object;)V","line":22},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.consumeFromPrimaryQueue()V","line":21},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.runDutyCycle()V","line":12},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.run()V","line":1},{"function":"java.lang.Thread.runWith(Ljava/lang/Object;Ljava/lang/Runnable;)V"},{"function":"java.lang.Thread.run()V"},{"function":"~StubRoutines::call_stub","relative_address":"0x00000001123b0140"}]}}} ==> expected: <{data_schema_version=1.0, error={is_crash=true, kind=OutOfMemory, message=Java heap space, source_type=crashtracking, stack={format=CrashTrackerV1, frames=[{file=libjvm.dylib, function=VMError::report_and_die(int, char const*, char const*, char*, Thread*, unsigned char*, void*, void*, char const*, int, unsigned long), relative_address=0xaa5f24}, {file=libjvm.dylib, function=report_fatal(VMErrorType, char const*, int, char const*, ...), relative_address=0x314c74}, {file=libjvm.dylib, function=report_java_out_of_memory(char const*), relative_address=0x315248}, {file=libjvm.dylib, function=MemAllocator::Allocation::check_out_of_memory(), relative_address=0x7d9764}, {file=libjvm.dylib, function=MemAllocator::allocate() const, relative_address=0x7da2f4}, {file=libjvm.dylib, function=CollectedHeap::array_allocate(Klass*, unsigned long, int, bool, JavaThread*), relative_address=0x2c3de4}, {file=libjvm.dylib, function=OptoRuntime::new_array_C(Klass*, int, JavaThread*), relative_address=0x8ea9ec}, {function=~RuntimeStub::_new_array_Java, relative_address=0x00000001124cb638}, {file=java.base, function=java.nio.ByteBuffer.allocate(I)Ljava/nio/ByteBuffer;, relative_address=0x0000000000000228}, {function=datadog.communication.serialization.FlushingBuffer.(ILdatadog/communication/serialization/ByteBufferConsumer;)V, line=6}, {function=datadog.trace.agent.common.writer.PayloadDispatcherImpl.selectMapper()V, line=126}, {function=datadog.trace.agent.common.writer.PayloadDispatcherImpl.addTrace(Ljava/util/List;)V, line=1}, {function=datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.onEvent(Ljava/lang/Object;)V, line=22}, {function=datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.consumeFromPrimaryQueue()V, line=21}, {function=datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.runDutyCycle()V, line=12}, {function=datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.run()V, line=1}, {function=java.lang.Thread.runWith(Ljava/lang/Object;Ljava/lang/Runnable;)V}, {function=java.lang.Thread.run()V}, {function=~StubRoutines::call_stub, relative_address=0x00000001123b0140}]}}, incomplete=false, metadata={family=java, library_name=dd-trace-java, library_version=1.59.0-SNAPSHOT~83d60598da}, proc_info={pid=74045}, timestamp=2025-11-24T09:43:29+01:00, uuid=a4194cd6-8cb3-45fd-9bd9-3af83e0a3ad3, version_id=0}> but was: <{timestamp=2025-11-24T09:43:29+01:00, ddsource=crashtracker, error={is_crash=true, type=OutOfMemory, message=Java heap space, source_type=crashtracking, stack={format=CrashTrackerV1, frames=[{file=libjvm.dylib, function=VMError::report_and_die(int, char const*, char const*, char*, Thread*, unsigned char*, void*, void*, char const*, int, unsigned long), relative_address=0xaa5f24}, {file=libjvm.dylib, function=report_fatal(VMErrorType, char const*, int, char const*, ...), relative_address=0x314c74}, {file=libjvm.dylib, function=report_java_out_of_memory(char const*), relative_address=0x315248}, {file=libjvm.dylib, function=MemAllocator::Allocation::check_out_of_memory(), relative_address=0x7d9764}, {file=libjvm.dylib, function=MemAllocator::allocate() const, relative_address=0x7da2f4}, {file=libjvm.dylib, function=CollectedHeap::array_allocate(Klass*, unsigned long, int, bool, JavaThread*), relative_address=0x2c3de4}, {file=libjvm.dylib, function=OptoRuntime::new_array_C(Klass*, int, JavaThread*), relative_address=0x8ea9ec}, {function=~RuntimeStub::_new_array_Java, relative_address=0x00000001124cb638}, {file=java.base, function=java.nio.ByteBuffer.allocate(I)Ljava/nio/ByteBuffer;, relative_address=0x0000000000000228}, {function=datadog.communication.serialization.FlushingBuffer.(ILdatadog/communication/serialization/ByteBufferConsumer;)V, line=6}, {function=datadog.trace.agent.common.writer.PayloadDispatcherImpl.selectMapper()V, line=126}, {function=datadog.trace.agent.common.writer.PayloadDispatcherImpl.addTrace(Ljava/util/List;)V, line=1}, {function=datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.onEvent(Ljava/lang/Object;)V, line=22}, {function=datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.consumeFromPrimaryQueue()V, line=21}, {function=datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.runDutyCycle()V, line=12}, {function=datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.run()V, line=1}, {function=java.lang.Thread.runWith(Ljava/lang/Object;Ljava/lang/Runnable;)V}, {function=java.lang.Thread.run()V}, {function=~StubRoutines::call_stub, relative_address=0x00000001123b0140}]}}} diff --git a/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample-crash-for-telemetry-2.txt b/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample-crash-for-telemetry-2.txt index 4e8611fc812..fce0f8ca696 100644 --- a/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample-crash-for-telemetry-2.txt +++ b/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample-crash-for-telemetry-2.txt @@ -1 +1 @@ -{"data_schema_version":"1.0","error":{"is_crash":true,"kind":"SIGSEGV","message":"Process terminated by signal SIGSEGV","source_type":"crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"file":"libpthread.so.0","function":"__pthread_clockjoin_ex"}]}},"incomplete":false,"metadata":{"family":"java","library_name":"dd-trace-java","library_version":"1.57.0-SNAPSHOT~0882768757"},"os_info":{"architecture":"aarch64","bitness":"64","os_type":"Mac OS X","version":{"Semantic":[15,7,1]}},"proc_info":{"pid":"576034"},"sig_info":{"address":"0x00007f011ab1ccd5 (sent by kill)","name":"SIGSEGV","number":11},"timestamp":"2024-09-20T13:19:06Z","uuid":"a4194cd6-8cb3-45fd-9bd9-3af83e0a3ad3","version_id":0} +{"data_schema_version":"1.0","error":{"is_crash":true,"kind":"UNKNOWN","message":"Process terminated by signal UNKNOWN","source_type":"Crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"file":"libpthread.so.0","function":"__pthread_clockjoin_ex","relative_address":"0x9cd5"}]}},"incomplete":false,"metadata":{"family":"java","library_name":"dd-trace-java","library_version":"1.59.0-SNAPSHOT~83d60598da"},"os_info":{"architecture":"aarch64","bitness":"64","os_type":"Mac OS X","version":{"Semantic":[15,7,1]}},"proc_info":{"pid":576034},"timestamp":"2024-09-20T13:19:06Z","uuid":"a4194cd6-8cb3-45fd-9bd9-3af83e0a3ad3","version_id":0} diff --git a/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample-crash-for-telemetry-3.txt b/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample-crash-for-telemetry-3.txt index d0303a8c863..99328e14792 100644 --- a/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample-crash-for-telemetry-3.txt +++ b/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample-crash-for-telemetry-3.txt @@ -1 +1 @@ -{"data_schema_version":"1.0","error":{"is_crash":true,"kind":"OutOfMemory","message":"Java heap space","source_type":"crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"file":"libjvm.dylib","function":"VMError::report_and_die()"},{"file":"libjvm.dylib","function":"report_vm_error(char const*, int, char const*, char const*)"},{"file":"libjvm.dylib","function":"report_java_out_of_memory(char const*)"},{"file":"libjvm.dylib","function":"CollectedHeap::common_mem_allocate_noinit(KlassHandle, unsigned long, Thread*)"},{"file":"libjvm.dylib","function":"TypeArrayKlass::allocate_common(int, bool, Thread*)"},{"file":"libjvm.dylib","function":"InterpreterRuntime::newarray(JavaThread*, BasicType, int)"},{"function":"datadog.smoketest.crashtracking.CrashtrackingTestApplication.main([Ljava/lang/String;)V","line":105},{"function":" ~StubRoutines::call_stub"},{"file":"libjvm.dylib","function":"JavaCalls::call_helper(JavaValue*, methodHandle*, JavaCallArguments*, Thread*)"},{"file":"libjvm.dylib","function":"jni_invoke_static(JNIEnv_*, JavaValue*, _jobject*, JNICallType, _jmethodID*, JNI_ArgumentPusher*, Thread*)"},{"file":"libjvm.dylib","function":"jni_CallStaticVoidMethod"},{"file":"java","function":"JavaMain"},{"file":"libsystem_pthread.dylib","function":"_pthread_start"},{"file":"libsystem_pthread.dylib","function":"thread_start"}]}},"incomplete":false,"metadata":{"family":"java","library_name":"dd-trace-java","library_version":"1.57.0-SNAPSHOT~2563480753"},"os_info":{"architecture":"aarch64","bitness":"64","os_type":"Mac OS X","version":{"Semantic":[15,7,1]}},"proc_info":{"pid":"96267"},"sig_info":{"address":"0x0000000000000000","name":"INVALID","number":0},"uuid":"a4194cd6-8cb3-45fd-9bd9-3af83e0a3ad3","version_id":0} +{"data_schema_version":"1.0","error":{"is_crash":true,"kind":"OutOfMemory","message":"Java heap space","source_type":"Crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"file":"libjvm.dylib","function":"VMError::report_and_die()","relative_address":"0x565d30"},{"file":"libjvm.dylib","function":"report_vm_error(char const*, int, char const*, char const*)","relative_address":"0x1941a0"},{"file":"libjvm.dylib","function":"report_java_out_of_memory(char const*)","relative_address":"0x1943d8"},{"file":"libjvm.dylib","function":"CollectedHeap::common_mem_allocate_noinit(KlassHandle, unsigned long, Thread*)","relative_address":"0x70430"},{"file":"libjvm.dylib","function":"TypeArrayKlass::allocate_common(int, bool, Thread*)","relative_address":"0x53eba8"},{"file":"libjvm.dylib","function":"InterpreterRuntime::newarray(JavaThread*, BasicType, int)","relative_address":"0x285b6c"},{"function":"datadog.smoketest.crashtracking.CrashtrackingTestApplication.main([Ljava/lang/String;)V","line":105},{"function":"~StubRoutines::call_stub"},{"file":"libjvm.dylib","function":"JavaCalls::call_helper(JavaValue*, methodHandle*, JavaCallArguments*, Thread*)","relative_address":"0x28f86c"},{"file":"libjvm.dylib","function":"jni_invoke_static(JNIEnv_*, JavaValue*, _jobject*, JNICallType, _jmethodID*, JNI_ArgumentPusher*, Thread*)","relative_address":"0x2d3b44"},{"file":"libjvm.dylib","function":"jni_CallStaticVoidMethod","relative_address":"0x2d7160"},{"file":"java","function":"JavaMain","relative_address":"0x6404"},{"file":"libsystem_pthread.dylib","function":"_pthread_start","relative_address":"0x6f94"},{"file":"libsystem_pthread.dylib","function":"thread_start","relative_address":"0x1d34"},{"function":"datadog.smoketest.crashtracking.CrashtrackingTestApplication.main([Ljava/lang/String;)V","line":105},{"function":"~StubRoutines::call_stub"}]}},"incomplete":false,"metadata":{"family":"java","library_name":"dd-trace-java","library_version":"1.59.0-SNAPSHOT~83d60598da"},"os_info":{"architecture":"aarch64","bitness":"64","os_type":"Mac OS X","version":{"Semantic":[15,7,1]}},"proc_info":{"pid":96267},"uuid":"a4194cd6-8cb3-45fd-9bd9-3af83e0a3ad3","version_id":0} diff --git a/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample-crash-for-telemetry.txt b/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample-crash-for-telemetry.txt index 4532e28e72d..9ea048bda6c 100644 --- a/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample-crash-for-telemetry.txt +++ b/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample-crash-for-telemetry.txt @@ -1 +1 @@ -{"data_schema_version":"1.0","error":{"is_crash":true,"kind":"SIGSEGV","message":"Process terminated by signal SIGSEGV","source_type":"crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"file":"libjvm.so","function":"vframeStreamForte::forte_next()"},{"file":"libjvm.so","function":"forte_fill_call_trace_given_top(JavaThread*, ASGCT_CallTrace*, int, frame) [clone .isra.22]"},{"file":"libjvm.so","function":"AsyncGetCallTrace"},{"file":"libjavaProfiler.so","function":"Profiler::getJavaTraceAsync(void*, ASGCT_CallFrame*, int, StackContext*, bool*) [clone .isra.531]"},{"file":"libjavaProfiler.so","function":"Profiler::recordSample(void*, unsigned long long, int, int, Event*)"},{"file":"libjavaProfiler.so","function":"WallClock::sharedSignalHandler(int, siginfo_t*, void*)"},{"file":"libpthread.so.0","function":"libpthread.so.0+0x12cf0"},{"file":"libjvm.so","function":"JfrStackTrace::record_safe(JavaThread*, int)"},{"file":"libjvm.so","function":"JfrStackTraceRepository::record_for_leak_profiler(JavaThread*, int)"},{"file":"libjvm.so","function":"ObjectSampler::sample(HeapWordImpl**, unsigned long, JavaThread*)"},{"file":"libjvm.so","function":"JfrAllocationTracer::JfrAllocationTracer(Klass const*, HeapWordImpl**, unsigned long, bool, JavaThread*)"},{"file":"libjvm.so","function":"AllocTracer::send_allocation_in_new_tlab(Klass*, HeapWordImpl**, unsigned long, unsigned long, JavaThread*)"},{"file":"libjvm.so","function":"MemAllocator::allocate() const"},{"file":"libjvm.so","function":"InstanceKlass::allocate_objArray(int, int, JavaThread*)"},{"file":"libjvm.so","function":"OptoRuntime::new_array_C(Klass*, int, JavaThread*)"}]}},"incomplete":false,"metadata":{"family":"java","library_name":"dd-trace-java","library_version":"1.59.0-SNAPSHOT~645ed325fc"},"os_info":{"architecture":"aarch64","bitness":"64","os_type":"Mac OS X","version":{"Semantic":[15,7,1]}},"proc_info":{"pid":"161958"},"sig_info":{"address":"0x00007f37a18bc187","name":"SIGSEGV","number":11},"timestamp":"2023-10-17T20:25:14+08:00","uuid":"a4194cd6-8cb3-45fd-9bd9-3af83e0a3ad3","version_id":0} +{"data_schema_version":"1.0","error":{"is_crash":true,"kind":"SIGSEGV","message":"Process terminated by signal SIGSEGV","source_type":"Crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"file":"libjvm.so","function":"vframeStreamForte::forte_next()","relative_address":"0x6b7187"},{"file":"libjvm.so","function":"forte_fill_call_trace_given_top(JavaThread*, ASGCT_CallTrace*, int, frame)","relative_address":"0x6b79ad"},{"file":"libjvm.so","function":"AsyncGetCallTrace","relative_address":"0x6b8123"},{"file":"libjavaProfiler.so","function":"Profiler::getJavaTraceAsync(void*, ASGCT_CallFrame*, int, StackContext*, bool*)","relative_address":"0x146c8"},{"file":"libjavaProfiler.so","function":"Profiler::recordSample(void*, unsigned long long, int, int, Event*)","relative_address":"0x1c18d"},{"file":"libjavaProfiler.so","function":"WallClock::sharedSignalHandler(int, siginfo_t*, void*)","relative_address":"0x1d128"},{"file":"libpthread.so.0","relative_address":"0x12cf0"},{"file":"libjvm.so","function":"JfrStackTrace::record_safe(JavaThread*, int)","relative_address":"0x85f9e9"},{"file":"libjvm.so","function":"JfrStackTraceRepository::record_for_leak_profiler(JavaThread*, int)","relative_address":"0x861650"},{"file":"libjvm.so","function":"ObjectSampler::sample(HeapWordImpl**, unsigned long, JavaThread*)","relative_address":"0xb1ecba"},{"file":"libjvm.so","function":"JfrAllocationTracer::JfrAllocationTracer(Klass const*, HeapWordImpl**, unsigned long, bool, JavaThread*)","relative_address":"0x81abee"},{"file":"libjvm.so","function":"AllocTracer::send_allocation_in_new_tlab(Klass*, HeapWordImpl**, unsigned long, unsigned long, JavaThread*)","relative_address":"0x3afa20"},{"file":"libjvm.so","function":"MemAllocator::allocate() const","relative_address":"0xa8f8ed"},{"file":"libjvm.so","function":"InstanceKlass::allocate_objArray(int, int, JavaThread*)","relative_address":"0x7e443c"},{"file":"libjvm.so","function":"OptoRuntime::new_array_C(Klass*, int, JavaThread*)","relative_address":"0xbe1b59"},{"function":"~RuntimeStub::_new_array_Java"},{"file":"java.base","function":"java.util.HashMap.resize()[Ljava/util/HashMap$Node;","relative_address":"0x00000000000008dc"},{"file":"java.base","function":"java.util.HashMap.putVal(ILjava/lang/Object;Ljava/lang/Object;ZZ)Ljava/lang/Object;","relative_address":"0x0000000000000058"},{"file":"java.base","function":"java.util.HashSet.add(Ljava/lang/Object;)Z","relative_address":"0x000000000000014c"},{"function":"com.REDACT_THIS.util.dom.DOMUtil.doTransform(Lorg/w3c/dom/Node;Ljava/io/PrintStream;IZZZZZ)V","relative_address":"0x0000000000001c40"},{"function":"com.REDACT_THIS.util.dom.DOMUtil.doTransform(Lorg/w3c/dom/Node;Ljava/io/PrintStream;IZZZZZ)V","relative_address":"0x0000000000001ee8"},{"function":"com.REDACT_THIS.util.dom.DOMUtil.doTransform(Lorg/w3c/dom/Node;Ljava/io/PrintStream;IZZZZZ)V","relative_address":"0x0000000000001ee8"},{"function":"com.REDACT_THIS.util.dom.DOMUtil.doTransform(Lorg/w3c/dom/Node;Ljava/io/PrintStream;IZZZZZ)V","relative_address":"0x0000000000003524"},{"function":"com.REDACT_THIS.util.dom.DOMUtil.partToString(Lorg/w3c/dom/Node;)Ljava/lang/String;","relative_address":"0x00000000000003b8"},{"function":"com.REDACT_THIS.message.impl.MessagePartDOMExt.writeExternal(Ljava/io/ObjectOutput;)V","relative_address":"0x0000000000000114"},{"file":"java.base","function":"java.io.ObjectOutputStream.writeOrdinaryObject(Ljava/lang/Object;Ljava/io/ObjectStreamClass;Z)V","relative_address":"0x00000000000005c8"},{"file":"java.base","function":"java.io.ObjectOutputStream.writeObject0(Ljava/lang/Object;Z)V","relative_address":"0x0000000000000a04"},{"file":"java.base","function":"jdk.internal.reflect.GeneratedMethodAccessor173.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;","relative_address":"0x00000000000003d8"},{"file":"java.base","function":"java.io.ObjectOutputStream.writeSerialData(Ljava/lang/Object;Ljava/io/ObjectStreamClass;)V","relative_address":"0x0000000000000434"},{"file":"java.base","function":"java.io.ObjectOutputStream.writeOrdinaryObject(Ljava/lang/Object;Ljava/io/ObjectStreamClass;Z)V","relative_address":"0x0000000000000124"},{"file":"java.base","function":"java.io.ObjectOutputStream.writeObject0(Ljava/lang/Object;Z)V","relative_address":"0x0000000000000a04"},{"function":"com.REDACT_THIS.message.impl.Message.writeExternal(Ljava/io/ObjectOutput;)V","relative_address":"0x00000000000008c4"},{"function":"com.REDACT_THIS.xstream.converters.reflection.ExternalizableConverter.marshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x00000000000003dc"},{"function":"com.REDACT_THIS.xstream.core.TreeMarshaller.convertAnother(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/converters/Converter;)V","relative_address":"0x0000000000000a54"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshallField(Lcom/REDACT_THIS/xstream/converters/MarshallingContext;Ljava/lang/Object;Ljava/lang/reflect/Field;)V","relative_address":"0x00000000000000d0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter$2.writeField(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;)V","relative_address":"0x00000000000009c0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.doMarshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000430"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000354"},{"function":"com.REDACT_THIS.xstream.core.TreeMarshaller.convertAnother(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/converters/Converter;)V","relative_address":"0x0000000000000a54"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshallField(Lcom/REDACT_THIS/xstream/converters/MarshallingContext;Ljava/lang/Object;Ljava/lang/reflect/Field;)V","relative_address":"0x00000000000000d0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter$2.writeField(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;)V","relative_address":"0x00000000000009c0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.doMarshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000430"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000354"},{"function":"com.REDACT_THIS.xstream.core.TreeMarshaller.convertAnother(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/converters/Converter;)V","relative_address":"0x0000000000000a54"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshallField(Lcom/REDACT_THIS/xstream/converters/MarshallingContext;Ljava/lang/Object;Ljava/lang/reflect/Field;)V","relative_address":"0x00000000000000d0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter$2.writeField(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;)V","relative_address":"0x00000000000009c0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.doMarshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000430"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000354"},{"function":"com.REDACT_THIS.xstream.core.TreeMarshaller.convertAnother(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/converters/Converter;)V","relative_address":"0x0000000000000a54"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshallField(Lcom/REDACT_THIS/xstream/converters/MarshallingContext;Ljava/lang/Object;Ljava/lang/reflect/Field;)V","relative_address":"0x00000000000000d0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter$2.writeField(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;)V","relative_address":"0x00000000000009c0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.doMarshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000430"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000354"},{"function":"com.REDACT_THIS.xstream.core.TreeMarshaller.convertAnother(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/converters/Converter;)V","relative_address":"0x0000000000000a54"},{"function":"com.REDACT_THIS.xstream.XStream.toXML(Ljava/lang/Object;Ljava/io/OutputStream;)V","relative_address":"0x00000000000010d8"},{"function":"com.REDACT_THIS.recover.impl.fs.FSJobSerializer.serializeJob(Ljava/lang/String;Lcom/REDACT_THIS/recover/impl/GenericRecoveryJob;)V","relative_address":"0x00000000000010a4"},{"function":"com.REDACT_THIS.recover.impl.db.RecoveryPoolDBImpl.specificSave(Lcom/REDACT_THIS/recover/spi/RecoveryJob;)V","relative_address":"0x0000000000004208"},{"function":"com.REDACT_THIS.recover.impl.REDACT_THIS.saveJob(Lcom/REDACT_THIS/recover/spi/RecoveryJob;ILjava/lang/String;)V","relative_address":"0x0000000000000960"},{"function":"com.REDACT_THIS.frame.core.FrameWorkListener.callbackNewData(Lcom/REDACT_THIS/frame/header/GenericTask;Ljava/util/concurrent/ExecutorService;)V","relative_address":"0x0000000000000f10"},{"function":"com.REDACT_THIS.frame.connection.direct.DirectModeMessageListener.onMessage(Ljavax/jms/Message;)V","relative_address":"0x0000000000001a34"},{"function":"datadog.trace.instrumentation.jms.DatadogMessageListener.onMessage(Ljavax/jms/Message;)V","relative_address":"0x0000000000000440"},{"function":"org.apache.activemq.artemis.jms.client.JMSMessageListenerWrapper.onMessage(Lorg/apache/activemq/artemis/api/core/client/ClientMessage;)V","relative_address":"0x0000000000000908"},{"function":"org.apache.activemq.artemis.core.client.impl.ClientConsumerImpl$Runner.run()V","relative_address":"0x0000000000001018"},{"function":"org.apache.activemq.artemis.utils.actors.ProcessorBase$$Lambda$2929+0x00000007ce44f8f8.run()V","relative_address":"0x00000000000002b4"},{"file":"java.base","function":"java.util.concurrent.ThreadPoolExecutor.runWorker(Ljava/util/concurrent/ThreadPoolExecutor$Worker;)V","relative_address":"0x0000000000000368"},{"file":"java.base","function":"java.util.concurrent.ThreadPoolExecutor$Worker.run()V","relative_address":"0x0000000000000078"},{"function":"org.apache.activemq.artemis.utils.ActiveMQThreadFactory$1.run()V","line":44},{"function":"~StubRoutines::call_stub"}]}},"incomplete":false,"metadata":{"family":"java","library_name":"dd-trace-java","library_version":"1.59.0-SNAPSHOT~83d60598da"},"os_info":{"architecture":"aarch64","bitness":"64","os_type":"Mac OS X","version":{"Semantic":[15,7,1]}},"proc_info":{"pid":161958},"sig_info":{"si_addr":"0x0000000000000070","si_code":1,"si_code_human_readable":"SEGV_MAPERR","si_signo":11,"si_signo_human_readable":"SIGSEGV"},"timestamp":"2023-10-17T20:25:14+08:00","uuid":"a4194cd6-8cb3-45fd-9bd9-3af83e0a3ad3","version_id":0} diff --git a/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample_oom.txt b/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample_oom.txt index 3f9791eff17..2721d566a58 100644 --- a/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample_oom.txt +++ b/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample_oom.txt @@ -1 +1 @@ -{"data_schema_version":"1.0","error":{"is_crash":true,"kind":"OutOfMemory","message":"Java heap space","source_type":"crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"file":"libjvm.dylib","function":"VMError::report_and_die(int, char const*, char const*, char*, Thread*, unsigned char*, void*, void*, char const*, int, unsigned long)"},{"file":"libjvm.dylib","function":"report_fatal(VMErrorType, char const*, int, char const*, ...)"},{"file":"libjvm.dylib","function":"report_java_out_of_memory(char const*)"},{"file":"libjvm.dylib","function":"MemAllocator::Allocation::check_out_of_memory()"},{"file":"libjvm.dylib","function":"MemAllocator::allocate() const"},{"file":"libjvm.dylib","function":"CollectedHeap::array_allocate(Klass*, unsigned long, int, bool, JavaThread*)"},{"file":"libjvm.dylib","function":"OptoRuntime::new_array_C(Klass*, int, JavaThread*)"},{"function":"Java"},{"function":" ~RuntimeStub::_new_array_Java 0x00000001124cb638"},{"function":"java.nio.ByteBuffer.allocate(I)Ljava/nio/ByteBuffer;"},{"function":"datadog.communication.serialization.FlushingBuffer.(ILdatadog/communication/serialization/ByteBufferConsumer;)V","line":6},{"function":"datadog.trace.agent.common.writer.PayloadDispatcherImpl.selectMapper()V","line":126},{"function":"datadog.trace.agent.common.writer.PayloadDispatcherImpl.addTrace(Ljava/util/List;)V","line":1},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.onEvent(Ljava/lang/Object;)V","line":22},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.consumeFromPrimaryQueue()V","line":21},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.runDutyCycle()V","line":12},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.run()V","line":1},{"function":"java.lang.Thread.runWith(Ljava/lang/Object;Ljava/lang/Runnable;)V"},{"function":"java.lang.Thread.run()V"},{"function":" ~StubRoutines::call_stub 0x00000001123b0140"}]}},"incomplete":false,"metadata":{"family":"java","library_name":"dd-trace-java","library_version":"1.57.0-SNAPSHOT~0882768757"},"os_info":{"architecture":"aarch64","bitness":"64","os_type":"Mac OS X","version":{"Semantic":[15,7,1]}},"proc_info":{"pid":"74045"},"timestamp":"2025-11-24T09:43:29+01:00","uuid":"a4194cd6-8cb3-45fd-9bd9-3af83e0a3ad3","version_id":0} +{"data_schema_version":"1.0","error":{"is_crash":true,"kind":"OutOfMemory","message":"Java heap space","source_type":"Crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"file":"libjvm.dylib","function":"VMError::report_and_die(int, char const*, char const*, char*, Thread*, unsigned char*, void*, void*, char const*, int, unsigned long)","relative_address":"0xaa5f24"},{"file":"libjvm.dylib","function":"report_fatal(VMErrorType, char const*, int, char const*, ...)","relative_address":"0x314c74"},{"file":"libjvm.dylib","function":"report_java_out_of_memory(char const*)","relative_address":"0x315248"},{"file":"libjvm.dylib","function":"MemAllocator::Allocation::check_out_of_memory()","relative_address":"0x7d9764"},{"file":"libjvm.dylib","function":"MemAllocator::allocate() const","relative_address":"0x7da2f4"},{"file":"libjvm.dylib","function":"CollectedHeap::array_allocate(Klass*, unsigned long, int, bool, JavaThread*)","relative_address":"0x2c3de4"},{"file":"libjvm.dylib","function":"OptoRuntime::new_array_C(Klass*, int, JavaThread*)","relative_address":"0x8ea9ec"},{"function":"~RuntimeStub::_new_array_Java","relative_address":"0x00000001124cb638"},{"file":"java.base","function":"java.nio.ByteBuffer.allocate(I)Ljava/nio/ByteBuffer;","relative_address":"0x0000000000000228"},{"function":"datadog.communication.serialization.FlushingBuffer.(ILdatadog/communication/serialization/ByteBufferConsumer;)V","line":6},{"function":"datadog.trace.agent.common.writer.PayloadDispatcherImpl.selectMapper()V","line":126},{"function":"datadog.trace.agent.common.writer.PayloadDispatcherImpl.addTrace(Ljava/util/List;)V","line":1},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.onEvent(Ljava/lang/Object;)V","line":22},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.consumeFromPrimaryQueue()V","line":21},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.runDutyCycle()V","line":12},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.run()V","line":1},{"function":"java.lang.Thread.runWith(Ljava/lang/Object;Ljava/lang/Runnable;)V"},{"function":"java.lang.Thread.run()V"},{"function":"~StubRoutines::call_stub","relative_address":"0x00000001123b0140"}]}},"incomplete":false,"metadata":{"family":"java","library_name":"dd-trace-java","library_version":"1.59.0-SNAPSHOT~4661a03cdb"},"os_info":{"architecture":"aarch64","bitness":"64","os_type":"Mac OS X","version":{"Semantic":[15,7,1]}},"proc_info":{"pid":74045},"timestamp":"2025-11-24T09:43:29+01:00","uuid":"a4194cd6-8cb3-45fd-9bd9-3af83e0a3ad3","version_id":0} From 8b0ecd6995fea0a9eae622eb4d78f7b891ef32aa Mon Sep 17 00:00:00 2001 From: Andrea Marziali Date: Thu, 29 Jan 2026 15:35:55 +0100 Subject: [PATCH 2/4] spotbugs --- .../buildid/ElfBuildIdExtractor.java | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/ElfBuildIdExtractor.java b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/ElfBuildIdExtractor.java index d22e354c2df..8aef786e04c 100644 --- a/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/ElfBuildIdExtractor.java +++ b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/ElfBuildIdExtractor.java @@ -147,14 +147,21 @@ private String parseNoteSegment( // Read note name byte[] name = new byte[namesz]; - raf.read(name); - raf.skipBytes(nameLen - namesz); + if (raf.read(name) != namesz) { + throw new IOException("Failed to read note name"); + } + int skipped = raf.skipBytes(nameLen - namesz); + if (skipped != nameLen - namesz) { + throw new IOException("Failed to skip padding after note name"); + } // Check if this is the GNU build ID note if (type == NT_GNU_BUILD_ID && Arrays.equals(name, GNU_NOTE_NAME)) { // Read build ID byte[] buildIdBytes = new byte[descsz]; - raf.read(buildIdBytes); + if (raf.read(buildIdBytes) != descsz) { + throw new IOException("Failed to read build ID"); + } // Convert to hex string StringBuilder hex = new StringBuilder(descsz * 2); @@ -164,7 +171,10 @@ private String parseNoteSegment( return hex.toString(); } else { // Skip descriptor - raf.skipBytes(descLen); + skipped = raf.skipBytes(descLen); + if (skipped != descLen) { + throw new IOException("Failed to skip descriptor"); + } } } return null; From 896c1ad9866829c41fc55dd4d8ab9651ede12b0e Mon Sep 17 00:00:00 2001 From: Andrea Marziali Date: Fri, 30 Jan 2026 09:21:07 +0100 Subject: [PATCH 3/4] Add timeout to the build_id collecting thread --- .../crashtracking/buildid/BuildIdCollector.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/BuildIdCollector.java b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/BuildIdCollector.java index ee5749aaf91..a1d754ac67d 100644 --- a/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/BuildIdCollector.java +++ b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/buildid/BuildIdCollector.java @@ -11,6 +11,7 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.LockSupport; import org.jctools.queues.MessagePassingQueue; @@ -29,12 +30,15 @@ public class BuildIdCollector { class Collector implements Runnable { private final BuildIdExtractor extractor = BuildIdExtractor.create(); + private final long deadline; - Collector() {} + Collector(long timeout, TimeUnit unit) { + this.deadline = unit.toNanos(timeout) + System.nanoTime(); + } @Override public void run() { - while (true) { + while (System.nanoTime() <= deadline) { final Path path = workQueue.poll(); if (path == null) { if (!collecting.get()) { @@ -64,7 +68,7 @@ public void addUnprocessedLibrary(String filename) { public void resolveBuildId(Path path) { if (collecting.compareAndSet(false, true)) { - AgentTaskScheduler.get().execute(new Collector()); + AgentTaskScheduler.get().execute(new Collector(5, SECONDS)); } final String filename = path.getFileName().toString(); if (!processed.add(filename)) { From 5cff218b59c2c75a007a2a108c0b9d483f4d026f Mon Sep 17 00:00:00 2001 From: Andrea Marziali Date: Fri, 30 Jan 2026 09:47:07 +0100 Subject: [PATCH 4/4] Change file to path --- .../datadog/crashtracking/dto/StackFrame.java | 10 +++---- .../parsers/HotspotCrashLogParser.java | 27 +++---------------- .../sample-crash-for-telemetry-2.txt | 2 +- .../sample-crash-for-telemetry-3.txt | 2 +- .../sample-crash-for-telemetry.txt | 2 +- .../golden/errortracking/sample_oom.txt | 2 +- .../sample-crash-for-telemetry-2.txt | 2 +- .../sample-crash-for-telemetry-3.txt | 2 +- .../telemetry/sample-crash-for-telemetry.txt | 2 +- .../resources/golden/telemetry/sample_oom.txt | 2 +- 10 files changed, 17 insertions(+), 36 deletions(-) diff --git a/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/dto/StackFrame.java b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/dto/StackFrame.java index 10b87aab0a6..fbe6be3abfd 100644 --- a/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/dto/StackFrame.java +++ b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/dto/StackFrame.java @@ -6,7 +6,7 @@ public final class StackFrame { - public final String file; + public final String path; public final Integer line; public final String function; @@ -23,14 +23,14 @@ public final class StackFrame { public String relativeAddress; public StackFrame( - String file, + String path, Integer line, String function, String buildId, BuildInfo.BuildIdType buildIdType, BuildInfo.FileType fileType, String relativeAddress) { - this.file = file; + this.path = path; this.line = line; this.function = function; this.buildId = buildId; @@ -48,7 +48,7 @@ public boolean equals(Object o) { return false; } StackFrame that = (StackFrame) o; - return Objects.equals(file, that.file) + return Objects.equals(path, that.path) && Objects.equals(line, that.line) && Objects.equals(function, that.function) && Objects.equals(buildId, that.buildId) @@ -59,6 +59,6 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(file, line, function, buildId, buildIdType, fileType, relativeAddress); + return Objects.hash(path, line, function, buildId, buildIdType, fileType, relativeAddress); } } diff --git a/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/parsers/HotspotCrashLogParser.java b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/parsers/HotspotCrashLogParser.java index 266d867095b..948fc6669aa 100644 --- a/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/parsers/HotspotCrashLogParser.java +++ b/dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/parsers/HotspotCrashLogParser.java @@ -91,25 +91,6 @@ private StackFrame parseLine(String line) { String[] parts = SPACE_SPLITTER.split(line); if (parts.length > 3) { functionName = parts[3]; - - // Extract module name (e.g., java.base@21.0.1) - if (parts.length > 4 && parts[4].contains("@")) { - int atIdx = parts[4].indexOf('@'); - filename = parts[4].substring(0, atIdx); - } - - // Extract relative address from bracket [0x...+0x...] - int bracketStart = line.indexOf('['); - if (bracketStart > 0) { - int bracketEnd = line.indexOf(']', bracketStart); - if (bracketEnd > 0) { - String bracketContent = line.substring(bracketStart + 1, bracketEnd); - int plusIdx = bracketContent.indexOf('+'); - if (plusIdx > 0 && plusIdx + 1 < bracketContent.length()) { - relAddress = bracketContent.substring(plusIdx + 1); - } - } - } } break; } @@ -370,15 +351,15 @@ public CrashLog parse(String uuid, String crashLog) { for (StackFrame frame : frames) { // enrich with the build id if collected (best effort) - if (frame.file == null) { + if (frame.path == null) { enrichedFrames.add(frame); continue; } - final BuildInfo buildInfo = buildIdCollector.getBuildInfo(frame.file); + final BuildInfo buildInfo = buildIdCollector.getBuildInfo(frame.path); if (buildInfo != null) { enrichedFrames.add( new StackFrame( - normalizeFilename(frame.file), + normalizeFilename(frame.path), frame.line, frame.function, buildInfo.buildId, @@ -388,7 +369,7 @@ public CrashLog parse(String uuid, String crashLog) { } else { enrichedFrames.add( new StackFrame( - normalizeFilename(frame.file), + normalizeFilename(frame.path), frame.line, frame.function, null, diff --git a/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample-crash-for-telemetry-2.txt b/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample-crash-for-telemetry-2.txt index c6c384b38cb..27d3e1b665e 100644 --- a/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample-crash-for-telemetry-2.txt +++ b/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample-crash-for-telemetry-2.txt @@ -1 +1 @@ -{"timestamp":"2024-09-20T13:19:06Z","ddsource":"crashtracker","error":{"is_crash":true,"type":"UNKNOWN","message":"Process terminated by signal UNKNOWN","source_type":"crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"file":"libpthread.so.0","function":"__pthread_clockjoin_ex","relative_address":"0x9cd5"}]}}} ==> expected: <{data_schema_version=1.0, error={is_crash=true, kind=SIGSEGV, message=Process terminated by signal SIGSEGV, source_type=crashtracking, stack={format=CrashTrackerV1, frames=[{file=libpthread.so.0, function=__pthread_clockjoin_ex, relative_address=0x9cd5}]}}, incomplete=false, metadata={family=java, library_name=dd-trace-java, library_version=1.59.0-SNAPSHOT~83d60598da}, proc_info={pid=576034}, sig_info={si_addr=0x00007f011ab1ccd5 (sent by kill), si_signo=11, si_signo_human_readable=SIGSEGV}, timestamp=2024-09-20T13:19:06Z, uuid=a4194cd6-8cb3-45fd-9bd9-3af83e0a3ad3, version_id=0}> but was: <{timestamp=2024-09-20T13:19:06Z, ddsource=crashtracker, error={is_crash=true, type=UNKNOWN, message=Process terminated by signal UNKNOWN, source_type=crashtracking, stack={format=CrashTrackerV1, frames=[{file=libpthread.so.0, function=__pthread_clockjoin_ex, relative_address=0x9cd5}]}}} + {"timestamp":"2024-09-20T13:19:06Z","ddsource":"crashtracker","error":{"is_crash":true,"type":"UNKNOWN","message":"Process terminated by signal UNKNOWN","source_type":"crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"function":"__pthread_clockjoin_ex","path":"libpthread.so.0","relative_address":"0x9cd5"}]}}} diff --git a/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample-crash-for-telemetry-3.txt b/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample-crash-for-telemetry-3.txt index b2c3913d910..791ff9408d2 100644 --- a/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample-crash-for-telemetry-3.txt +++ b/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample-crash-for-telemetry-3.txt @@ -1 +1 @@ -{"ddsource":"crashtracker","error":{"is_crash":true,"type":"OutOfMemory","message":"Java heap space","source_type":"crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"file":"libjvm.dylib","function":"VMError::report_and_die()","relative_address":"0x565d30"},{"file":"libjvm.dylib","function":"report_vm_error(char const*, int, char const*, char const*)","relative_address":"0x1941a0"},{"file":"libjvm.dylib","function":"report_java_out_of_memory(char const*)","relative_address":"0x1943d8"},{"file":"libjvm.dylib","function":"CollectedHeap::common_mem_allocate_noinit(KlassHandle, unsigned long, Thread*)","relative_address":"0x70430"},{"file":"libjvm.dylib","function":"TypeArrayKlass::allocate_common(int, bool, Thread*)","relative_address":"0x53eba8"},{"file":"libjvm.dylib","function":"InterpreterRuntime::newarray(JavaThread*, BasicType, int)","relative_address":"0x285b6c"},{"function":"datadog.smoketest.crashtracking.CrashtrackingTestApplication.main([Ljava/lang/String;)V","line":105},{"function":"~StubRoutines::call_stub"},{"file":"libjvm.dylib","function":"JavaCalls::call_helper(JavaValue*, methodHandle*, JavaCallArguments*, Thread*)","relative_address":"0x28f86c"},{"file":"libjvm.dylib","function":"jni_invoke_static(JNIEnv_*, JavaValue*, _jobject*, JNICallType, _jmethodID*, JNI_ArgumentPusher*, Thread*)","relative_address":"0x2d3b44"},{"file":"libjvm.dylib","function":"jni_CallStaticVoidMethod","relative_address":"0x2d7160"},{"file":"java","function":"JavaMain","relative_address":"0x6404"},{"file":"libsystem_pthread.dylib","function":"_pthread_start","relative_address":"0x6f94"},{"file":"libsystem_pthread.dylib","function":"thread_start","relative_address":"0x1d34"},{"function":"datadog.smoketest.crashtracking.CrashtrackingTestApplication.main([Ljava/lang/String;)V","line":105},{"function":"~StubRoutines::call_stub"}]}}} +{"ddsource":"crashtracker","error":{"is_crash":true,"type":"OutOfMemory","message":"Java heap space","source_type":"crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"function":"VMError::report_and_die()","path":"libjvm.dylib","relative_address":"0x565d30"},{"function":"report_vm_error(char const*, int, char const*, char const*)","path":"libjvm.dylib","relative_address":"0x1941a0"},{"function":"report_java_out_of_memory(char const*)","path":"libjvm.dylib","relative_address":"0x1943d8"},{"function":"CollectedHeap::common_mem_allocate_noinit(KlassHandle, unsigned long, Thread*)","path":"libjvm.dylib","relative_address":"0x70430"},{"function":"TypeArrayKlass::allocate_common(int, bool, Thread*)","path":"libjvm.dylib","relative_address":"0x53eba8"},{"function":"InterpreterRuntime::newarray(JavaThread*, BasicType, int)","path":"libjvm.dylib","relative_address":"0x285b6c"},{"function":"datadog.smoketest.crashtracking.CrashtrackingTestApplication.main([Ljava/lang/String;)V","line":105},{"function":"~StubRoutines::call_stub"},{"function":"JavaCalls::call_helper(JavaValue*, methodHandle*, JavaCallArguments*, Thread*)","path":"libjvm.dylib","relative_address":"0x28f86c"},{"function":"jni_invoke_static(JNIEnv_*, JavaValue*, _jobject*, JNICallType, _jmethodID*, JNI_ArgumentPusher*, Thread*)","path":"libjvm.dylib","relative_address":"0x2d3b44"},{"function":"jni_CallStaticVoidMethod","path":"libjvm.dylib","relative_address":"0x2d7160"},{"function":"JavaMain","path":"java","relative_address":"0x6404"},{"function":"_pthread_start","path":"libsystem_pthread.dylib","relative_address":"0x6f94"},{"function":"thread_start","path":"libsystem_pthread.dylib","relative_address":"0x1d34"},{"function":"datadog.smoketest.crashtracking.CrashtrackingTestApplication.main([Ljava/lang/String;)V","line":105},{"function":"~StubRoutines::call_stub"}]}}} diff --git a/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample-crash-for-telemetry.txt b/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample-crash-for-telemetry.txt index 46ca45b4032..8503e816fa8 100644 --- a/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample-crash-for-telemetry.txt +++ b/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample-crash-for-telemetry.txt @@ -1 +1 @@ -{"timestamp":"2023-10-17T20:25:14+08:00","ddsource":"crashtracker","error":{"is_crash":true,"type":"SIGSEGV","message":"Process terminated by signal SIGSEGV","source_type":"crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"file":"libjvm.so","function":"vframeStreamForte::forte_next()","relative_address":"0x6b7187"},{"file":"libjvm.so","function":"forte_fill_call_trace_given_top(JavaThread*, ASGCT_CallTrace*, int, frame)","relative_address":"0x6b79ad"},{"file":"libjvm.so","function":"AsyncGetCallTrace","relative_address":"0x6b8123"},{"file":"libjavaProfiler.so","function":"Profiler::getJavaTraceAsync(void*, ASGCT_CallFrame*, int, StackContext*, bool*)","relative_address":"0x146c8"},{"file":"libjavaProfiler.so","function":"Profiler::recordSample(void*, unsigned long long, int, int, Event*)","relative_address":"0x1c18d"},{"file":"libjavaProfiler.so","function":"WallClock::sharedSignalHandler(int, siginfo_t*, void*)","relative_address":"0x1d128"},{"file":"libpthread.so.0","relative_address":"0x12cf0"},{"file":"libjvm.so","function":"JfrStackTrace::record_safe(JavaThread*, int)","relative_address":"0x85f9e9"},{"file":"libjvm.so","function":"JfrStackTraceRepository::record_for_leak_profiler(JavaThread*, int)","relative_address":"0x861650"},{"file":"libjvm.so","function":"ObjectSampler::sample(HeapWordImpl**, unsigned long, JavaThread*)","relative_address":"0xb1ecba"},{"file":"libjvm.so","function":"JfrAllocationTracer::JfrAllocationTracer(Klass const*, HeapWordImpl**, unsigned long, bool, JavaThread*)","relative_address":"0x81abee"},{"file":"libjvm.so","function":"AllocTracer::send_allocation_in_new_tlab(Klass*, HeapWordImpl**, unsigned long, unsigned long, JavaThread*)","relative_address":"0x3afa20"},{"file":"libjvm.so","function":"MemAllocator::allocate() const","relative_address":"0xa8f8ed"},{"file":"libjvm.so","function":"InstanceKlass::allocate_objArray(int, int, JavaThread*)","relative_address":"0x7e443c"},{"file":"libjvm.so","function":"OptoRuntime::new_array_C(Klass*, int, JavaThread*)","relative_address":"0xbe1b59"},{"function":"~RuntimeStub::_new_array_Java"},{"file":"java.base","function":"java.util.HashMap.resize()[Ljava/util/HashMap$Node;","relative_address":"0x00000000000008dc"},{"file":"java.base","function":"java.util.HashMap.putVal(ILjava/lang/Object;Ljava/lang/Object;ZZ)Ljava/lang/Object;","relative_address":"0x0000000000000058"},{"file":"java.base","function":"java.util.HashSet.add(Ljava/lang/Object;)Z","relative_address":"0x000000000000014c"},{"function":"com.REDACT_THIS.util.dom.DOMUtil.doTransform(Lorg/w3c/dom/Node;Ljava/io/PrintStream;IZZZZZ)V","relative_address":"0x0000000000001c40"},{"function":"com.REDACT_THIS.util.dom.DOMUtil.doTransform(Lorg/w3c/dom/Node;Ljava/io/PrintStream;IZZZZZ)V","relative_address":"0x0000000000001ee8"},{"function":"com.REDACT_THIS.util.dom.DOMUtil.doTransform(Lorg/w3c/dom/Node;Ljava/io/PrintStream;IZZZZZ)V","relative_address":"0x0000000000001ee8"},{"function":"com.REDACT_THIS.util.dom.DOMUtil.doTransform(Lorg/w3c/dom/Node;Ljava/io/PrintStream;IZZZZZ)V","relative_address":"0x0000000000003524"},{"function":"com.REDACT_THIS.util.dom.DOMUtil.partToString(Lorg/w3c/dom/Node;)Ljava/lang/String;","relative_address":"0x00000000000003b8"},{"function":"com.REDACT_THIS.message.impl.MessagePartDOMExt.writeExternal(Ljava/io/ObjectOutput;)V","relative_address":"0x0000000000000114"},{"file":"java.base","function":"java.io.ObjectOutputStream.writeOrdinaryObject(Ljava/lang/Object;Ljava/io/ObjectStreamClass;Z)V","relative_address":"0x00000000000005c8"},{"file":"java.base","function":"java.io.ObjectOutputStream.writeObject0(Ljava/lang/Object;Z)V","relative_address":"0x0000000000000a04"},{"file":"java.base","function":"jdk.internal.reflect.GeneratedMethodAccessor173.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;","relative_address":"0x00000000000003d8"},{"file":"java.base","function":"java.io.ObjectOutputStream.writeSerialData(Ljava/lang/Object;Ljava/io/ObjectStreamClass;)V","relative_address":"0x0000000000000434"},{"file":"java.base","function":"java.io.ObjectOutputStream.writeOrdinaryObject(Ljava/lang/Object;Ljava/io/ObjectStreamClass;Z)V","relative_address":"0x0000000000000124"},{"file":"java.base","function":"java.io.ObjectOutputStream.writeObject0(Ljava/lang/Object;Z)V","relative_address":"0x0000000000000a04"},{"function":"com.REDACT_THIS.message.impl.Message.writeExternal(Ljava/io/ObjectOutput;)V","relative_address":"0x00000000000008c4"},{"function":"com.REDACT_THIS.xstream.converters.reflection.ExternalizableConverter.marshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x00000000000003dc"},{"function":"com.REDACT_THIS.xstream.core.TreeMarshaller.convertAnother(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/converters/Converter;)V","relative_address":"0x0000000000000a54"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshallField(Lcom/REDACT_THIS/xstream/converters/MarshallingContext;Ljava/lang/Object;Ljava/lang/reflect/Field;)V","relative_address":"0x00000000000000d0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter$2.writeField(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;)V","relative_address":"0x00000000000009c0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.doMarshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000430"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000354"},{"function":"com.REDACT_THIS.xstream.core.TreeMarshaller.convertAnother(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/converters/Converter;)V","relative_address":"0x0000000000000a54"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshallField(Lcom/REDACT_THIS/xstream/converters/MarshallingContext;Ljava/lang/Object;Ljava/lang/reflect/Field;)V","relative_address":"0x00000000000000d0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter$2.writeField(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;)V","relative_address":"0x00000000000009c0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.doMarshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000430"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000354"},{"function":"com.REDACT_THIS.xstream.core.TreeMarshaller.convertAnother(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/converters/Converter;)V","relative_address":"0x0000000000000a54"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshallField(Lcom/REDACT_THIS/xstream/converters/MarshallingContext;Ljava/lang/Object;Ljava/lang/reflect/Field;)V","relative_address":"0x00000000000000d0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter$2.writeField(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;)V","relative_address":"0x00000000000009c0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.doMarshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000430"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000354"},{"function":"com.REDACT_THIS.xstream.core.TreeMarshaller.convertAnother(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/converters/Converter;)V","relative_address":"0x0000000000000a54"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshallField(Lcom/REDACT_THIS/xstream/converters/MarshallingContext;Ljava/lang/Object;Ljava/lang/reflect/Field;)V","relative_address":"0x00000000000000d0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter$2.writeField(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;)V","relative_address":"0x00000000000009c0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.doMarshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000430"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000354"},{"function":"com.REDACT_THIS.xstream.core.TreeMarshaller.convertAnother(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/converters/Converter;)V","relative_address":"0x0000000000000a54"},{"function":"com.REDACT_THIS.xstream.XStream.toXML(Ljava/lang/Object;Ljava/io/OutputStream;)V","relative_address":"0x00000000000010d8"},{"function":"com.REDACT_THIS.recover.impl.fs.FSJobSerializer.serializeJob(Ljava/lang/String;Lcom/REDACT_THIS/recover/impl/GenericRecoveryJob;)V","relative_address":"0x00000000000010a4"},{"function":"com.REDACT_THIS.recover.impl.db.RecoveryPoolDBImpl.specificSave(Lcom/REDACT_THIS/recover/spi/RecoveryJob;)V","relative_address":"0x0000000000004208"},{"function":"com.REDACT_THIS.recover.impl.REDACT_THIS.saveJob(Lcom/REDACT_THIS/recover/spi/RecoveryJob;ILjava/lang/String;)V","relative_address":"0x0000000000000960"},{"function":"com.REDACT_THIS.frame.core.FrameWorkListener.callbackNewData(Lcom/REDACT_THIS/frame/header/GenericTask;Ljava/util/concurrent/ExecutorService;)V","relative_address":"0x0000000000000f10"},{"function":"com.REDACT_THIS.frame.connection.direct.DirectModeMessageListener.onMessage(Ljavax/jms/Message;)V","relative_address":"0x0000000000001a34"},{"function":"datadog.trace.instrumentation.jms.DatadogMessageListener.onMessage(Ljavax/jms/Message;)V","relative_address":"0x0000000000000440"},{"function":"org.apache.activemq.artemis.jms.client.JMSMessageListenerWrapper.onMessage(Lorg/apache/activemq/artemis/api/core/client/ClientMessage;)V","relative_address":"0x0000000000000908"},{"function":"org.apache.activemq.artemis.core.client.impl.ClientConsumerImpl$Runner.run()V","relative_address":"0x0000000000001018"},{"function":"org.apache.activemq.artemis.utils.actors.ProcessorBase$$Lambda$2929+0x00000007ce44f8f8.run()V","relative_address":"0x00000000000002b4"},{"file":"java.base","function":"java.util.concurrent.ThreadPoolExecutor.runWorker(Ljava/util/concurrent/ThreadPoolExecutor$Worker;)V","relative_address":"0x0000000000000368"},{"file":"java.base","function":"java.util.concurrent.ThreadPoolExecutor$Worker.run()V","relative_address":"0x0000000000000078"},{"function":"org.apache.activemq.artemis.utils.ActiveMQThreadFactory$1.run()V","line":44},{"function":"~StubRoutines::call_stub"}]}},"sig_info":{"si_addr":"0x0000000000000070","si_signo_human_readable":"SIGSEGV","si_signo":11}} +{"timestamp":"2023-10-17T20:25:14+08:00","ddsource":"crashtracker","error":{"is_crash":true,"type":"SIGSEGV","message":"Process terminated by signal SIGSEGV","source_type":"crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"function":"vframeStreamForte::forte_next()","path":"libjvm.so","relative_address":"0x6b7187"},{"function":"forte_fill_call_trace_given_top(JavaThread*, ASGCT_CallTrace*, int, frame)","path":"libjvm.so","relative_address":"0x6b79ad"},{"function":"AsyncGetCallTrace","path":"libjvm.so","relative_address":"0x6b8123"},{"function":"Profiler::getJavaTraceAsync(void*, ASGCT_CallFrame*, int, StackContext*, bool*)","path":"libjavaProfiler.so","relative_address":"0x146c8"},{"function":"Profiler::recordSample(void*, unsigned long long, int, int, Event*)","path":"libjavaProfiler.so","relative_address":"0x1c18d"},{"function":"WallClock::sharedSignalHandler(int, siginfo_t*, void*)","path":"libjavaProfiler.so","relative_address":"0x1d128"},{"path":"libpthread.so.0","relative_address":"0x12cf0"},{"function":"JfrStackTrace::record_safe(JavaThread*, int)","path":"libjvm.so","relative_address":"0x85f9e9"},{"function":"JfrStackTraceRepository::record_for_leak_profiler(JavaThread*, int)","path":"libjvm.so","relative_address":"0x861650"},{"function":"ObjectSampler::sample(HeapWordImpl**, unsigned long, JavaThread*)","path":"libjvm.so","relative_address":"0xb1ecba"},{"function":"JfrAllocationTracer::JfrAllocationTracer(Klass const*, HeapWordImpl**, unsigned long, bool, JavaThread*)","path":"libjvm.so","relative_address":"0x81abee"},{"function":"AllocTracer::send_allocation_in_new_tlab(Klass*, HeapWordImpl**, unsigned long, unsigned long, JavaThread*)","path":"libjvm.so","relative_address":"0x3afa20"},{"function":"MemAllocator::allocate() const","path":"libjvm.so","relative_address":"0xa8f8ed"},{"function":"InstanceKlass::allocate_objArray(int, int, JavaThread*)","path":"libjvm.so","relative_address":"0x7e443c"},{"function":"OptoRuntime::new_array_C(Klass*, int, JavaThread*)","path":"libjvm.so","relative_address":"0xbe1b59"},{"function":"~RuntimeStub::_new_array_Java"},{"function":"java.util.HashMap.resize()[Ljava/util/HashMap$Node;"},{"function":"java.util.HashMap.putVal(ILjava/lang/Object;Ljava/lang/Object;ZZ)Ljava/lang/Object;"},{"function":"java.util.HashSet.add(Ljava/lang/Object;)Z"},{"function":"com.REDACT_THIS.util.dom.DOMUtil.doTransform(Lorg/w3c/dom/Node;Ljava/io/PrintStream;IZZZZZ)V"},{"function":"com.REDACT_THIS.util.dom.DOMUtil.doTransform(Lorg/w3c/dom/Node;Ljava/io/PrintStream;IZZZZZ)V"},{"function":"com.REDACT_THIS.util.dom.DOMUtil.doTransform(Lorg/w3c/dom/Node;Ljava/io/PrintStream;IZZZZZ)V"},{"function":"com.REDACT_THIS.util.dom.DOMUtil.doTransform(Lorg/w3c/dom/Node;Ljava/io/PrintStream;IZZZZZ)V"},{"function":"com.REDACT_THIS.util.dom.DOMUtil.partToString(Lorg/w3c/dom/Node;)Ljava/lang/String;"},{"function":"com.REDACT_THIS.message.impl.MessagePartDOMExt.writeExternal(Ljava/io/ObjectOutput;)V"},{"function":"java.io.ObjectOutputStream.writeOrdinaryObject(Ljava/lang/Object;Ljava/io/ObjectStreamClass;Z)V"},{"function":"java.io.ObjectOutputStream.writeObject0(Ljava/lang/Object;Z)V"},{"function":"jdk.internal.reflect.GeneratedMethodAccessor173.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"},{"function":"java.io.ObjectOutputStream.writeSerialData(Ljava/lang/Object;Ljava/io/ObjectStreamClass;)V"},{"function":"java.io.ObjectOutputStream.writeOrdinaryObject(Ljava/lang/Object;Ljava/io/ObjectStreamClass;Z)V"},{"function":"java.io.ObjectOutputStream.writeObject0(Ljava/lang/Object;Z)V"},{"function":"com.REDACT_THIS.message.impl.Message.writeExternal(Ljava/io/ObjectOutput;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.ExternalizableConverter.marshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V"},{"function":"com.REDACT_THIS.xstream.core.TreeMarshaller.convertAnother(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/converters/Converter;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshallField(Lcom/REDACT_THIS/xstream/converters/MarshallingContext;Ljava/lang/Object;Ljava/lang/reflect/Field;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter$2.writeField(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.doMarshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V"},{"function":"com.REDACT_THIS.xstream.core.TreeMarshaller.convertAnother(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/converters/Converter;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshallField(Lcom/REDACT_THIS/xstream/converters/MarshallingContext;Ljava/lang/Object;Ljava/lang/reflect/Field;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter$2.writeField(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.doMarshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V"},{"function":"com.REDACT_THIS.xstream.core.TreeMarshaller.convertAnother(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/converters/Converter;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshallField(Lcom/REDACT_THIS/xstream/converters/MarshallingContext;Ljava/lang/Object;Ljava/lang/reflect/Field;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter$2.writeField(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.doMarshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V"},{"function":"com.REDACT_THIS.xstream.core.TreeMarshaller.convertAnother(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/converters/Converter;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshallField(Lcom/REDACT_THIS/xstream/converters/MarshallingContext;Ljava/lang/Object;Ljava/lang/reflect/Field;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter$2.writeField(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.doMarshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V"},{"function":"com.REDACT_THIS.xstream.core.TreeMarshaller.convertAnother(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/converters/Converter;)V"},{"function":"com.REDACT_THIS.xstream.XStream.toXML(Ljava/lang/Object;Ljava/io/OutputStream;)V"},{"function":"com.REDACT_THIS.recover.impl.fs.FSJobSerializer.serializeJob(Ljava/lang/String;Lcom/REDACT_THIS/recover/impl/GenericRecoveryJob;)V"},{"function":"com.REDACT_THIS.recover.impl.db.RecoveryPoolDBImpl.specificSave(Lcom/REDACT_THIS/recover/spi/RecoveryJob;)V"},{"function":"com.REDACT_THIS.recover.impl.REDACT_THIS.saveJob(Lcom/REDACT_THIS/recover/spi/RecoveryJob;ILjava/lang/String;)V"},{"function":"com.REDACT_THIS.frame.core.FrameWorkListener.callbackNewData(Lcom/REDACT_THIS/frame/header/GenericTask;Ljava/util/concurrent/ExecutorService;)V"},{"function":"com.REDACT_THIS.frame.connection.direct.DirectModeMessageListener.onMessage(Ljavax/jms/Message;)V"},{"function":"datadog.trace.instrumentation.jms.DatadogMessageListener.onMessage(Ljavax/jms/Message;)V"},{"function":"org.apache.activemq.artemis.jms.client.JMSMessageListenerWrapper.onMessage(Lorg/apache/activemq/artemis/api/core/client/ClientMessage;)V"},{"function":"org.apache.activemq.artemis.core.client.impl.ClientConsumerImpl$Runner.run()V"},{"function":"org.apache.activemq.artemis.utils.actors.ProcessorBase$$Lambda$2929+0x00000007ce44f8f8.run()V"},{"function":"java.util.concurrent.ThreadPoolExecutor.runWorker(Ljava/util/concurrent/ThreadPoolExecutor$Worker;)V"},{"function":"java.util.concurrent.ThreadPoolExecutor$Worker.run()V"},{"function":"org.apache.activemq.artemis.utils.ActiveMQThreadFactory$1.run()V","line":44},{"function":"~StubRoutines::call_stub"}]}},"sig_info":{"si_addr":"0x0000000000000070","si_signo_human_readable":"SIGSEGV","si_signo":11}} diff --git a/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample_oom.txt b/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample_oom.txt index dac59403b14..6771b6c2f23 100644 --- a/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample_oom.txt +++ b/dd-java-agent/agent-crashtracking/src/test/resources/golden/errortracking/sample_oom.txt @@ -1 +1 @@ -{"timestamp":"2025-11-24T09:43:29+01:00","ddsource":"crashtracker","error":{"is_crash":true,"type":"OutOfMemory","message":"Java heap space","source_type":"crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"file":"libjvm.dylib","function":"VMError::report_and_die(int, char const*, char const*, char*, Thread*, unsigned char*, void*, void*, char const*, int, unsigned long)","relative_address":"0xaa5f24"},{"file":"libjvm.dylib","function":"report_fatal(VMErrorType, char const*, int, char const*, ...)","relative_address":"0x314c74"},{"file":"libjvm.dylib","function":"report_java_out_of_memory(char const*)","relative_address":"0x315248"},{"file":"libjvm.dylib","function":"MemAllocator::Allocation::check_out_of_memory()","relative_address":"0x7d9764"},{"file":"libjvm.dylib","function":"MemAllocator::allocate() const","relative_address":"0x7da2f4"},{"file":"libjvm.dylib","function":"CollectedHeap::array_allocate(Klass*, unsigned long, int, bool, JavaThread*)","relative_address":"0x2c3de4"},{"file":"libjvm.dylib","function":"OptoRuntime::new_array_C(Klass*, int, JavaThread*)","relative_address":"0x8ea9ec"},{"function":"~RuntimeStub::_new_array_Java","relative_address":"0x00000001124cb638"},{"file":"java.base","function":"java.nio.ByteBuffer.allocate(I)Ljava/nio/ByteBuffer;","relative_address":"0x0000000000000228"},{"function":"datadog.communication.serialization.FlushingBuffer.(ILdatadog/communication/serialization/ByteBufferConsumer;)V","line":6},{"function":"datadog.trace.agent.common.writer.PayloadDispatcherImpl.selectMapper()V","line":126},{"function":"datadog.trace.agent.common.writer.PayloadDispatcherImpl.addTrace(Ljava/util/List;)V","line":1},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.onEvent(Ljava/lang/Object;)V","line":22},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.consumeFromPrimaryQueue()V","line":21},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.runDutyCycle()V","line":12},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.run()V","line":1},{"function":"java.lang.Thread.runWith(Ljava/lang/Object;Ljava/lang/Runnable;)V"},{"function":"java.lang.Thread.run()V"},{"function":"~StubRoutines::call_stub","relative_address":"0x00000001123b0140"}]}}} ==> expected: <{data_schema_version=1.0, error={is_crash=true, kind=OutOfMemory, message=Java heap space, source_type=crashtracking, stack={format=CrashTrackerV1, frames=[{file=libjvm.dylib, function=VMError::report_and_die(int, char const*, char const*, char*, Thread*, unsigned char*, void*, void*, char const*, int, unsigned long), relative_address=0xaa5f24}, {file=libjvm.dylib, function=report_fatal(VMErrorType, char const*, int, char const*, ...), relative_address=0x314c74}, {file=libjvm.dylib, function=report_java_out_of_memory(char const*), relative_address=0x315248}, {file=libjvm.dylib, function=MemAllocator::Allocation::check_out_of_memory(), relative_address=0x7d9764}, {file=libjvm.dylib, function=MemAllocator::allocate() const, relative_address=0x7da2f4}, {file=libjvm.dylib, function=CollectedHeap::array_allocate(Klass*, unsigned long, int, bool, JavaThread*), relative_address=0x2c3de4}, {file=libjvm.dylib, function=OptoRuntime::new_array_C(Klass*, int, JavaThread*), relative_address=0x8ea9ec}, {function=~RuntimeStub::_new_array_Java, relative_address=0x00000001124cb638}, {file=java.base, function=java.nio.ByteBuffer.allocate(I)Ljava/nio/ByteBuffer;, relative_address=0x0000000000000228}, {function=datadog.communication.serialization.FlushingBuffer.(ILdatadog/communication/serialization/ByteBufferConsumer;)V, line=6}, {function=datadog.trace.agent.common.writer.PayloadDispatcherImpl.selectMapper()V, line=126}, {function=datadog.trace.agent.common.writer.PayloadDispatcherImpl.addTrace(Ljava/util/List;)V, line=1}, {function=datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.onEvent(Ljava/lang/Object;)V, line=22}, {function=datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.consumeFromPrimaryQueue()V, line=21}, {function=datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.runDutyCycle()V, line=12}, {function=datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.run()V, line=1}, {function=java.lang.Thread.runWith(Ljava/lang/Object;Ljava/lang/Runnable;)V}, {function=java.lang.Thread.run()V}, {function=~StubRoutines::call_stub, relative_address=0x00000001123b0140}]}}, incomplete=false, metadata={family=java, library_name=dd-trace-java, library_version=1.59.0-SNAPSHOT~83d60598da}, proc_info={pid=74045}, timestamp=2025-11-24T09:43:29+01:00, uuid=a4194cd6-8cb3-45fd-9bd9-3af83e0a3ad3, version_id=0}> but was: <{timestamp=2025-11-24T09:43:29+01:00, ddsource=crashtracker, error={is_crash=true, type=OutOfMemory, message=Java heap space, source_type=crashtracking, stack={format=CrashTrackerV1, frames=[{file=libjvm.dylib, function=VMError::report_and_die(int, char const*, char const*, char*, Thread*, unsigned char*, void*, void*, char const*, int, unsigned long), relative_address=0xaa5f24}, {file=libjvm.dylib, function=report_fatal(VMErrorType, char const*, int, char const*, ...), relative_address=0x314c74}, {file=libjvm.dylib, function=report_java_out_of_memory(char const*), relative_address=0x315248}, {file=libjvm.dylib, function=MemAllocator::Allocation::check_out_of_memory(), relative_address=0x7d9764}, {file=libjvm.dylib, function=MemAllocator::allocate() const, relative_address=0x7da2f4}, {file=libjvm.dylib, function=CollectedHeap::array_allocate(Klass*, unsigned long, int, bool, JavaThread*), relative_address=0x2c3de4}, {file=libjvm.dylib, function=OptoRuntime::new_array_C(Klass*, int, JavaThread*), relative_address=0x8ea9ec}, {function=~RuntimeStub::_new_array_Java, relative_address=0x00000001124cb638}, {file=java.base, function=java.nio.ByteBuffer.allocate(I)Ljava/nio/ByteBuffer;, relative_address=0x0000000000000228}, {function=datadog.communication.serialization.FlushingBuffer.(ILdatadog/communication/serialization/ByteBufferConsumer;)V, line=6}, {function=datadog.trace.agent.common.writer.PayloadDispatcherImpl.selectMapper()V, line=126}, {function=datadog.trace.agent.common.writer.PayloadDispatcherImpl.addTrace(Ljava/util/List;)V, line=1}, {function=datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.onEvent(Ljava/lang/Object;)V, line=22}, {function=datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.consumeFromPrimaryQueue()V, line=21}, {function=datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.runDutyCycle()V, line=12}, {function=datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.run()V, line=1}, {function=java.lang.Thread.runWith(Ljava/lang/Object;Ljava/lang/Runnable;)V}, {function=java.lang.Thread.run()V}, {function=~StubRoutines::call_stub, relative_address=0x00000001123b0140}]}}} +{"timestamp":"2025-11-24T09:43:29+01:00","ddsource":"crashtracker","error":{"is_crash":true,"type":"OutOfMemory","message":"Java heap space","source_type":"crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"function":"VMError::report_and_die(int, char const*, char const*, char*, Thread*, unsigned char*, void*, void*, char const*, int, unsigned long)","path":"libjvm.dylib","relative_address":"0xaa5f24"},{"function":"report_fatal(VMErrorType, char const*, int, char const*, ...)","path":"libjvm.dylib","relative_address":"0x314c74"},{"function":"report_java_out_of_memory(char const*)","path":"libjvm.dylib","relative_address":"0x315248"},{"function":"MemAllocator::Allocation::check_out_of_memory()","path":"libjvm.dylib","relative_address":"0x7d9764"},{"function":"MemAllocator::allocate() const","path":"libjvm.dylib","relative_address":"0x7da2f4"},{"function":"CollectedHeap::array_allocate(Klass*, unsigned long, int, bool, JavaThread*)","path":"libjvm.dylib","relative_address":"0x2c3de4"},{"function":"OptoRuntime::new_array_C(Klass*, int, JavaThread*)","path":"libjvm.dylib","relative_address":"0x8ea9ec"},{"function":"~RuntimeStub::_new_array_Java","relative_address":"0x00000001124cb638"},{"function":"java.nio.ByteBuffer.allocate(I)Ljava/nio/ByteBuffer;"},{"function":"datadog.communication.serialization.FlushingBuffer.(ILdatadog/communication/serialization/ByteBufferConsumer;)V","line":6},{"function":"datadog.trace.agent.common.writer.PayloadDispatcherImpl.selectMapper()V","line":126},{"function":"datadog.trace.agent.common.writer.PayloadDispatcherImpl.addTrace(Ljava/util/List;)V","line":1},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.onEvent(Ljava/lang/Object;)V","line":22},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.consumeFromPrimaryQueue()V","line":21},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.runDutyCycle()V","line":12},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.run()V","line":1},{"function":"java.lang.Thread.runWith(Ljava/lang/Object;Ljava/lang/Runnable;)V"},{"function":"java.lang.Thread.run()V"},{"function":"~StubRoutines::call_stub","relative_address":"0x00000001123b0140"}]}}} ==> expected: <{data_schema_version=1.0, error={is_crash=true, kind=OutOfMemory, message=Java heap space, source_type=Crashtracking, stack={format=CrashTrackerV1, frames=[{function=VMError::report_and_die(int, char const*, char const*, char*, Thread*, unsigned char*, void*, void*, char const*, int, unsigned long), path=libjvm.dylib, relative_address=0xaa5f24}, {function=report_fatal(VMErrorType, char const*, int, char const*, ...), path=libjvm.dylib, relative_address=0x314c74}, {function=report_java_out_of_memory(char const*), path=libjvm.dylib, relative_address=0x315248}, {function=MemAllocator::Allocation::check_out_of_memory(), path=libjvm.dylib, relative_address=0x7d9764}, {function=MemAllocator::allocate() const, path=libjvm.dylib, relative_address=0x7da2f4}, {function=CollectedHeap::array_allocate(Klass*, unsigned long, int, bool, JavaThread*), path=libjvm.dylib, relative_address=0x2c3de4}, {function=OptoRuntime::new_array_C(Klass*, int, JavaThread*), path=libjvm.dylib, relative_address=0x8ea9ec}, {function=~RuntimeStub::_new_array_Java, relative_address=0x00000001124cb638}, {function=java.nio.ByteBuffer.allocate(I)Ljava/nio/ByteBuffer;}, {function=datadog.communication.serialization.FlushingBuffer.(ILdatadog/communication/serialization/ByteBufferConsumer;)V, line=6}, {function=datadog.trace.agent.common.writer.PayloadDispatcherImpl.selectMapper()V, line=126}, {function=datadog.trace.agent.common.writer.PayloadDispatcherImpl.addTrace(Ljava/util/List;)V, line=1}, {function=datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.onEvent(Ljava/lang/Object;)V, line=22}, {function=datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.consumeFromPrimaryQueue()V, line=21}, {function=datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.runDutyCycle()V, line=12}, {function=datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.run()V, line=1}, {function=java.lang.Thread.runWith(Ljava/lang/Object;Ljava/lang/Runnable;)V}, {function=java.lang.Thread.run()V}, {function=~StubRoutines::call_stub, relative_address=0x00000001123b0140}]}}, incomplete=false, metadata={family=java, library_name=dd-trace-java, library_version=1.59.0-SNAPSHOT~896c1ad986}, proc_info={pid=74045}, timestamp=2025-11-24T09:43:29+01:00, uuid=a4194cd6-8cb3-45fd-9bd9-3af83e0a3ad3, version_id=0}> but was: <{timestamp=2025-11-24T09:43:29+01:00, ddsource=crashtracker, error={is_crash=true, type=OutOfMemory, message=Java heap space, source_type=crashtracking, stack={format=CrashTrackerV1, frames=[{function=VMError::report_and_die(int, char const*, char const*, char*, Thread*, unsigned char*, void*, void*, char const*, int, unsigned long), path=libjvm.dylib, relative_address=0xaa5f24}, {function=report_fatal(VMErrorType, char const*, int, char const*, ...), path=libjvm.dylib, relative_address=0x314c74}, {function=report_java_out_of_memory(char const*), path=libjvm.dylib, relative_address=0x315248}, {function=MemAllocator::Allocation::check_out_of_memory(), path=libjvm.dylib, relative_address=0x7d9764}, {function=MemAllocator::allocate() const, path=libjvm.dylib, relative_address=0x7da2f4}, {function=CollectedHeap::array_allocate(Klass*, unsigned long, int, bool, JavaThread*), path=libjvm.dylib, relative_address=0x2c3de4}, {function=OptoRuntime::new_array_C(Klass*, int, JavaThread*), path=libjvm.dylib, relative_address=0x8ea9ec}, {function=~RuntimeStub::_new_array_Java, relative_address=0x00000001124cb638}, {function=java.nio.ByteBuffer.allocate(I)Ljava/nio/ByteBuffer;}, {function=datadog.communication.serialization.FlushingBuffer.(ILdatadog/communication/serialization/ByteBufferConsumer;)V, line=6}, {function=datadog.trace.agent.common.writer.PayloadDispatcherImpl.selectMapper()V, line=126}, {function=datadog.trace.agent.common.writer.PayloadDispatcherImpl.addTrace(Ljava/util/List;)V, line=1}, {function=datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.onEvent(Ljava/lang/Object;)V, line=22}, {function=datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.consumeFromPrimaryQueue()V, line=21}, {function=datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.runDutyCycle()V, line=12}, {function=datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.run()V, line=1}, {function=java.lang.Thread.runWith(Ljava/lang/Object;Ljava/lang/Runnable;)V}, {function=java.lang.Thread.run()V}, {function=~StubRoutines::call_stub, relative_address=0x00000001123b0140}]}}} diff --git a/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample-crash-for-telemetry-2.txt b/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample-crash-for-telemetry-2.txt index fce0f8ca696..d2340d9dd3e 100644 --- a/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample-crash-for-telemetry-2.txt +++ b/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample-crash-for-telemetry-2.txt @@ -1 +1 @@ -{"data_schema_version":"1.0","error":{"is_crash":true,"kind":"UNKNOWN","message":"Process terminated by signal UNKNOWN","source_type":"Crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"file":"libpthread.so.0","function":"__pthread_clockjoin_ex","relative_address":"0x9cd5"}]}},"incomplete":false,"metadata":{"family":"java","library_name":"dd-trace-java","library_version":"1.59.0-SNAPSHOT~83d60598da"},"os_info":{"architecture":"aarch64","bitness":"64","os_type":"Mac OS X","version":{"Semantic":[15,7,1]}},"proc_info":{"pid":576034},"timestamp":"2024-09-20T13:19:06Z","uuid":"a4194cd6-8cb3-45fd-9bd9-3af83e0a3ad3","version_id":0} +{"data_schema_version":"1.0","error":{"is_crash":true,"kind":"UNKNOWN","message":"Process terminated by signal UNKNOWN","source_type":"Crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"function":"__pthread_clockjoin_ex","path":"libpthread.so.0","relative_address":"0x9cd5"}]}},"incomplete":false,"metadata":{"family":"java","library_name":"dd-trace-java","library_version":"1.59.0-SNAPSHOT~896c1ad986"},"os_info":{"architecture":"aarch64","bitness":"64","os_type":"Mac OS X","version":{"Semantic":[15,7,1]}},"proc_info":{"pid":576034},"timestamp":"2024-09-20T13:19:06Z","uuid":"a4194cd6-8cb3-45fd-9bd9-3af83e0a3ad3","version_id":0} diff --git a/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample-crash-for-telemetry-3.txt b/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample-crash-for-telemetry-3.txt index 99328e14792..fb6695894b0 100644 --- a/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample-crash-for-telemetry-3.txt +++ b/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample-crash-for-telemetry-3.txt @@ -1 +1 @@ -{"data_schema_version":"1.0","error":{"is_crash":true,"kind":"OutOfMemory","message":"Java heap space","source_type":"Crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"file":"libjvm.dylib","function":"VMError::report_and_die()","relative_address":"0x565d30"},{"file":"libjvm.dylib","function":"report_vm_error(char const*, int, char const*, char const*)","relative_address":"0x1941a0"},{"file":"libjvm.dylib","function":"report_java_out_of_memory(char const*)","relative_address":"0x1943d8"},{"file":"libjvm.dylib","function":"CollectedHeap::common_mem_allocate_noinit(KlassHandle, unsigned long, Thread*)","relative_address":"0x70430"},{"file":"libjvm.dylib","function":"TypeArrayKlass::allocate_common(int, bool, Thread*)","relative_address":"0x53eba8"},{"file":"libjvm.dylib","function":"InterpreterRuntime::newarray(JavaThread*, BasicType, int)","relative_address":"0x285b6c"},{"function":"datadog.smoketest.crashtracking.CrashtrackingTestApplication.main([Ljava/lang/String;)V","line":105},{"function":"~StubRoutines::call_stub"},{"file":"libjvm.dylib","function":"JavaCalls::call_helper(JavaValue*, methodHandle*, JavaCallArguments*, Thread*)","relative_address":"0x28f86c"},{"file":"libjvm.dylib","function":"jni_invoke_static(JNIEnv_*, JavaValue*, _jobject*, JNICallType, _jmethodID*, JNI_ArgumentPusher*, Thread*)","relative_address":"0x2d3b44"},{"file":"libjvm.dylib","function":"jni_CallStaticVoidMethod","relative_address":"0x2d7160"},{"file":"java","function":"JavaMain","relative_address":"0x6404"},{"file":"libsystem_pthread.dylib","function":"_pthread_start","relative_address":"0x6f94"},{"file":"libsystem_pthread.dylib","function":"thread_start","relative_address":"0x1d34"},{"function":"datadog.smoketest.crashtracking.CrashtrackingTestApplication.main([Ljava/lang/String;)V","line":105},{"function":"~StubRoutines::call_stub"}]}},"incomplete":false,"metadata":{"family":"java","library_name":"dd-trace-java","library_version":"1.59.0-SNAPSHOT~83d60598da"},"os_info":{"architecture":"aarch64","bitness":"64","os_type":"Mac OS X","version":{"Semantic":[15,7,1]}},"proc_info":{"pid":96267},"uuid":"a4194cd6-8cb3-45fd-9bd9-3af83e0a3ad3","version_id":0} +{"data_schema_version":"1.0","error":{"is_crash":true,"kind":"OutOfMemory","message":"Java heap space","source_type":"Crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"function":"VMError::report_and_die()","path":"libjvm.dylib","relative_address":"0x565d30"},{"function":"report_vm_error(char const*, int, char const*, char const*)","path":"libjvm.dylib","relative_address":"0x1941a0"},{"function":"report_java_out_of_memory(char const*)","path":"libjvm.dylib","relative_address":"0x1943d8"},{"function":"CollectedHeap::common_mem_allocate_noinit(KlassHandle, unsigned long, Thread*)","path":"libjvm.dylib","relative_address":"0x70430"},{"function":"TypeArrayKlass::allocate_common(int, bool, Thread*)","path":"libjvm.dylib","relative_address":"0x53eba8"},{"function":"InterpreterRuntime::newarray(JavaThread*, BasicType, int)","path":"libjvm.dylib","relative_address":"0x285b6c"},{"function":"datadog.smoketest.crashtracking.CrashtrackingTestApplication.main([Ljava/lang/String;)V","line":105},{"function":"~StubRoutines::call_stub"},{"function":"JavaCalls::call_helper(JavaValue*, methodHandle*, JavaCallArguments*, Thread*)","path":"libjvm.dylib","relative_address":"0x28f86c"},{"function":"jni_invoke_static(JNIEnv_*, JavaValue*, _jobject*, JNICallType, _jmethodID*, JNI_ArgumentPusher*, Thread*)","path":"libjvm.dylib","relative_address":"0x2d3b44"},{"function":"jni_CallStaticVoidMethod","path":"libjvm.dylib","relative_address":"0x2d7160"},{"function":"JavaMain","path":"java","relative_address":"0x6404"},{"function":"_pthread_start","path":"libsystem_pthread.dylib","relative_address":"0x6f94"},{"function":"thread_start","path":"libsystem_pthread.dylib","relative_address":"0x1d34"},{"function":"datadog.smoketest.crashtracking.CrashtrackingTestApplication.main([Ljava/lang/String;)V","line":105},{"function":"~StubRoutines::call_stub"}]}},"incomplete":false,"metadata":{"family":"java","library_name":"dd-trace-java","library_version":"1.59.0-SNAPSHOT~896c1ad986"},"os_info":{"architecture":"aarch64","bitness":"64","os_type":"Mac OS X","version":{"Semantic":[15,7,1]}},"proc_info":{"pid":96267},"uuid":"a4194cd6-8cb3-45fd-9bd9-3af83e0a3ad3","version_id":0} diff --git a/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample-crash-for-telemetry.txt b/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample-crash-for-telemetry.txt index 9ea048bda6c..eae4c373e8b 100644 --- a/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample-crash-for-telemetry.txt +++ b/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample-crash-for-telemetry.txt @@ -1 +1 @@ -{"data_schema_version":"1.0","error":{"is_crash":true,"kind":"SIGSEGV","message":"Process terminated by signal SIGSEGV","source_type":"Crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"file":"libjvm.so","function":"vframeStreamForte::forte_next()","relative_address":"0x6b7187"},{"file":"libjvm.so","function":"forte_fill_call_trace_given_top(JavaThread*, ASGCT_CallTrace*, int, frame)","relative_address":"0x6b79ad"},{"file":"libjvm.so","function":"AsyncGetCallTrace","relative_address":"0x6b8123"},{"file":"libjavaProfiler.so","function":"Profiler::getJavaTraceAsync(void*, ASGCT_CallFrame*, int, StackContext*, bool*)","relative_address":"0x146c8"},{"file":"libjavaProfiler.so","function":"Profiler::recordSample(void*, unsigned long long, int, int, Event*)","relative_address":"0x1c18d"},{"file":"libjavaProfiler.so","function":"WallClock::sharedSignalHandler(int, siginfo_t*, void*)","relative_address":"0x1d128"},{"file":"libpthread.so.0","relative_address":"0x12cf0"},{"file":"libjvm.so","function":"JfrStackTrace::record_safe(JavaThread*, int)","relative_address":"0x85f9e9"},{"file":"libjvm.so","function":"JfrStackTraceRepository::record_for_leak_profiler(JavaThread*, int)","relative_address":"0x861650"},{"file":"libjvm.so","function":"ObjectSampler::sample(HeapWordImpl**, unsigned long, JavaThread*)","relative_address":"0xb1ecba"},{"file":"libjvm.so","function":"JfrAllocationTracer::JfrAllocationTracer(Klass const*, HeapWordImpl**, unsigned long, bool, JavaThread*)","relative_address":"0x81abee"},{"file":"libjvm.so","function":"AllocTracer::send_allocation_in_new_tlab(Klass*, HeapWordImpl**, unsigned long, unsigned long, JavaThread*)","relative_address":"0x3afa20"},{"file":"libjvm.so","function":"MemAllocator::allocate() const","relative_address":"0xa8f8ed"},{"file":"libjvm.so","function":"InstanceKlass::allocate_objArray(int, int, JavaThread*)","relative_address":"0x7e443c"},{"file":"libjvm.so","function":"OptoRuntime::new_array_C(Klass*, int, JavaThread*)","relative_address":"0xbe1b59"},{"function":"~RuntimeStub::_new_array_Java"},{"file":"java.base","function":"java.util.HashMap.resize()[Ljava/util/HashMap$Node;","relative_address":"0x00000000000008dc"},{"file":"java.base","function":"java.util.HashMap.putVal(ILjava/lang/Object;Ljava/lang/Object;ZZ)Ljava/lang/Object;","relative_address":"0x0000000000000058"},{"file":"java.base","function":"java.util.HashSet.add(Ljava/lang/Object;)Z","relative_address":"0x000000000000014c"},{"function":"com.REDACT_THIS.util.dom.DOMUtil.doTransform(Lorg/w3c/dom/Node;Ljava/io/PrintStream;IZZZZZ)V","relative_address":"0x0000000000001c40"},{"function":"com.REDACT_THIS.util.dom.DOMUtil.doTransform(Lorg/w3c/dom/Node;Ljava/io/PrintStream;IZZZZZ)V","relative_address":"0x0000000000001ee8"},{"function":"com.REDACT_THIS.util.dom.DOMUtil.doTransform(Lorg/w3c/dom/Node;Ljava/io/PrintStream;IZZZZZ)V","relative_address":"0x0000000000001ee8"},{"function":"com.REDACT_THIS.util.dom.DOMUtil.doTransform(Lorg/w3c/dom/Node;Ljava/io/PrintStream;IZZZZZ)V","relative_address":"0x0000000000003524"},{"function":"com.REDACT_THIS.util.dom.DOMUtil.partToString(Lorg/w3c/dom/Node;)Ljava/lang/String;","relative_address":"0x00000000000003b8"},{"function":"com.REDACT_THIS.message.impl.MessagePartDOMExt.writeExternal(Ljava/io/ObjectOutput;)V","relative_address":"0x0000000000000114"},{"file":"java.base","function":"java.io.ObjectOutputStream.writeOrdinaryObject(Ljava/lang/Object;Ljava/io/ObjectStreamClass;Z)V","relative_address":"0x00000000000005c8"},{"file":"java.base","function":"java.io.ObjectOutputStream.writeObject0(Ljava/lang/Object;Z)V","relative_address":"0x0000000000000a04"},{"file":"java.base","function":"jdk.internal.reflect.GeneratedMethodAccessor173.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;","relative_address":"0x00000000000003d8"},{"file":"java.base","function":"java.io.ObjectOutputStream.writeSerialData(Ljava/lang/Object;Ljava/io/ObjectStreamClass;)V","relative_address":"0x0000000000000434"},{"file":"java.base","function":"java.io.ObjectOutputStream.writeOrdinaryObject(Ljava/lang/Object;Ljava/io/ObjectStreamClass;Z)V","relative_address":"0x0000000000000124"},{"file":"java.base","function":"java.io.ObjectOutputStream.writeObject0(Ljava/lang/Object;Z)V","relative_address":"0x0000000000000a04"},{"function":"com.REDACT_THIS.message.impl.Message.writeExternal(Ljava/io/ObjectOutput;)V","relative_address":"0x00000000000008c4"},{"function":"com.REDACT_THIS.xstream.converters.reflection.ExternalizableConverter.marshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x00000000000003dc"},{"function":"com.REDACT_THIS.xstream.core.TreeMarshaller.convertAnother(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/converters/Converter;)V","relative_address":"0x0000000000000a54"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshallField(Lcom/REDACT_THIS/xstream/converters/MarshallingContext;Ljava/lang/Object;Ljava/lang/reflect/Field;)V","relative_address":"0x00000000000000d0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter$2.writeField(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;)V","relative_address":"0x00000000000009c0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.doMarshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000430"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000354"},{"function":"com.REDACT_THIS.xstream.core.TreeMarshaller.convertAnother(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/converters/Converter;)V","relative_address":"0x0000000000000a54"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshallField(Lcom/REDACT_THIS/xstream/converters/MarshallingContext;Ljava/lang/Object;Ljava/lang/reflect/Field;)V","relative_address":"0x00000000000000d0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter$2.writeField(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;)V","relative_address":"0x00000000000009c0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.doMarshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000430"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000354"},{"function":"com.REDACT_THIS.xstream.core.TreeMarshaller.convertAnother(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/converters/Converter;)V","relative_address":"0x0000000000000a54"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshallField(Lcom/REDACT_THIS/xstream/converters/MarshallingContext;Ljava/lang/Object;Ljava/lang/reflect/Field;)V","relative_address":"0x00000000000000d0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter$2.writeField(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;)V","relative_address":"0x00000000000009c0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.doMarshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000430"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000354"},{"function":"com.REDACT_THIS.xstream.core.TreeMarshaller.convertAnother(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/converters/Converter;)V","relative_address":"0x0000000000000a54"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshallField(Lcom/REDACT_THIS/xstream/converters/MarshallingContext;Ljava/lang/Object;Ljava/lang/reflect/Field;)V","relative_address":"0x00000000000000d0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter$2.writeField(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;)V","relative_address":"0x00000000000009c0"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.doMarshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000430"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V","relative_address":"0x0000000000000354"},{"function":"com.REDACT_THIS.xstream.core.TreeMarshaller.convertAnother(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/converters/Converter;)V","relative_address":"0x0000000000000a54"},{"function":"com.REDACT_THIS.xstream.XStream.toXML(Ljava/lang/Object;Ljava/io/OutputStream;)V","relative_address":"0x00000000000010d8"},{"function":"com.REDACT_THIS.recover.impl.fs.FSJobSerializer.serializeJob(Ljava/lang/String;Lcom/REDACT_THIS/recover/impl/GenericRecoveryJob;)V","relative_address":"0x00000000000010a4"},{"function":"com.REDACT_THIS.recover.impl.db.RecoveryPoolDBImpl.specificSave(Lcom/REDACT_THIS/recover/spi/RecoveryJob;)V","relative_address":"0x0000000000004208"},{"function":"com.REDACT_THIS.recover.impl.REDACT_THIS.saveJob(Lcom/REDACT_THIS/recover/spi/RecoveryJob;ILjava/lang/String;)V","relative_address":"0x0000000000000960"},{"function":"com.REDACT_THIS.frame.core.FrameWorkListener.callbackNewData(Lcom/REDACT_THIS/frame/header/GenericTask;Ljava/util/concurrent/ExecutorService;)V","relative_address":"0x0000000000000f10"},{"function":"com.REDACT_THIS.frame.connection.direct.DirectModeMessageListener.onMessage(Ljavax/jms/Message;)V","relative_address":"0x0000000000001a34"},{"function":"datadog.trace.instrumentation.jms.DatadogMessageListener.onMessage(Ljavax/jms/Message;)V","relative_address":"0x0000000000000440"},{"function":"org.apache.activemq.artemis.jms.client.JMSMessageListenerWrapper.onMessage(Lorg/apache/activemq/artemis/api/core/client/ClientMessage;)V","relative_address":"0x0000000000000908"},{"function":"org.apache.activemq.artemis.core.client.impl.ClientConsumerImpl$Runner.run()V","relative_address":"0x0000000000001018"},{"function":"org.apache.activemq.artemis.utils.actors.ProcessorBase$$Lambda$2929+0x00000007ce44f8f8.run()V","relative_address":"0x00000000000002b4"},{"file":"java.base","function":"java.util.concurrent.ThreadPoolExecutor.runWorker(Ljava/util/concurrent/ThreadPoolExecutor$Worker;)V","relative_address":"0x0000000000000368"},{"file":"java.base","function":"java.util.concurrent.ThreadPoolExecutor$Worker.run()V","relative_address":"0x0000000000000078"},{"function":"org.apache.activemq.artemis.utils.ActiveMQThreadFactory$1.run()V","line":44},{"function":"~StubRoutines::call_stub"}]}},"incomplete":false,"metadata":{"family":"java","library_name":"dd-trace-java","library_version":"1.59.0-SNAPSHOT~83d60598da"},"os_info":{"architecture":"aarch64","bitness":"64","os_type":"Mac OS X","version":{"Semantic":[15,7,1]}},"proc_info":{"pid":161958},"sig_info":{"si_addr":"0x0000000000000070","si_code":1,"si_code_human_readable":"SEGV_MAPERR","si_signo":11,"si_signo_human_readable":"SIGSEGV"},"timestamp":"2023-10-17T20:25:14+08:00","uuid":"a4194cd6-8cb3-45fd-9bd9-3af83e0a3ad3","version_id":0} +{"data_schema_version":"1.0","error":{"is_crash":true,"kind":"SIGSEGV","message":"Process terminated by signal SIGSEGV","source_type":"Crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"function":"vframeStreamForte::forte_next()","path":"libjvm.so","relative_address":"0x6b7187"},{"function":"forte_fill_call_trace_given_top(JavaThread*, ASGCT_CallTrace*, int, frame)","path":"libjvm.so","relative_address":"0x6b79ad"},{"function":"AsyncGetCallTrace","path":"libjvm.so","relative_address":"0x6b8123"},{"function":"Profiler::getJavaTraceAsync(void*, ASGCT_CallFrame*, int, StackContext*, bool*)","path":"libjavaProfiler.so","relative_address":"0x146c8"},{"function":"Profiler::recordSample(void*, unsigned long long, int, int, Event*)","path":"libjavaProfiler.so","relative_address":"0x1c18d"},{"function":"WallClock::sharedSignalHandler(int, siginfo_t*, void*)","path":"libjavaProfiler.so","relative_address":"0x1d128"},{"path":"libpthread.so.0","relative_address":"0x12cf0"},{"function":"JfrStackTrace::record_safe(JavaThread*, int)","path":"libjvm.so","relative_address":"0x85f9e9"},{"function":"JfrStackTraceRepository::record_for_leak_profiler(JavaThread*, int)","path":"libjvm.so","relative_address":"0x861650"},{"function":"ObjectSampler::sample(HeapWordImpl**, unsigned long, JavaThread*)","path":"libjvm.so","relative_address":"0xb1ecba"},{"function":"JfrAllocationTracer::JfrAllocationTracer(Klass const*, HeapWordImpl**, unsigned long, bool, JavaThread*)","path":"libjvm.so","relative_address":"0x81abee"},{"function":"AllocTracer::send_allocation_in_new_tlab(Klass*, HeapWordImpl**, unsigned long, unsigned long, JavaThread*)","path":"libjvm.so","relative_address":"0x3afa20"},{"function":"MemAllocator::allocate() const","path":"libjvm.so","relative_address":"0xa8f8ed"},{"function":"InstanceKlass::allocate_objArray(int, int, JavaThread*)","path":"libjvm.so","relative_address":"0x7e443c"},{"function":"OptoRuntime::new_array_C(Klass*, int, JavaThread*)","path":"libjvm.so","relative_address":"0xbe1b59"},{"function":"~RuntimeStub::_new_array_Java"},{"function":"java.util.HashMap.resize()[Ljava/util/HashMap$Node;"},{"function":"java.util.HashMap.putVal(ILjava/lang/Object;Ljava/lang/Object;ZZ)Ljava/lang/Object;"},{"function":"java.util.HashSet.add(Ljava/lang/Object;)Z"},{"function":"com.REDACT_THIS.util.dom.DOMUtil.doTransform(Lorg/w3c/dom/Node;Ljava/io/PrintStream;IZZZZZ)V"},{"function":"com.REDACT_THIS.util.dom.DOMUtil.doTransform(Lorg/w3c/dom/Node;Ljava/io/PrintStream;IZZZZZ)V"},{"function":"com.REDACT_THIS.util.dom.DOMUtil.doTransform(Lorg/w3c/dom/Node;Ljava/io/PrintStream;IZZZZZ)V"},{"function":"com.REDACT_THIS.util.dom.DOMUtil.doTransform(Lorg/w3c/dom/Node;Ljava/io/PrintStream;IZZZZZ)V"},{"function":"com.REDACT_THIS.util.dom.DOMUtil.partToString(Lorg/w3c/dom/Node;)Ljava/lang/String;"},{"function":"com.REDACT_THIS.message.impl.MessagePartDOMExt.writeExternal(Ljava/io/ObjectOutput;)V"},{"function":"java.io.ObjectOutputStream.writeOrdinaryObject(Ljava/lang/Object;Ljava/io/ObjectStreamClass;Z)V"},{"function":"java.io.ObjectOutputStream.writeObject0(Ljava/lang/Object;Z)V"},{"function":"jdk.internal.reflect.GeneratedMethodAccessor173.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"},{"function":"java.io.ObjectOutputStream.writeSerialData(Ljava/lang/Object;Ljava/io/ObjectStreamClass;)V"},{"function":"java.io.ObjectOutputStream.writeOrdinaryObject(Ljava/lang/Object;Ljava/io/ObjectStreamClass;Z)V"},{"function":"java.io.ObjectOutputStream.writeObject0(Ljava/lang/Object;Z)V"},{"function":"com.REDACT_THIS.message.impl.Message.writeExternal(Ljava/io/ObjectOutput;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.ExternalizableConverter.marshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V"},{"function":"com.REDACT_THIS.xstream.core.TreeMarshaller.convertAnother(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/converters/Converter;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshallField(Lcom/REDACT_THIS/xstream/converters/MarshallingContext;Ljava/lang/Object;Ljava/lang/reflect/Field;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter$2.writeField(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.doMarshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V"},{"function":"com.REDACT_THIS.xstream.core.TreeMarshaller.convertAnother(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/converters/Converter;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshallField(Lcom/REDACT_THIS/xstream/converters/MarshallingContext;Ljava/lang/Object;Ljava/lang/reflect/Field;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter$2.writeField(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.doMarshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V"},{"function":"com.REDACT_THIS.xstream.core.TreeMarshaller.convertAnother(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/converters/Converter;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshallField(Lcom/REDACT_THIS/xstream/converters/MarshallingContext;Ljava/lang/Object;Ljava/lang/reflect/Field;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter$2.writeField(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.doMarshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V"},{"function":"com.REDACT_THIS.xstream.core.TreeMarshaller.convertAnother(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/converters/Converter;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshallField(Lcom/REDACT_THIS/xstream/converters/MarshallingContext;Ljava/lang/Object;Ljava/lang/reflect/Field;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter$2.writeField(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.doMarshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V"},{"function":"com.REDACT_THIS.xstream.converters.reflection.AbstractReflectionConverter.marshal(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/io/HierarchicalStreamWriter;Lcom/REDACT_THIS/xstream/converters/MarshallingContext;)V"},{"function":"com.REDACT_THIS.xstream.core.TreeMarshaller.convertAnother(Ljava/lang/Object;Lcom/REDACT_THIS/xstream/converters/Converter;)V"},{"function":"com.REDACT_THIS.xstream.XStream.toXML(Ljava/lang/Object;Ljava/io/OutputStream;)V"},{"function":"com.REDACT_THIS.recover.impl.fs.FSJobSerializer.serializeJob(Ljava/lang/String;Lcom/REDACT_THIS/recover/impl/GenericRecoveryJob;)V"},{"function":"com.REDACT_THIS.recover.impl.db.RecoveryPoolDBImpl.specificSave(Lcom/REDACT_THIS/recover/spi/RecoveryJob;)V"},{"function":"com.REDACT_THIS.recover.impl.REDACT_THIS.saveJob(Lcom/REDACT_THIS/recover/spi/RecoveryJob;ILjava/lang/String;)V"},{"function":"com.REDACT_THIS.frame.core.FrameWorkListener.callbackNewData(Lcom/REDACT_THIS/frame/header/GenericTask;Ljava/util/concurrent/ExecutorService;)V"},{"function":"com.REDACT_THIS.frame.connection.direct.DirectModeMessageListener.onMessage(Ljavax/jms/Message;)V"},{"function":"datadog.trace.instrumentation.jms.DatadogMessageListener.onMessage(Ljavax/jms/Message;)V"},{"function":"org.apache.activemq.artemis.jms.client.JMSMessageListenerWrapper.onMessage(Lorg/apache/activemq/artemis/api/core/client/ClientMessage;)V"},{"function":"org.apache.activemq.artemis.core.client.impl.ClientConsumerImpl$Runner.run()V"},{"function":"org.apache.activemq.artemis.utils.actors.ProcessorBase$$Lambda$2929+0x00000007ce44f8f8.run()V"},{"function":"java.util.concurrent.ThreadPoolExecutor.runWorker(Ljava/util/concurrent/ThreadPoolExecutor$Worker;)V"},{"function":"java.util.concurrent.ThreadPoolExecutor$Worker.run()V"},{"function":"org.apache.activemq.artemis.utils.ActiveMQThreadFactory$1.run()V","line":44},{"function":"~StubRoutines::call_stub"}]}},"incomplete":false,"metadata":{"family":"java","library_name":"dd-trace-java","library_version":"1.59.0-SNAPSHOT~896c1ad986"},"os_info":{"architecture":"aarch64","bitness":"64","os_type":"Mac OS X","version":{"Semantic":[15,7,1]}},"proc_info":{"pid":161958},"sig_info":{"si_addr":"0x0000000000000070","si_code":1,"si_code_human_readable":"SEGV_MAPERR","si_signo":11,"si_signo_human_readable":"SIGSEGV"},"timestamp":"2023-10-17T20:25:14+08:00","uuid":"a4194cd6-8cb3-45fd-9bd9-3af83e0a3ad3","version_id":0} diff --git a/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample_oom.txt b/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample_oom.txt index 2721d566a58..acc570a28d9 100644 --- a/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample_oom.txt +++ b/dd-java-agent/agent-crashtracking/src/test/resources/golden/telemetry/sample_oom.txt @@ -1 +1 @@ -{"data_schema_version":"1.0","error":{"is_crash":true,"kind":"OutOfMemory","message":"Java heap space","source_type":"Crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"file":"libjvm.dylib","function":"VMError::report_and_die(int, char const*, char const*, char*, Thread*, unsigned char*, void*, void*, char const*, int, unsigned long)","relative_address":"0xaa5f24"},{"file":"libjvm.dylib","function":"report_fatal(VMErrorType, char const*, int, char const*, ...)","relative_address":"0x314c74"},{"file":"libjvm.dylib","function":"report_java_out_of_memory(char const*)","relative_address":"0x315248"},{"file":"libjvm.dylib","function":"MemAllocator::Allocation::check_out_of_memory()","relative_address":"0x7d9764"},{"file":"libjvm.dylib","function":"MemAllocator::allocate() const","relative_address":"0x7da2f4"},{"file":"libjvm.dylib","function":"CollectedHeap::array_allocate(Klass*, unsigned long, int, bool, JavaThread*)","relative_address":"0x2c3de4"},{"file":"libjvm.dylib","function":"OptoRuntime::new_array_C(Klass*, int, JavaThread*)","relative_address":"0x8ea9ec"},{"function":"~RuntimeStub::_new_array_Java","relative_address":"0x00000001124cb638"},{"file":"java.base","function":"java.nio.ByteBuffer.allocate(I)Ljava/nio/ByteBuffer;","relative_address":"0x0000000000000228"},{"function":"datadog.communication.serialization.FlushingBuffer.(ILdatadog/communication/serialization/ByteBufferConsumer;)V","line":6},{"function":"datadog.trace.agent.common.writer.PayloadDispatcherImpl.selectMapper()V","line":126},{"function":"datadog.trace.agent.common.writer.PayloadDispatcherImpl.addTrace(Ljava/util/List;)V","line":1},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.onEvent(Ljava/lang/Object;)V","line":22},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.consumeFromPrimaryQueue()V","line":21},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.runDutyCycle()V","line":12},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.run()V","line":1},{"function":"java.lang.Thread.runWith(Ljava/lang/Object;Ljava/lang/Runnable;)V"},{"function":"java.lang.Thread.run()V"},{"function":"~StubRoutines::call_stub","relative_address":"0x00000001123b0140"}]}},"incomplete":false,"metadata":{"family":"java","library_name":"dd-trace-java","library_version":"1.59.0-SNAPSHOT~4661a03cdb"},"os_info":{"architecture":"aarch64","bitness":"64","os_type":"Mac OS X","version":{"Semantic":[15,7,1]}},"proc_info":{"pid":74045},"timestamp":"2025-11-24T09:43:29+01:00","uuid":"a4194cd6-8cb3-45fd-9bd9-3af83e0a3ad3","version_id":0} +{"data_schema_version":"1.0","error":{"is_crash":true,"kind":"OutOfMemory","message":"Java heap space","source_type":"Crashtracking","stack":{"format":"CrashTrackerV1","frames":[{"function":"VMError::report_and_die(int, char const*, char const*, char*, Thread*, unsigned char*, void*, void*, char const*, int, unsigned long)","path":"libjvm.dylib","relative_address":"0xaa5f24"},{"function":"report_fatal(VMErrorType, char const*, int, char const*, ...)","path":"libjvm.dylib","relative_address":"0x314c74"},{"function":"report_java_out_of_memory(char const*)","path":"libjvm.dylib","relative_address":"0x315248"},{"function":"MemAllocator::Allocation::check_out_of_memory()","path":"libjvm.dylib","relative_address":"0x7d9764"},{"function":"MemAllocator::allocate() const","path":"libjvm.dylib","relative_address":"0x7da2f4"},{"function":"CollectedHeap::array_allocate(Klass*, unsigned long, int, bool, JavaThread*)","path":"libjvm.dylib","relative_address":"0x2c3de4"},{"function":"OptoRuntime::new_array_C(Klass*, int, JavaThread*)","path":"libjvm.dylib","relative_address":"0x8ea9ec"},{"function":"~RuntimeStub::_new_array_Java","relative_address":"0x00000001124cb638"},{"function":"java.nio.ByteBuffer.allocate(I)Ljava/nio/ByteBuffer;"},{"function":"datadog.communication.serialization.FlushingBuffer.(ILdatadog/communication/serialization/ByteBufferConsumer;)V","line":6},{"function":"datadog.trace.agent.common.writer.PayloadDispatcherImpl.selectMapper()V","line":126},{"function":"datadog.trace.agent.common.writer.PayloadDispatcherImpl.addTrace(Ljava/util/List;)V","line":1},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.onEvent(Ljava/lang/Object;)V","line":22},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.consumeFromPrimaryQueue()V","line":21},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.runDutyCycle()V","line":12},{"function":"datadog.trace.agent.common.writer.TraceProcessingWorker$TraceSerializingHandler.run()V","line":1},{"function":"java.lang.Thread.runWith(Ljava/lang/Object;Ljava/lang/Runnable;)V"},{"function":"java.lang.Thread.run()V"},{"function":"~StubRoutines::call_stub","relative_address":"0x00000001123b0140"}]}},"incomplete":false,"metadata":{"family":"java","library_name":"dd-trace-java","library_version":"1.59.0-SNAPSHOT~896c1ad986"},"os_info":{"architecture":"aarch64","bitness":"64","os_type":"Mac OS X","version":{"Semantic":[15,7,1]}},"proc_info":{"pid":74045},"timestamp":"2025-11-24T09:43:29+01:00","uuid":"a4194cd6-8cb3-45fd-9bd9-3af83e0a3ad3","version_id":0}