Skip to content

Commit b7c2fd7

Browse files
committed
feat(crashtracking): Add crashtracking.experimental.register-mapping.enabled
1 parent 3ddb175 commit b7c2fd7

File tree

10 files changed

+135
-7
lines changed

10 files changed

+135
-7
lines changed

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

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public static class StoredConfig {
3535
final String reportUUID;
3636
final boolean agentless;
3737
final boolean sendToErrorTracking;
38+
final boolean registerMappingEnabled;
3839

3940
StoredConfig(
4041
String reportUUID,
@@ -45,7 +46,8 @@ public static class StoredConfig {
4546
String processTags,
4647
String runtimeId,
4748
boolean agentless,
48-
boolean sendToErrorTracking) {
49+
boolean sendToErrorTracking,
50+
boolean registerMappingEnabled) {
4951
this.service = service;
5052
this.env = env;
5153
this.version = version;
@@ -55,6 +57,11 @@ public static class StoredConfig {
5557
this.reportUUID = reportUUID;
5658
this.agentless = agentless;
5759
this.sendToErrorTracking = sendToErrorTracking;
60+
this.registerMappingEnabled = registerMappingEnabled;
61+
}
62+
63+
public CrashUploaderSettings toCrashUploaderSettings() {
64+
return new CrashUploaderSettings(registerMappingEnabled);
5865
}
5966

6067
public static class Builder {
@@ -67,6 +74,7 @@ public static class Builder {
6774
String reportUUID;
6875
boolean agentless;
6976
boolean sendToErrorTracking;
77+
boolean registerMappingEnabled;
7078

7179
public Builder(Config config) {
7280
// get sane defaults
@@ -77,6 +85,8 @@ public Builder(Config config) {
7785
this.reportUUID = RandomUtils.randomUUID().toString();
7886
this.agentless = config.isCrashTrackingAgentless();
7987
this.sendToErrorTracking = config.isCrashTrackingErrorsIntakeEnabled();
88+
this.registerMappingEnabled =
89+
config.isCrashTrackingExperimentalRegisterMappingEnabled();
8090
}
8191

8292
public Builder service(String service) {
@@ -119,6 +129,11 @@ public Builder agentless(boolean agentless) {
119129
return this;
120130
}
121131

132+
public Builder registerMappingEnabled(boolean registerMappingEnabled) {
133+
this.registerMappingEnabled = registerMappingEnabled;
134+
return this;
135+
}
136+
122137
// @VisibleForTesting
123138
Builder reportUUID(String reportUUID) {
124139
this.reportUUID = reportUUID;
@@ -135,7 +150,8 @@ public StoredConfig build() {
135150
processTags,
136151
runtimeId,
137152
agentless,
138-
sendToErrorTracking);
153+
sendToErrorTracking,
154+
registerMappingEnabled);
139155
}
140156
}
141157
}
@@ -194,6 +210,10 @@ static void writeConfigToFile(Config config, Path cfgPath, String... additionalE
194210
writeEntry(bw, "java_home", SystemProperties.get("java.home"));
195211
writeEntry(bw, "agentless", Boolean.toString(config.isCrashTrackingAgentless()));
196212
writeEntry(bw, "upload_to_et", Boolean.toString(config.isCrashTrackingErrorsIntakeEnabled()));
213+
writeEntry(
214+
bw,
215+
"register_mapping",
216+
Boolean.toString(config.isCrashTrackingExperimentalRegisterMappingEnabled()));
197217

198218
Runtime.getRuntime()
199219
.addShutdownHook(
@@ -257,6 +277,9 @@ public static StoredConfig readConfig(Config config, Path scriptPath) {
257277
case "upload_to_et":
258278
cfgBuilder.sendToErrorTracking(Boolean.parseBoolean(value));
259279
break;
280+
case "register_mapping":
281+
cfgBuilder.registerMappingEnabled(Boolean.parseBoolean(value));
282+
break;
260283
default:
261284
// ignore
262285
break;

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,18 @@ public static CrashLog fromJ9Javacore(String uuid, String javacoreContent) {
3333
* </ul>
3434
*/
3535
public static CrashLog parse(String uuid, String content) {
36+
return parse(uuid, content, new CrashUploaderSettings(true));
37+
}
38+
39+
/**
40+
* Auto-detect crash log format and parse accordingly, using the provided settings to control
41+
* which sections are included in the result.
42+
*/
43+
public static CrashLog parse(String uuid, String content, CrashUploaderSettings settings) {
3644
if (isJ9Javacore(content)) {
3745
return fromJ9Javacore(uuid, content);
3846
}
39-
return fromHotspotCrashLog(uuid, content);
47+
return new HotspotCrashLogParser(settings).parse(uuid, content);
4048
}
4149

4250
/** Check if the content appears to be a J9 javacore file. */

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,8 @@ void remoteUpload(
257257
final String uuid = storedConfig.reportUUID;
258258
try {
259259
// Auto-detect crash log format (HotSpot hs_err or J9 javacore)
260-
CrashLog crashLog = CrashLogParser.parse(uuid, fileContent);
260+
CrashLog crashLog =
261+
CrashLogParser.parse(uuid, fileContent, storedConfig.toCrashUploaderSettings());
261262
if (sendToTelemetry) {
262263
uploadToTelemetry(crashLog);
263264
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package datadog.crashtracking;
2+
3+
/** Crash-tracking-specific settings controlling which sections are included in parsed crash reports. */
4+
public final class CrashUploaderSettings {
5+
6+
private final boolean registerMappingEnabled;
7+
8+
public CrashUploaderSettings(boolean registerMappingEnabled) {
9+
this.registerMappingEnabled = registerMappingEnabled;
10+
}
11+
12+
/** Whether the register-to-memory mapping section should be included in parsed crash reports. */
13+
public boolean isRegisterMappingEnabled() {
14+
return registerMappingEnabled;
15+
}
16+
}

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

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import static java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME;
44

55
import datadog.common.version.VersionInfo;
6+
import datadog.crashtracking.CrashUploaderSettings;
67
import datadog.crashtracking.buildid.BuildIdCollector;
78
import datadog.crashtracking.buildid.BuildInfo;
89
import datadog.crashtracking.dto.CrashLog;
@@ -72,9 +73,15 @@ enum State {
7273
}
7374

7475
private State state = State.NEW;
76+
private final CrashUploaderSettings settings;
7577

7678
public HotspotCrashLogParser() {
79+
this(new CrashUploaderSettings(true));
80+
}
81+
82+
public HotspotCrashLogParser(CrashUploaderSettings settings) {
7783
this.buildIdCollector = new BuildIdCollector();
84+
this.settings = settings;
7885
}
7986

8087
private static final Pattern PLUS_SPLITTER = Pattern.compile("\\+");
@@ -598,12 +605,16 @@ public CrashLog parse(String uuid, String crashLog) {
598605
Metadata metadata = new Metadata("dd-trace-java", VersionInfo.VERSION, "java", null);
599606
Integer parsedPid = safelyParseInt(pid);
600607
ProcInfo procInfo = parsedPid != null ? new ProcInfo(parsedPid) : null;
601-
registerToMemoryMapping.replaceAll((k, v) -> RedactUtils.redactRegisterToMemoryMapping(v));
608+
Map<String, String> resolvedMapping = null;
609+
if (settings.isRegisterMappingEnabled() && !registerToMemoryMapping.isEmpty()) {
610+
registerToMemoryMapping.replaceAll((k, v) -> RedactUtils.redactRegisterToMemoryMapping(v));
611+
resolvedMapping = registerToMemoryMapping;
612+
}
602613
Experimental experimental =
603614
!registers.isEmpty()
604-
|| !registerToMemoryMapping.isEmpty()
615+
|| resolvedMapping != null
605616
|| (runtimeArgs != null && !runtimeArgs.isEmpty())
606-
? new Experimental(registers, registerToMemoryMapping, runtimeArgs)
617+
? new Experimental(registers, resolvedMapping, runtimeArgs)
607618
: null;
608619
DynamicLibs files =
609620
(dynamicLibraryLines != null && !dynamicLibraryLines.isEmpty())

dd-java-agent/agent-crashtracking/src/test/java/datadog/crashtracking/ConfigManagerTest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public void testConfigWriteAndRead() throws IOException {
2424
.thenReturn(new WellKnownTags("1234", "", "env", "service", "version", ""));
2525
when(config.isCrashTrackingAgentless()).thenReturn(false);
2626
when(config.isCrashTrackingErrorsIntakeEnabled()).thenReturn(true);
27+
when(config.isCrashTrackingExperimentalRegisterMappingEnabled()).thenReturn(true);
2728
when(config.getMergedCrashTrackingTags()).thenReturn(Collections.singletonMap("key", "value"));
2829
File tmpFile = File.createTempFile("ConfigManagerTest", null);
2930
tmpFile.deleteOnExit();
@@ -41,6 +42,7 @@ public void testConfigWriteAndRead() throws IOException {
4142
deserialized.processTags);
4243
assertFalse(deserialized.agentless);
4344
assertTrue(deserialized.sendToErrorTracking);
45+
assertTrue(deserialized.registerMappingEnabled);
4446
}
4547

4648
@Test
@@ -56,5 +58,6 @@ public void testStoredConfigDefaults() {
5658
assertEquals("env", storedConfig.env);
5759
assertFalse(storedConfig.agentless);
5860
assertFalse(storedConfig.sendToErrorTracking);
61+
assertFalse(storedConfig.registerMappingEnabled);
5962
}
6063
}

dd-java-agent/agent-crashtracking/src/test/java/datadog/crashtracking/CrashUploaderTest.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,7 @@ public void testErrorTrackingSerializesRegisterToMemoryMapping() throws Exceptio
401401
.processTags("a:b")
402402
.runtimeId("1234")
403403
.tags(ConfigManager.getMergedTagsForSerialization(Config.get()))
404+
.registerMappingEnabled(true)
404405
.build();
405406

406407
uploader = new CrashUploader(config, crashConfig);
@@ -418,6 +419,28 @@ public void testErrorTrackingSerializesRegisterToMemoryMapping() throws Exceptio
418419
assertThat(mapping.get("RDI").asText()).isEqualTo("0x0 is NULL");
419420
}
420421

422+
@Test
423+
public void testErrorTrackingOmitsRegisterToMemoryMappingByDefault() throws Exception {
424+
// registerMappingEnabled defaults to false — the mapping must not appear in the payload
425+
ConfigManager.StoredConfig crashConfig =
426+
new ConfigManager.StoredConfig.Builder(config)
427+
.reportUUID(SAMPLE_UUID)
428+
.processTags("a:b")
429+
.runtimeId("1234")
430+
.tags(ConfigManager.getMergedTagsForSerialization(Config.get()))
431+
.build();
432+
433+
uploader = new CrashUploader(config, crashConfig);
434+
server.enqueue(new MockResponse().setResponseCode(200));
435+
uploader.remoteUpload(readFileAsString("sample-crash.txt"), false, true);
436+
437+
final RecordedRequest recordedRequest = server.takeRequest(5, TimeUnit.SECONDS);
438+
final ObjectMapper mapper = new ObjectMapper();
439+
final JsonNode event = mapper.readTree(recordedRequest.getBody().readUtf8());
440+
441+
assertThat(event.at("/experimental/register_to_memory_mapping").isMissingNode()).isTrue();
442+
}
443+
421444
private void assertCommonHeader(JsonNode event) {
422445
assertEquals(TELEMETRY_API_VERSION, event.get("api_version").asText());
423446
assertEquals("logs", event.get("request_type").asText());

dd-java-agent/agent-crashtracking/src/test/java/datadog/crashtracking/parsers/HotspotCrashLogParserTest.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import static org.junit.jupiter.api.Assertions.assertNotNull;
88
import static org.junit.jupiter.api.Assertions.assertTrue;
99

10+
import datadog.crashtracking.CrashUploaderSettings;
1011
import datadog.crashtracking.dto.CrashLog;
1112
import java.io.BufferedReader;
1213
import java.io.IOException;
@@ -304,6 +305,31 @@ public void testParseCurrentThreadName(String line, String expected) {
304305
HotspotCrashLogParser.parseCurrentThreadName(line));
305306
}
306307

308+
@Test
309+
public void testRegisterToMemoryMappingExcludedWhenDisabled() throws Exception {
310+
CrashLog crashLog =
311+
new HotspotCrashLogParser(new CrashUploaderSettings(false))
312+
.parse(UUID.randomUUID().toString(), readFileAsString("sample-crash.txt"));
313+
314+
assertNotNull(crashLog.experimental, "registers and runtimeArgs should still be populated");
315+
assertThat(crashLog.experimental.registerToMemoryMapping)
316+
.as("registerToMemoryMapping should be absent when disabled")
317+
.isNull();
318+
}
319+
320+
@Test
321+
public void testRegisterToMemoryMappingIncludedWhenEnabled() throws Exception {
322+
CrashLog crashLog =
323+
new HotspotCrashLogParser(new CrashUploaderSettings(true))
324+
.parse(UUID.randomUUID().toString(), readFileAsString("sample-crash.txt"));
325+
326+
assertNotNull(crashLog.experimental);
327+
assertNotNull(crashLog.experimental.registerToMemoryMapping);
328+
assertFalse(
329+
crashLog.experimental.registerToMemoryMapping.isEmpty(),
330+
"registerToMemoryMapping should be populated when enabled");
331+
}
332+
307333
private String readFileAsString(String resource) throws IOException {
308334
try (InputStream stream = getClass().getClassLoader().getResourceAsStream(resource)) {
309335
return new BufferedReader(

dd-trace-api/src/main/java/datadog/trace/api/config/CrashTrackingConfig.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,9 @@ public final class CrashTrackingConfig {
3535
"crashtracking.debug.autoconfig.enable";
3636
public static final boolean CRASH_TRACKING_ENABLE_AUTOCONFIG_DEFAULT = false;
3737

38+
public static final String CRASH_TRACKING_EXPERIMENTAL_REGISTER_MAPPING_ENABLED =
39+
"crashtracking.experimental.register-mapping.enabled";
40+
public static final boolean CRASH_TRACKING_EXPERIMENTAL_REGISTER_MAPPING_ENABLED_DEFAULT = false;
41+
3842
private CrashTrackingConfig() {}
3943
}

internal-api/src/main/java/datadog/trace/api/Config.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,8 @@
298298
import static datadog.trace.api.config.CrashTrackingConfig.CRASH_TRACKING_AGENTLESS_DEFAULT;
299299
import static datadog.trace.api.config.CrashTrackingConfig.CRASH_TRACKING_ERRORS_INTAKE_ENABLED;
300300
import static datadog.trace.api.config.CrashTrackingConfig.CRASH_TRACKING_ERRORS_INTAKE_ENABLED_DEFAULT;
301+
import static datadog.trace.api.config.CrashTrackingConfig.CRASH_TRACKING_EXPERIMENTAL_REGISTER_MAPPING_ENABLED;
302+
import static datadog.trace.api.config.CrashTrackingConfig.CRASH_TRACKING_EXPERIMENTAL_REGISTER_MAPPING_ENABLED_DEFAULT;
301303
import static datadog.trace.api.config.CrashTrackingConfig.CRASH_TRACKING_TAGS;
302304
import static datadog.trace.api.config.CwsConfig.CWS_ENABLED;
303305
import static datadog.trace.api.config.CwsConfig.CWS_TLS_REFRESH;
@@ -1001,6 +1003,7 @@ public static String getHostName() {
10011003
private final boolean crashTrackingAgentless;
10021004
private final Map<String, String> crashTrackingTags;
10031005
private final boolean crashTrackingErrorsIntakeEnabled;
1006+
private final boolean crashTrackingExperimentalRegisterMappingEnabled;
10041007

10051008
private final boolean clientIpEnabled;
10061009

@@ -2216,6 +2219,10 @@ PROFILING_DATADOG_PROFILER_ENABLED, isDatadogProfilerSafeInCurrentEnvironment())
22162219
crashTrackingErrorsIntakeEnabled =
22172220
configProvider.getBoolean(
22182221
CRASH_TRACKING_ERRORS_INTAKE_ENABLED, CRASH_TRACKING_ERRORS_INTAKE_ENABLED_DEFAULT);
2222+
crashTrackingExperimentalRegisterMappingEnabled =
2223+
configProvider.getBoolean(
2224+
CRASH_TRACKING_EXPERIMENTAL_REGISTER_MAPPING_ENABLED,
2225+
CRASH_TRACKING_EXPERIMENTAL_REGISTER_MAPPING_ENABLED_DEFAULT);
22192226

22202227
float telemetryInterval =
22212228
configProvider.getFloat(TELEMETRY_HEARTBEAT_INTERVAL, DEFAULT_TELEMETRY_HEARTBEAT_INTERVAL);
@@ -3809,6 +3816,10 @@ public boolean isCrashTrackingErrorsIntakeEnabled() {
38093816
return crashTrackingErrorsIntakeEnabled;
38103817
}
38113818

3819+
public boolean isCrashTrackingExperimentalRegisterMappingEnabled() {
3820+
return crashTrackingExperimentalRegisterMappingEnabled;
3821+
}
3822+
38123823
public boolean isTelemetryEnabled() {
38133824
return instrumenterConfig.isTelemetryEnabled();
38143825
}
@@ -6114,6 +6125,8 @@ public String toString() {
61146125
+ crashTrackingAgentless
61156126
+ ", crashTrackingErrorsIntakeEnabled="
61166127
+ crashTrackingErrorsIntakeEnabled
6128+
+ ", crashTrackingExperimentalRegisterMappingEnabled="
6129+
+ crashTrackingExperimentalRegisterMappingEnabled
61176130
+ ", remoteConfigEnabled="
61186131
+ remoteConfigEnabled
61196132
+ ", remoteConfigUrl="

0 commit comments

Comments
 (0)