Skip to content

Commit

Permalink
feat(exception email): add raw email body when reporting parsin failure
Browse files Browse the repository at this point in the history
Closes #2
  • Loading branch information
ArturMoczulski committed May 20, 2019
1 parent f6b4172 commit 91beb7a
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 23 deletions.
57 changes: 36 additions & 21 deletions force-app/main/default/classes/DataBuilder.cls
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,37 @@ public with sharing class DataBuilder {

public Map<String, Object> buildPayload(String level, String message)
{
return buildPayloadStructure(level, this.buildMessageBody(message));
return buildPayloadStructure(level, buildMessageBody(message), null);
}

public Map<String, Object> buildPayload(Exception exc)
{
if (exc.getCause() != null) {
return buildTraceChainPayload(exc);
} else {
return buildExceptionPayload(exc);
}
return buildPayloadStructure('error', buildExceptionBody(exc), null);
}

public Map<String, Object> buildPayload(ExceptionData exData)
public Map<String, Object> buildPayload(Exception exc, Map<String, Object> custom)
{
Map<String, Object> payload = buildPayloadStructure('error', this.buildTraceBody(exData));
return buildPayloadStructure('error', buildExceptionBody(exc), custom);
}

public Map<String, Object> buildPayload(ExceptionData exData)
{
Map<String, Object> custom = new Map<String, Object>();
custom.put('context', exData.context());

Map<String, Object> data = (Map<String, Object>)payload.get('data');
data.put('custom', custom);

return payload;
return buildPayloadStructure('error', buildTraceBody(exData), custom);
}

private Map<String, Object> buildExceptionPayload(Exception exc)
private Map<String, Object> buildExceptionBody(Exception exc)
{
return buildPayloadStructure('error', this.buildTraceBody(exc));
if (exc.getCause() == null) {
return buildTraceBody(exc);
} else {
return buildTraceChainBody(exc);
}
}

private Map<String, Object> buildTraceChainPayload(Exception exc)
private Map<String, Object> buildTraceChainBody(Exception exc)
{
Map<String, Object> outterExTrace = (Map<String, Object>)this.buildTraceBody(exc).get('trace');
Map<String, Object> innerExTrace = (Map<String, Object>)this.buildTraceBody(exc.getCause()).get('trace');
Expand All @@ -48,21 +48,34 @@ public with sharing class DataBuilder {
Map<String, Object> body = new Map<String, Object>();
body.put('trace_chain', traceChainList);

return buildPayloadStructure('error', body);
return body;
}

private Map<String, Object> buildPayloadStructure(String level, Map<String, Object> body)
{
Map<String, Object> data = this.buildDataStructure(level, this.config.environment(), body);
private Map<String, Object> buildPayloadStructure(
String level,
Map<String, Object> body,
Map<String, Object> custom
) {
Map<String, Object> data = this.buildDataStructure(
level,
this.config.environment(),
body,
custom
);

Map<String, Object> structure = new Map<String, Object>();
structure.put('access_token', this.config.accessToken());
structure.put('data', data);
return structure;
}

private Map<String, Object> buildDataStructure(String level, String environment, Map<String, Object> body)
{
private Map<String, Object> buildDataStructure(
String level,
String environment,
Map<String, Object> body,
Map<String, Object> custom
) {

Map<String, Object> notifierMap = new Map<String, Object>();
notifierMap.put('name', Notifier.NAME);
notifierMap.put('version', Notifier.VERSION);
Expand All @@ -73,6 +86,8 @@ public with sharing class DataBuilder {
structure.put('environment', environment);
structure.put('framework', 'apex');
structure.put('body', body);
structure.put('custom', custom);

return structure;
}

Expand Down
6 changes: 6 additions & 0 deletions force-app/main/default/classes/Notifier.cls
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ public with sharing class Notifier
return reportPayload(payload);
}

public HttpResponse log(Exception exc, Map<String, Object> custom)
{
String payload = JSON.serialize(this.dataBuilder.buildPayload(exc, custom));
return reportPayload(payload);
}

public HttpResponse log(ExceptionData exData)
{
String payload = JSON.serialize(this.dataBuilder.buildPayload(exData));
Expand Down
5 changes: 5 additions & 0 deletions force-app/main/default/classes/Rollbar.cls
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ public with sharing class Rollbar {
return instance.notifier.log(exc);
}

public static HttpResponse log(Exception exc, Map<String, Object> custom) {
Rollbar instance = initializedInstance();
return instance.notifier.log(exc, custom);
}

public static HttpResponse log(ExceptionData exData) {
Rollbar instance = initializedInstance();
return instance.notifier.log(exData);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,12 @@ global class RollbarExceptionEmailHandler implements Messaging.InboundEmailHandl
throw new ExceptionEmailParsingException('Unable to process unhandled email', exc);
}
} catch(ExceptionEmailParsingException wrapper) {
// TODO: add full email body in case we can't process exception email
wrapper.getStackTraceString(); // without those calls strack trace string is not populated
Rollbar.log(wrapper);

Map<String, String> custom = new Map<String, String>();
custom.put('email_body', emailBody);

Rollbar.log(wrapper, custom);
}

// Set the result to true. No need to send an email back to the user
Expand Down
16 changes: 16 additions & 0 deletions force-app/main/default/tests/DataBuilderTest.cls
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,22 @@ public class DataBuilderTest
}
}

@isTest
static void testBuildExceptionPayloadWithCustom()
{
DataBuilder subject = new DataBuilder(new Config('foo', 'bar'));
Map<String, String> expectedCustom = new Map<String, String>();
expectedCustom.put('foo', 'bar');

DataBuilderTestException exc = new DataBuilderTestException('foobar');

Map<String, Object> result = subject.buildPayload(exc, expectedCustom);
Map<String, Object> data = (Map<String, Object>)result.get('data');
Map<String, Object> custom = (Map<String, Object>)data.get('custom');

System.assertEquals(expectedCustom.get('foo'), (String)custom.get('foo'));
}

@isTest
static void testBuildTraceChainPayload()
{
Expand Down

0 comments on commit 91beb7a

Please sign in to comment.