Skip to content

Commit f10fc7e

Browse files
committed
chore(crashtracking): Report VM argument flags
1 parent 3e22e27 commit f10fc7e

File tree

10 files changed

+648
-18
lines changed

10 files changed

+648
-18
lines changed

dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/CrashUploader.java

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -575,15 +575,27 @@ private RequestBody makeErrorTrackingRequestBody(@Nonnull CrashLog payload, bool
575575
writer.endObject();
576576
}
577577
// experimental
578-
if (payload.experimental != null && payload.experimental.ucontext != null) {
578+
if (payload.experimental != null
579+
&& (payload.experimental.ucontext != null
580+
|| payload.experimental.runtimeArgs != null)) {
579581
writer.name("experimental");
580582
writer.beginObject();
581-
writer.name("ucontext");
582-
writer.beginObject();
583-
for (Map.Entry<String, String> entry : payload.experimental.ucontext.entrySet()) {
584-
writer.name(entry.getKey()).value(entry.getValue());
583+
if (payload.experimental.ucontext != null) {
584+
writer.name("ucontext");
585+
writer.beginObject();
586+
for (Map.Entry<String, String> entry : payload.experimental.ucontext.entrySet()) {
587+
writer.name(entry.getKey()).value(entry.getValue());
588+
}
589+
writer.endObject();
590+
}
591+
if (payload.experimental.runtimeArgs != null) {
592+
writer.name("runtime_args");
593+
writer.beginArray();
594+
for (String arg : payload.experimental.runtimeArgs) {
595+
writer.value(arg);
596+
}
597+
writer.endArray();
585598
}
586-
writer.endObject();
587599
writer.endObject();
588600
}
589601
// files (e.g. /proc/self/maps or dynamic_libraries)
Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,34 @@
11
package datadog.crashtracking.dto;
22

3+
import com.squareup.moshi.Json;
4+
import java.util.List;
35
import java.util.Map;
46
import java.util.Objects;
57

68
public final class Experimental {
79
public final Map<String, String> ucontext;
810

11+
@Json(name = "runtime_args")
12+
public final List<String> runtimeArgs;
13+
914
public Experimental(Map<String, String> ucontext) {
15+
this(ucontext, null);
16+
}
17+
18+
public Experimental(Map<String, String> ucontext, List<String> runtimeArgs) {
1019
this.ucontext = ucontext;
20+
this.runtimeArgs = runtimeArgs;
1121
}
1222

1323
@Override
1424
public boolean equals(Object o) {
1525
if (!(o instanceof Experimental)) return false;
1626
Experimental that = (Experimental) o;
17-
return Objects.equals(ucontext, that.ucontext);
27+
return Objects.equals(ucontext, that.ucontext) && Objects.equals(runtimeArgs, that.runtimeArgs);
1828
}
1929

2030
@Override
2131
public int hashCode() {
22-
return Objects.hash(ucontext);
32+
return Objects.hash(ucontext, runtimeArgs);
2333
}
2434
}

dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/parsers/HotspotCrashLogParser.java

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
* resulting {@link datadog.crashtracking.dto.CrashLog} will be marked {@code incomplete}.
4444
*/
4545
public final class HotspotCrashLogParser {
46+
private static final String HOTSPOT_JVM_ARGS_PREFIX = "jvm_args:";
4647
private static final DateTimeFormatter ZONED_DATE_TIME_FORMATTER =
4748
DateTimeFormatter.ofPattern("EEE MMM ppd HH:mm:ss yyyy zzz", Locale.getDefault());
4849
private static final DateTimeFormatter OFFSET_DATE_TIME_FORMATTER =
@@ -62,7 +63,8 @@ enum State {
6263
THREAD,
6364
STACKTRACE,
6465
REGISTERS,
65-
SEEK_DYNAMIC_LIBRARIES,
66+
PROCESS,
67+
VM_ARGUMENTS,
6668
DYNAMIC_LIBRARIES,
6769
SYSTEM,
6870
DONE
@@ -332,6 +334,13 @@ static String parseCurrentThreadName(String line) {
332334
return threadDescriptor;
333335
}
334336

337+
private static List<String> parseHotspotJvmArgs(String line) {
338+
if (line == null || !line.startsWith(HOTSPOT_JVM_ARGS_PREFIX)) {
339+
return null;
340+
}
341+
return RuntimeArgs.parseVmArgs(line.substring(HOTSPOT_JVM_ARGS_PREFIX.length()));
342+
}
343+
335344
public CrashLog parse(String uuid, String crashLog) {
336345
SigInfo sigInfo = null;
337346
String pid = null;
@@ -342,6 +351,7 @@ public CrashLog parse(String uuid, String crashLog) {
342351
boolean incomplete = false;
343352
String oomMessage = null;
344353
Map<String, String> registers = null;
354+
List<String> runtimeArgs = null;
345355
List<String> dynamicLibraryLines = null;
346356
String dynamicLibraryKey = null;
347357

@@ -420,7 +430,7 @@ public CrashLog parse(String uuid, String crashLog) {
420430
registers = new LinkedHashMap<>();
421431
state = State.REGISTERS;
422432
} else if (line.contains("P R O C E S S")) {
423-
state = State.SEEK_DYNAMIC_LIBRARIES;
433+
state = State.PROCESS;
424434
} else {
425435
// Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
426436
final StackFrame frame = parseLine(line);
@@ -440,18 +450,27 @@ public CrashLog parse(String uuid, String crashLog) {
440450
}
441451
}
442452
break;
443-
case SEEK_DYNAMIC_LIBRARIES:
444-
if (line.startsWith("Dynamic libraries:")) {
453+
case PROCESS:
454+
if (runtimeArgs == null && line.startsWith("VM Arguments:")) {
455+
state = State.VM_ARGUMENTS;
456+
} else if (line.startsWith("Dynamic libraries:")) {
445457
state = State.DYNAMIC_LIBRARIES;
446458
} else if (line.contains("S Y S T E M")) {
447459
state = State.SYSTEM;
448460
} else if (line.equals("END.")) {
449461
state = State.DONE;
450462
}
451463
break;
464+
case VM_ARGUMENTS:
465+
if (line.isEmpty()) {
466+
state = State.PROCESS;
467+
} else if (runtimeArgs == null && line.startsWith(HOTSPOT_JVM_ARGS_PREFIX)) {
468+
runtimeArgs = parseHotspotJvmArgs(line);
469+
}
470+
break;
452471
case DYNAMIC_LIBRARIES:
453472
if (line.isEmpty()) {
454-
state = State.SEEK_DYNAMIC_LIBRARIES;
473+
state = State.PROCESS;
455474
} else {
456475
if (dynamicLibraryKey == null) {
457476
dynamicLibraryKey = detectDynamicLibrariesKey(line);
@@ -491,8 +510,8 @@ public CrashLog parse(String uuid, String crashLog) {
491510
}
492511
}
493512

494-
// SEEK_DYNAMIC_LIBRARIES and SYSTEM sections are late enough that all critical data is captured
495-
if (state != State.DONE && state != State.SEEK_DYNAMIC_LIBRARIES && state != State.SYSTEM) {
513+
// PROCESS and SYSTEM sections are late enough that all critical data is captured
514+
if (state != State.DONE && state != State.PROCESS && state != State.SYSTEM) {
496515
// incomplete crash log
497516
incomplete = true;
498517
}
@@ -553,7 +572,10 @@ public CrashLog parse(String uuid, String crashLog) {
553572
Integer parsedPid = safelyParseInt(pid);
554573
ProcInfo procInfo = parsedPid != null ? new ProcInfo(parsedPid) : null;
555574
Experimental experimental =
556-
(registers != null && !registers.isEmpty()) ? new Experimental(registers) : null;
575+
(registers != null && !registers.isEmpty())
576+
|| (runtimeArgs != null && !runtimeArgs.isEmpty())
577+
? new Experimental(registers, runtimeArgs)
578+
: null;
557579
DynamicLibs files =
558580
(dynamicLibraryLines != null && !dynamicLibraryLines.isEmpty())
559581
? new DynamicLibs(dynamicLibraryKey, dynamicLibraryLines)

dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/parsers/J9JavacoreParser.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
* </ul>
4646
*/
4747
public final class J9JavacoreParser {
48+
private static final String J9_USER_ARG_PREFIX = "2CIUSERARG";
4849

4950
private final BuildIdCollector buildIdCollector;
5051

@@ -117,10 +118,17 @@ public CrashLog parse(String uuid, String javacoreContent) {
117118
boolean foundThreadSection = false;
118119

119120
Map<String, String> registers = null;
121+
RuntimeArgs j9UserArgs = new RuntimeArgs();
120122

121123
String[] lines = NEWLINE_SPLITTER.split(javacoreContent);
122124

123125
for (String line : lines) {
126+
// Full command line is available under 1CICMDLINE, but it's harder to parse properly,
127+
// than adding them from 2CIUSERARGS
128+
if (line.startsWith(J9_USER_ARG_PREFIX)) {
129+
j9UserArgs.addArg(line.substring(J9_USER_ARG_PREFIX.length()).trim());
130+
}
131+
124132
// Track section changes
125133
if (line.startsWith(SECTION_MARKER)) {
126134
currentSection = detectSection(line);
@@ -290,8 +298,12 @@ public CrashLog parse(String uuid, String javacoreContent) {
290298
Metadata metadata = new Metadata("dd-trace-java", VersionInfo.VERSION, "java", null);
291299
Integer parsedPid = safelyParseInt(pid);
292300
ProcInfo procInfo = parsedPid != null ? new ProcInfo(parsedPid) : null;
301+
List<String> runtimeArgs = j9UserArgs.build();
293302
Experimental experimental =
294-
(registers != null && !registers.isEmpty()) ? new Experimental(registers) : null;
303+
(registers != null && !registers.isEmpty())
304+
|| (runtimeArgs != null && !runtimeArgs.isEmpty())
305+
? new Experimental(registers, runtimeArgs)
306+
: null;
295307

296308
return new CrashLog(
297309
uuid,

0 commit comments

Comments
 (0)