Skip to content

Commit 6b33361

Browse files
committed
Crashtracking: send ping message
1 parent 92a857d commit 6b33361

File tree

7 files changed

+70
-34
lines changed

7 files changed

+70
-34
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import datadog.trace.api.ProcessTags;
1010
import datadog.trace.api.WellKnownTags;
1111
import datadog.trace.util.PidHelper;
12+
import datadog.trace.util.RandomUtils;
1213
import java.io.BufferedReader;
1314
import java.io.BufferedWriter;
1415
import java.io.IOException;
@@ -31,6 +32,7 @@ public static class StoredConfig {
3132
final String tags;
3233
final String processTags;
3334
final String runtimeId;
35+
final String reportUUID;
3436

3537
StoredConfig(
3638
String service,
@@ -45,6 +47,7 @@ public static class StoredConfig {
4547
this.tags = tags;
4648
this.processTags = processTags;
4749
this.runtimeId = runtimeId;
50+
this.reportUUID = RandomUtils.randomUUID().toString();
4851
}
4952

5053
public static class Builder {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import datadog.crashtracking.parsers.HotspotCrashLogParser;
55

66
public final class CrashLogParser {
7-
public static CrashLog fromHotspotCrashLog(String logText) {
8-
return new HotspotCrashLogParser().parse(logText);
7+
public static CrashLog fromHotspotCrashLog(String uuid, String logText) {
8+
return new HotspotCrashLogParser().parse(uuid, logText);
99
}
1010
}

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

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,6 @@ public final class CrashUploader {
6161

6262
private static final MediaType APPLICATION_JSON =
6363
MediaType.get("application/json; charset=utf-8");
64-
private static final MediaType APPLICATION_OCTET_STREAM =
65-
MediaType.parse("application/octet-stream");
6664

6765
private final Config config;
6866
private final ConfigManager.StoredConfig storedConfig;
@@ -114,10 +112,32 @@ public CrashUploader(@Nonnull final ConfigManager.StoredConfig storedConfig) {
114112
CRASH_TRACKING_UPLOAD_TIMEOUT, CRASH_TRACKING_UPLOAD_TIMEOUT_DEFAULT)));
115113
}
116114

115+
public void notifyCrashStarted(String error) {
116+
// send a ping message to the telemetry to notify that the crash report started
117+
try (Buffer buf = new Buffer();
118+
JsonWriter writer = JsonWriter.of(buf)) {
119+
writer.beginObject();
120+
writer.name("crash_uuid").value(storedConfig.reportUUID);
121+
writer
122+
.name("message")
123+
.value(
124+
"Crashtracker crash ping: " + (error != null ? error : "crash processing started"));
125+
writer.endObject();
126+
handleCall(
127+
makeTelemetryRequest(RequestBody.create(APPLICATION_JSON, buf.toString())), "ping");
128+
} catch (Throwable t) {
129+
log.error("Failed to send c crash ping", t);
130+
}
131+
}
132+
117133
public void upload(@Nonnull List<Path> files) throws IOException {
134+
String uuid = storedConfig.reportUUID;
118135
for (Path file : files) {
119136
uploadToLogs(file);
120-
uploadToTelemetry(file);
137+
uploadToTelemetry(file, uuid);
138+
// if we send more than 1 file via the CLI, let's make sure we have unique uuid (will be
139+
// generated if null)
140+
uuid = null;
121141
}
122142
}
123143

@@ -236,24 +256,18 @@ private String extractErrorStackTrace(String fileContent, boolean redact) {
236256
return "";
237257
}
238258

239-
private String extractErrorStackTrace(String fileContent) {
240-
return extractErrorStackTrace(fileContent, true);
241-
}
242-
243-
boolean uploadToTelemetry(@Nonnull Path file) {
259+
boolean uploadToTelemetry(@Nonnull Path file, String uuid) {
244260
try {
245261
String content = new String(Files.readAllBytes(file), Charset.defaultCharset());
246-
handleCall(makeTelemetryRequest(content));
262+
handleCall(makeTelemetryRequest(makeTelemetryRequestBody(content, uuid)), "file");
247263
} catch (IOException e) {
248264
log.error("Failed to upload crash file: {}", file, e);
249265
return false;
250266
}
251267
return true;
252268
}
253269

254-
private Call makeTelemetryRequest(@Nonnull String content) throws IOException {
255-
final RequestBody requestBody = makeTelemetryRequestBody(content);
256-
270+
private Call makeTelemetryRequest(@Nonnull RequestBody requestBody) throws IOException {
257271
final Map<String, String> headers = new HashMap<>();
258272
// Set chunked transfer
259273
MediaType contentType = requestBody.contentType();
@@ -273,8 +287,9 @@ private Call makeTelemetryRequest(@Nonnull String content) throws IOException {
273287
.build());
274288
}
275289

276-
private RequestBody makeTelemetryRequestBody(@Nonnull String content) throws IOException {
277-
CrashLog crashLog = CrashLogParser.fromHotspotCrashLog(content);
290+
private RequestBody makeTelemetryRequestBody(@Nonnull String content, String uuid)
291+
throws IOException {
292+
CrashLog crashLog = CrashLogParser.fromHotspotCrashLog(content, uuid);
278293
if (crashLog == null) {
279294
throw new IOException("Failed to parse crash log");
280295
}
@@ -327,32 +342,35 @@ private RequestBody makeTelemetryRequestBody(@Nonnull String content) throws IOE
327342
}
328343
}
329344

330-
private void handleCall(final Call call) {
345+
private void handleCall(final Call call, String kind) {
331346
try (Response response = call.execute()) {
332-
handleSuccess(call, response);
333-
} catch (IOException e) {
334-
handleFailure(e);
347+
handleSuccess(call, response, kind);
348+
} catch (Throwable t) {
349+
handleFailure(t, kind);
335350
}
336351
}
337352

338-
private void handleSuccess(final Call call, final Response response) throws IOException {
353+
private void handleSuccess(final Call call, final Response response, String kind)
354+
throws IOException {
339355
if (response.isSuccessful()) {
340356
log.info(
341-
"Successfully uploaded the crash files to {}, code = {} \"{}\"",
357+
"Successfully uploaded the crash {} to {}, code = {} \"{}\"",
358+
kind,
342359
call.request().url(),
343360
response.code(),
344361
response.message());
345362
} else {
346363
log.error(
347-
"Failed to upload crash files to {}, code = {} \"{}\", body = \"{}\"",
364+
"Failed to upload crash {} to {}, code = {} \"{}\", body = \"{}\"",
365+
kind,
348366
call.request().url(),
349367
response.code(),
350368
response.message(),
351369
response.body() != null ? response.body().string().trim() : "<null>");
352370
}
353371
}
354372

355-
private void handleFailure(final IOException exception) {
356-
log.error("Failed to upload crash files, got exception", exception);
373+
private void handleFailure(final Throwable exception, String kind) {
374+
log.error("Failed to upload crash {}, got exception", kind, exception);
357375
}
358376
}

dd-java-agent/agent-crashtracking/src/main/java/datadog/crashtracking/dto/CrashLog.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public final class CrashLog {
1717
ADAPTER = moshi.adapter(CrashLog.class);
1818
}
1919

20-
public final String uuid = RandomUtils.randomUUID().toString();
20+
public final String uuid;
2121

2222
@Json(name = "data_schema_version")
2323
public final String dataSchemaVersion;
@@ -37,13 +37,15 @@ public final class CrashLog {
3737
public final int version = VERSION;
3838

3939
public CrashLog(
40+
String uuid,
4041
boolean incomplete,
4142
String timestamp,
4243
ErrorData error,
4344
Metadata metadata,
4445
OSInfo osInfo,
4546
ProcInfo procInfo,
4647
String dataSchemaVersion) {
48+
this.uuid = uuid != null ? uuid : RandomUtils.randomUUID().toString();
4749
this.incomplete = incomplete;
4850
this.timestamp = timestamp;
4951
this.error = error;

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ private StackFrame parseLine(String line) {
115115
return null;
116116
}
117117

118-
public CrashLog parse(String crashLog) {
118+
public CrashLog parse(String uuid, String crashLog) {
119119
String signal = null;
120120
String pid = null;
121121
List<StackFrame> frames = new ArrayList<>();
@@ -213,7 +213,7 @@ public CrashLog parse(String crashLog) {
213213
SystemProperties.get("os.name"),
214214
SemanticVersion.of(SystemProperties.get("os.version")));
215215
ProcInfo procInfo = pid != null ? new ProcInfo(pid) : null;
216-
return new CrashLog(false, datetime, error, metadata, osInfo, procInfo, "1.0");
216+
return new CrashLog(uuid, false, datetime, error, metadata, osInfo, procInfo, "1.0");
217217
}
218218

219219
static String dateTimeToISO(String datetime) {

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public class CrashUploaderTest {
4545
private static final String HOSTNAME = "crash-hostname";
4646
private static final String SERVICE = "crash-service";
4747
private static final String VERSION = "crash-version";
48+
private static final String SAMPLE_UUID = "a4194cd6-8cb3-45fd-9bd9-3af83e0a3ad3";
4849
// private static final Map<String, String> TAGS = Map.of("foo", "bar", "baz", "123", "null",
4950
// null, "empty", "");
5051

@@ -159,7 +160,7 @@ public void testTelemetryHappyPath(String log) throws Exception {
159160
// When
160161
uploader = new CrashUploader(config, crashConfig);
161162
server.enqueue(new MockResponse().setResponseCode(200));
162-
uploader.uploadToTelemetry(getResourcePath(log));
163+
uploader.uploadToTelemetry(getResourcePath(log), SAMPLE_UUID);
163164

164165
final RecordedRequest recordedRequest = server.takeRequest(5, TimeUnit.SECONDS);
165166

@@ -170,6 +171,7 @@ public void testTelemetryHappyPath(String log) throws Exception {
170171
final JsonNode event = mapper.readTree(recordedRequest.getBody().readUtf8());
171172

172173
assertEquals(CrashUploader.TELEMETRY_API_VERSION, event.get("api_version").asText());
174+
assertEquals(SAMPLE_UUID, event.get("uuid").asText());
173175
assertEquals("logs", event.get("request_type").asText());
174176
assertEquals("crashtracker", event.get("origin").asText());
175177
assertEquals("1234", event.get("runtime_id").asText());
@@ -209,7 +211,7 @@ public void testTelemetryUnrecognizedFile() throws Exception {
209211
// When
210212
uploader = new CrashUploader(config, crashConfig);
211213
server.enqueue(new MockResponse().setResponseCode(200));
212-
assertFalse(uploader.uploadToTelemetry(getResourcePath("no-crash.txt")));
214+
assertFalse(uploader.uploadToTelemetry(getResourcePath("no-crash.txt"), null));
213215
}
214216

215217
@Test

dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/AgentCLI.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,22 +83,33 @@ public static void sendSampleTraces(final int count, final double interval) thro
8383
}
8484

8585
public static void uploadCrash(final String configFile, final String... files) throws Exception {
86+
String error = null;
8687
ConfigManager.StoredConfig storedConfig = null;
8788
if (configFile != null) {
8889
Path configPath = Paths.get(configFile);
8990
if (!Files.exists(configPath)) {
9091
log.error("Config file {} does not exist", configFile);
91-
System.exit(1);
92+
error = "Config file does not exist";
9293
}
9394
storedConfig = readConfig(Config.get(), configPath);
9495
if (storedConfig == null) {
9596
log.error("Unable to parse config file {}", configFile);
96-
System.exit(1);
97+
error += "Unable to parse config file";
9798
}
98-
} else {
99+
}
100+
if (storedConfig == null) {
99101
// if the PID is not provided, the config file will be null
100102
storedConfig = new ConfigManager.StoredConfig.Builder(Config.get()).build();
101103
}
104+
105+
final CrashUploader crashUploader = new CrashUploader(storedConfig);
106+
// send the crash ping
107+
crashUploader.notifyCrashStarted(error);
108+
109+
if (error != null) {
110+
System.exit(1);
111+
}
112+
102113
List<Path> paths = new ArrayList<>(files.length);
103114
for (String file : files) {
104115
final Path path = Paths.get(file);
@@ -108,7 +119,7 @@ public static void uploadCrash(final String configFile, final String... files) t
108119
}
109120
paths.add(path);
110121
}
111-
new CrashUploader(storedConfig).upload(paths);
122+
crashUploader.upload(paths);
112123
}
113124

114125
public static void sendOomeEvent(String taglist) throws Exception {

0 commit comments

Comments
 (0)