66import static datadog .trace .api .config .CrashTrackingConfig .CRASH_TRACKING_PROXY_USERNAME ;
77import static datadog .trace .api .config .CrashTrackingConfig .CRASH_TRACKING_UPLOAD_TIMEOUT ;
88import static datadog .trace .api .config .CrashTrackingConfig .CRASH_TRACKING_UPLOAD_TIMEOUT_DEFAULT ;
9+ import static datadog .trace .api .telemetry .LogCollector .SEND_TELEMETRY ;
10+ import static datadog .trace .util .TraceUtils .normalizeServiceName ;
11+ import static datadog .trace .util .TraceUtils .normalizeTagValue ;
912
1013import com .squareup .moshi .JsonWriter ;
1114import datadog .common .container .ContainerInfo ;
2730import java .time .Instant ;
2831import java .util .Arrays ;
2932import java .util .HashMap ;
30- import java .util .List ;
3133import java .util .Map ;
3234import java .util .Scanner ;
3335import java .util .concurrent .TimeUnit ;
@@ -61,8 +63,6 @@ public final class CrashUploader {
6163
6264 private static final MediaType APPLICATION_JSON =
6365 MediaType .get ("application/json; charset=utf-8" );
64- private static final MediaType APPLICATION_OCTET_STREAM =
65- MediaType .parse ("application/octet-stream" );
6666
6767 private final Config config ;
6868 private final ConfigManager .StoredConfig storedConfig ;
@@ -114,13 +114,32 @@ public CrashUploader(@Nonnull final ConfigManager.StoredConfig storedConfig) {
114114 CRASH_TRACKING_UPLOAD_TIMEOUT , CRASH_TRACKING_UPLOAD_TIMEOUT_DEFAULT )));
115115 }
116116
117- public void upload (@ Nonnull List <Path > files ) throws IOException {
118- for (Path file : files ) {
119- uploadToLogs (file );
120- uploadToTelemetry (file );
117+ public void notifyCrashStarted (String error ) {
118+ // send a ping message to the telemetry to notify that the crash report started
119+ try (Buffer buf = new Buffer ();
120+ JsonWriter writer = JsonWriter .of (buf )) {
121+ writer .beginObject ();
122+ writer .name ("crash_uuid" ).value (storedConfig .reportUUID );
123+ writer .name ("kind" ).value ("Crash ping" );
124+ writer .name ("current_schema_version" ).value ("1.0" );
125+ writer
126+ .name ("message" )
127+ .value (
128+ "Crashtracker crash ping: " + (error != null ? error : "crash processing started" ));
129+ writer .endObject ();
130+ handleCall (makeTelemetryRequest (makeTelemetryRequestBody (buf .readUtf8 (), true )), "ping" );
131+
132+ } catch (Throwable t ) {
133+ log .error ("Failed to send crash ping" , t );
121134 }
122135 }
123136
137+ public void upload (@ Nonnull Path file ) throws IOException {
138+ String uuid = storedConfig .reportUUID ;
139+ uploadToLogs (file );
140+ uploadToTelemetry (file , uuid );
141+ }
142+
124143 @ SuppressForbidden
125144 boolean uploadToLogs (@ Nonnull Path file ) {
126145 try {
@@ -236,24 +255,23 @@ private String extractErrorStackTrace(String fileContent, boolean redact) {
236255 return "" ;
237256 }
238257
239- private String extractErrorStackTrace (String fileContent ) {
240- return extractErrorStackTrace (fileContent , true );
241- }
242-
243- boolean uploadToTelemetry (@ Nonnull Path file ) {
258+ boolean uploadToTelemetry (@ Nonnull Path file , String uuid ) {
244259 try {
245260 String content = new String (Files .readAllBytes (file ), Charset .defaultCharset ());
246- handleCall (makeTelemetryRequest (content ));
247- } catch (IOException e ) {
248- log .error ("Failed to upload crash file: {}" , file , e );
261+ CrashLog crashLog = CrashLogParser .fromHotspotCrashLog (uuid , content );
262+ if (crashLog == null ) {
263+ log .error (SEND_TELEMETRY , "Failed to parse crash log with uuid {} " , uuid );
264+ return false ;
265+ }
266+ handleCall (makeTelemetryRequest (makeTelemetryRequestBody (crashLog .toJson (), false )), "crash" );
267+ } catch (Throwable t ) {
268+ log .error ("Failed to upload crash file: {}" , file , t );
249269 return false ;
250270 }
251271 return true ;
252272 }
253273
254- private Call makeTelemetryRequest (@ Nonnull String content ) throws IOException {
255- final RequestBody requestBody = makeTelemetryRequestBody (content );
256-
274+ private Call makeTelemetryRequest (@ Nonnull RequestBody requestBody ) throws IOException {
257275 final Map <String , String > headers = new HashMap <>();
258276 // Set chunked transfer
259277 MediaType contentType = requestBody .contentType ();
@@ -273,11 +291,9 @@ private Call makeTelemetryRequest(@Nonnull String content) throws IOException {
273291 .build ());
274292 }
275293
276- private RequestBody makeTelemetryRequestBody (@ Nonnull String content ) throws IOException {
277- CrashLog crashLog = CrashLogParser .fromHotspotCrashLog (content );
278- if (crashLog == null ) {
279- throw new IOException ("Failed to parse crash log" );
280- }
294+ private RequestBody makeTelemetryRequestBody (@ Nonnull String payload , boolean isPing )
295+ throws IOException {
296+
281297 try (Buffer buf = new Buffer ()) {
282298 try (JsonWriter writer = JsonWriter .of (buf )) {
283299 writer .beginObject ();
@@ -291,11 +307,17 @@ private RequestBody makeTelemetryRequestBody(@Nonnull String content) throws IOE
291307 writer .name ("payload" );
292308 writer .beginArray ();
293309 writer .beginObject ();
294- writer .name ("message" ).value (crashLog .toJson ());
295- writer .name ("level" ).value ("ERROR" );
296- writer .name ("tags" ).value ("severity:crash" );
297- writer .name ("is_sensitive" ).value (true );
298- writer .name ("is_crash" ).value (true );
310+ writer .name ("message" ).value (payload );
311+ if (isPing ) {
312+ writer .name ("level" ).value ("DEBUG" );
313+ writer .name ("is_sensitive" ).value (false );
314+ writer .name ("tags" ).value (tagsForPing (storedConfig .reportUUID ));
315+ } else {
316+ writer .name ("level" ).value ("ERROR" );
317+ writer .name ("tags" ).value ("severity:crash" );
318+ writer .name ("is_sensitive" ).value (true );
319+ writer .name ("is_crash" ).value (true );
320+ }
299321 writer .endObject ();
300322 writer .endArray ();
301323 writer .name ("application" );
@@ -327,32 +349,47 @@ private RequestBody makeTelemetryRequestBody(@Nonnull String content) throws IOE
327349 }
328350 }
329351
330- private void handleCall (final Call call ) {
352+ private String tagsForPing (String uuid ) {
353+ final StringBuilder tags = new StringBuilder ("is_crash_ping:true" );
354+ tags .append ("," ).append ("language_name:jvm" );
355+ tags .append ("," ).append ("service:" ).append (normalizeServiceName (storedConfig .service ));
356+ tags .append ("," )
357+ .append ("language_version:" )
358+ .append (normalizeTagValue (SystemProperties .getOrDefault ("java.version" , "unknown" )));
359+ tags .append ("," ).append ("tracer_version:" ).append (normalizeTagValue (VersionInfo .VERSION ));
360+ tags .append ("," ).append ("uuid:" ).append (uuid );
361+ return (tags .toString ());
362+ }
363+
364+ private void handleCall (final Call call , String kind ) {
331365 try (Response response = call .execute ()) {
332- handleSuccess (call , response );
333- } catch (IOException e ) {
334- handleFailure (e );
366+ handleSuccess (call , response , kind );
367+ } catch (Throwable t ) {
368+ handleFailure (t , kind );
335369 }
336370 }
337371
338- private void handleSuccess (final Call call , final Response response ) throws IOException {
372+ private void handleSuccess (final Call call , final Response response , String kind )
373+ throws IOException {
339374 if (response .isSuccessful ()) {
340375 log .info (
341- "Successfully uploaded the crash files to {}, code = {} \" {}\" " ,
376+ "Successfully uploaded the crash {} to {}, code = {} \" {}\" " ,
377+ kind ,
342378 call .request ().url (),
343379 response .code (),
344380 response .message ());
345381 } else {
346382 log .error (
347- "Failed to upload crash files to {}, code = {} \" {}\" , body = \" {}\" " ,
383+ "Failed to upload crash {} to {}, code = {} \" {}\" , body = \" {}\" " ,
384+ kind ,
348385 call .request ().url (),
349386 response .code (),
350387 response .message (),
351388 response .body () != null ? response .body ().string ().trim () : "<null>" );
352389 }
353390 }
354391
355- private void handleFailure (final IOException exception ) {
356- log .error ("Failed to upload crash files , got exception" , exception );
392+ private void handleFailure (final Throwable exception , String kind ) {
393+ log .error ("Failed to upload crash {} , got exception" , kind , exception );
357394 }
358395}
0 commit comments