-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
44 changed files
with
1,306 additions
and
0 deletions.
There are no files selected for viewing
16 changes: 16 additions & 0 deletions
16
force-app/main/default/applications/Logger_Demo.app-meta.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<CustomApplication xmlns="http://soap.sforce.com/2006/04/metadata"> | ||
<brand> | ||
<headerColor>#0070D2</headerColor> | ||
<shouldOverrideOrgTheme>false</shouldOverrideOrgTheme> | ||
</brand> | ||
<formFactors>Small</formFactors> | ||
<formFactors>Large</formFactors> | ||
<isNavAutoTempTabsDisabled>false</isNavAutoTempTabsDisabled> | ||
<isNavPersonalizationDisabled>false</isNavPersonalizationDisabled> | ||
<label>Logger Demo</label> | ||
<navType>Standard</navType> | ||
<tabs>Log_Event__c</tabs> | ||
<uiType>Lightning</uiType> | ||
<utilityBar>Logger_Demo_UtilityBar</utilityBar> | ||
</CustomApplication> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/** | ||
* @author elganellis | ||
* @description Custom exception for errors executed in flows. | ||
*/ | ||
|
||
public with sharing class FlowException extends Exception { | ||
|
||
public String flowName; | ||
public String failingActionName; | ||
/** | ||
* @description Constructor | ||
* @param faultMessage the fault message produced by the flow when the error was encountere | ||
* @param flowName the name of the flow that reported the error | ||
* @param failingActionName the name of the action that triggered the error | ||
*/ | ||
public FlowException(String faultMessage, String flowName, String failingActionName) { | ||
|
||
this(faultMessage,flowName); | ||
this.failingActionName = failingActionName; | ||
|
||
} | ||
/** | ||
* @description Constructor | ||
* Used for creating flow exceptions without the name of the causing action | ||
* @param faultMessage the fault message produced by the flow when the error was encountere | ||
* @param flowName the name of the flow that reported the error | ||
*/ | ||
public FlowException(String faultMessage, String flowName) { | ||
|
||
this.flowName = flowName; | ||
setMessage(faultMessage); | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata"> | ||
<apiVersion>54.0</apiVersion> | ||
<status>Active</status> | ||
</ApexClass> |
44 changes: 44 additions & 0 deletions
44
force-app/main/default/classes/InvocableFlowExceptions.cls
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
|
||
/** | ||
* @author elganellis | ||
* @description class used to contain an invocable method 'log flow exceptions' to log errors in flows | ||
*/ | ||
public with sharing class InvocableFlowExceptions { | ||
/** | ||
* @description Invocable input class | ||
* @param faultMessage the fault message produced by the flow when the error was encountere | ||
* @param flowName the name of the flow that reported the error | ||
* @param failingActionName the name of the action that triggered the error | ||
*/ | ||
public class MethodInput { | ||
|
||
@InvocableVariable(required=true) | ||
public String faultMessage; | ||
|
||
@InvocableVariable(required=true) | ||
public String flowName; | ||
|
||
@InvocableVariable(required=false) | ||
public String failing_action_name; | ||
|
||
} | ||
/** | ||
* @description invocable method that takes detail of a flow error and logs it as a log event record | ||
*/ | ||
@InvocableMethod( label = 'Log flow exception') | ||
public static void LogExceptions(List<MethodInput> methodInputs) { | ||
|
||
Logger exceptionLogger = Logger.get(); | ||
|
||
for (MethodInput input : methodInputs) { | ||
|
||
FlowException newFlowException = new FlowException( input.faultMessage,input.flowName, input.failing_action_name); | ||
exceptionLogger.add(newFlowException); | ||
|
||
} | ||
|
||
exceptionLogger.publish(); | ||
|
||
|
||
} | ||
} |
5 changes: 5 additions & 0 deletions
5
force-app/main/default/classes/InvocableFlowExceptions.cls-meta.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata"> | ||
<apiVersion>54.0</apiVersion> | ||
<status>Active</status> | ||
</ApexClass> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
/** | ||
* @author tomcarman | ||
* @description Base class for all Log types. Common methods/atrributes should get added here, whilst | ||
specific implementations of different types of logs should extend this class - eg. | ||
LogExceptn, LogDMLExceptn. | ||
*/ | ||
|
||
public virtual class Log { | ||
|
||
/** | ||
* @description String that describes the type of Log | ||
*/ | ||
protected String logType = 'Standard Log'; | ||
|
||
|
||
/** | ||
* @description String of arbitrary data that forms the log. Recommended format is JSON, but can be anything. | ||
* Limited to 131,072 characters | ||
*/ | ||
protected String data; | ||
|
||
|
||
/** | ||
* @description Enum to represent the severity of the log - DEBUG, INFO, WARN, ERROR | ||
*/ | ||
protected LogSeverity severity; | ||
|
||
|
||
/** | ||
* @description Used to store any single recordId, eg. the Id of the record that initiated the transaction | ||
*/ | ||
protected Id recordId; | ||
|
||
|
||
/** | ||
* @description The internal Id of the Salesforce request (often called transaction) that is executing when this | ||
* log is being created. Useful to correlate multiple logs created in a single execution. | ||
*/ | ||
protected String requestId { | ||
get { | ||
if(requestId == null) { | ||
requestId = Request.getCurrent()?.getRequestId(); | ||
} | ||
return requestId; | ||
} | ||
protected set; | ||
} | ||
|
||
|
||
/** | ||
* description The quddity value of the request that is executing when this log is being created. | ||
*/ | ||
protected Quiddity quiddity { | ||
get { | ||
if(quiddity == null) { | ||
quiddity = Request.getCurrent()?.getQuiddity(); | ||
} | ||
return quiddity; | ||
} | ||
protected set; | ||
} | ||
|
||
/** | ||
* description Logic to determine the "location" of where the log was raised - eg. MyClass.myMethod Line 1 Column 1 | ||
* There is currently no native apex method to do this, so instead an Exception is constructed and then | ||
* the stacktrace is traversed with regex to extract the class and method. | ||
* Note: changes to the implementation of the Logger/Log classes could require a change to the line noted | ||
* below with an inline comment, as the stack trace could get deeper/shallower. | ||
*/ | ||
|
||
|
||
protected String location { | ||
|
||
get { | ||
|
||
if(location == null) { | ||
|
||
Map<String, String> locationMap = new Map<String, String>(); | ||
|
||
try { | ||
|
||
List<String> stackTraceLines = new DmlException().getStackTraceString().split('\n'); | ||
|
||
String relevantLine = ''; | ||
|
||
if(stackTraceLines.size() >= 6) { | ||
relevantLine = stackTraceLines[5]; | ||
} else if (stackTraceLines.size() >= 3) { | ||
relevantLine = stackTraceLines[stackTraceLines.size()-2]; | ||
} else { | ||
relevantLine = stackTraceLines[stackTraceLines.size()-1]; | ||
} | ||
|
||
Matcher m = generateMatcher(relevantLine); | ||
|
||
if (m.find()) { | ||
|
||
if (String.isBlank(m.group(3))) { | ||
|
||
locationMap.put('className', m.group(1)); | ||
locationMap.put('methodName',prettifyMethodName(m.group(2))); | ||
|
||
} else { | ||
|
||
locationMap.put('className', m.group(1) + '.' + m.group(2)); | ||
locationMap.put('methodName', prettifyMethodName(m.group(3))); | ||
|
||
} | ||
|
||
locationMap.put('line', String.valueOf(m.group(4))); | ||
locationMap.put('column', String.valueOf(m.group(5))); | ||
} | ||
|
||
location = JSON.serializePretty(locationMap); | ||
|
||
} catch (Exception e) { | ||
// Allow this to silently fail and print a debug, as this can be a little finicky, and we | ||
// dont want block the creation of logs. | ||
System.debug('Failed to identify location for Log: ' + e); | ||
} | ||
} | ||
|
||
return location; | ||
} | ||
|
||
protected set; | ||
} | ||
|
||
|
||
|
||
/** | ||
* @description Default constructor - required to allow subclassing. | ||
*/ | ||
public Log(){} | ||
|
||
|
||
/** | ||
* @description Constructor | ||
* @param data an arbitrary string of data | ||
*/ | ||
public Log(String data){ | ||
this(data, LogSeverity.INFO); | ||
} | ||
|
||
/** | ||
* @description Constructor | ||
* @param data an arbitrary string of data | ||
* @param severity LogSeverity enum | ||
*/ | ||
public Log(String data, LogSeverity severity){ | ||
this.data = data; | ||
this.severity = severity; | ||
} | ||
|
||
|
||
/** | ||
* @description Method to convert this log into a Log__e Platform Event ready for publishing | ||
* Overridable to allow different implementations of Log.cls to create different types of | ||
* Platform Event. | ||
*/ | ||
public virtual SObject toEvent() { | ||
return new Log__e( | ||
Type__c = this.logType, | ||
Severity__c = this.severity?.name(), | ||
Record_Id__c = this.recordId, | ||
Transaction_Id__c = this.requestId, | ||
Quiddity__c = this.quiddity?.name(), | ||
Location__c = this.location, | ||
Data__c = this.data, | ||
Running_User__c = UserInfo.getUserId() | ||
); | ||
|
||
} | ||
|
||
|
||
|
||
|
||
/** | ||
* @description Tidy up method names for constructors and getter/setters when using the location property | ||
* @param name Raw method name from stack trace | ||
*/ | ||
private String prettifyMethodName(String name) { | ||
return (name == null) ? null : | ||
name.replace('<init>', '(constructor) ') | ||
.replace('__sfdc_', '(getter/setter) '); | ||
} | ||
|
||
/** | ||
* @description Regex expression to extract class/method/line/column from a stack trace. | ||
* @param firstLine Raw line of stack trace | ||
*/ | ||
private Matcher generateMatcher(String firstLine) { | ||
return Pattern.compile( | ||
'(?i)^(?:class\\.)?([^.]+)\\.?([^\\.\\:]+)?[\\.\\:]?([^\\.\\:]*): line (\\d+), column (\\d+)$' | ||
).matcher(firstLine); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata"> | ||
<apiVersion>50.0</apiVersion> | ||
<status>Active</status> | ||
</ApexClass> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/** | ||
* @author tomcarman | ||
* @description Subclass of Log.cls to create Logs specific to DMLExceptions | ||
*/ | ||
public class LogDMLExceptn extends Log { | ||
|
||
/** | ||
* @description An instance of a DML Exception | ||
*/ | ||
private DMLException dmlEx; | ||
|
||
|
||
/** | ||
* @description Constructor | ||
* @param dmlEx the DML exception to create the log from | ||
*/ | ||
public LogDMLExceptn(DMLException dmlEx) { | ||
|
||
this.dmlEx = dmlEx; | ||
this.recordId = dmlEx.getDmlId(0); | ||
this.logType = 'DML Exception Log'; | ||
this.data = buildData(); | ||
this.severity = LogSeverity.ERROR; | ||
|
||
} | ||
|
||
|
||
/** | ||
* @description Helper method to extract details from the DML exception and format as JSON. | ||
*/ | ||
private String buildData() { | ||
|
||
Map<String, Map<String, String>> exceptionMap = new Map<String, Map<String, String>>(); | ||
|
||
Map<String, String> exceptionDetails = new Map<String, String>(); | ||
|
||
exceptionDetails.put('ExceptionType', dmlEx.getTypeName()); | ||
exceptionDetails.put('LineNumber', String.valueOf(dmlEx.getLineNumber())); | ||
exceptionDetails.put('Message', dmlEx.getMessage()); | ||
exceptionDetails.put('StackTrace', dmlEx.getStackTraceString()); | ||
|
||
exceptionMap.put('Exception Details', exceptionDetails); | ||
|
||
for (Integer i = 0; i < dmlEx.getNumDml(); i++) { | ||
Map<String, String> dmlExceptionMap = new Map<String, String>(); | ||
dmlExceptionMap.put('Id', dmlEx.getDmlId(i)); | ||
dmlExceptionMap.put('Message', dmlEx.getDmlMessage(i)); | ||
dmlExceptionMap.put('StatusCode', dmlEx.getDmlStatusCode(i)); | ||
dmlExceptionMap.put('FieldNames', String.join(dmlEx.getDmlFieldNames(i), ', ')); | ||
exceptionMap.put('Row ' + String.valueOf(i), dmlExceptionMap); | ||
} | ||
|
||
return JSON.serializePretty(exceptionMap); | ||
|
||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata"> | ||
<apiVersion>50.0</apiVersion> | ||
<status>Active</status> | ||
</ApexClass> |
Oops, something went wrong.