Since the beginning of APEX, developers are creating persistent event and error logs in Salesforce. Multiple Salesforce Bloggers explained their version of Error Logging in Salesforce:
- Creating Persistent Logs Using Apex and a Custom Object by Mayank Srivastava
- Easy Steps to create persistent Exception Logs in Salesforce by anjargholi.com
- Logging, Alerting and Recovery on the Force.com Platform by Gareth Park FT
All the mechanisms that have been available are using the “try-catch mechanism” and then storing a record in Salesforce. This approach comes with multiple downsides:
- The error is getting catched and not reported to the next higher instance
- It is impossible to see from the “Apex Job Log” if batch jobs are successful or not, since all catched exceptions are reported as “success”.
- An additional DML operation is needed.
- The Error Log was limited to Salesforce APEX Code
In the past this approch was the only solution to handle exceptions and store them persistent in Salesforce. But with Platform Events a new generation of Error Logging becomes possible.
Universal Log — The Next Generation Error Log
Platform Events and the Salesforce Event Bus allow the implementation of an even more sophisticated solution. I call my solution Universal Log.
My Version of the Log allows not only to store information and exceptions from APEX, the solution supports even configuration like process builder, workflows and external applications.
Architecture of Universal Log
Uniersal Log leverages the out of the box Event Bus in Salesforce. All kinds of services, such as Apex Code, Triggers, Batches, External Applications and others can create Log Events. And send them on the Event Bus. There they can be captured and translated into a persistent log.
Architecture of Universal LogUniversal Log Components
The system is based on 4 major components:
- The Logger Class that creates based on Exceptions, Flows and other functionality Log Events
- The Log Event that is used as a transport tool to be catched by
- The Log Event Trigger that creates based on the event a log record
- The Log Record That is storing the log information persistently
The Universal Logger Class
The Universal Logger Class can be called during the execution of a class similar to other error logs the error is getting catched and then logged to the log.
But with one difference: The Exception is re-thrown and becomes visible.
Example
This simple code is going to throw an Exception. Now the universal logger sends the exceptions to the event bus and the class re-throw the exception.
try
{
Integer i = 12/0;
}
catch(Exception e)
{
UniversalLogger.log(e);
throw e;
}
The re-thrown exception will be presented to the next higher level. E.g. the developer console
The universal logger take the exception and put the exception on the bus.
global class UniversalLogger
{
global static void log(Exception e)
{
UniversalLogEvent__e l = new UniversalLogEvent__e();
l.Stacktrace__c = e.getStackTraceString();
EventBus.publish(l);
}
} // Simplified Version
Universal Log Event Trigger
The Universal Event Log Trigger is the last component that then finally converts the Event to a persistent reocrd.
trigger UniversalLogEventTrigger on UniversalLogEvent__e (after insert)
{
List<Log__c> logs = new List<Log__c>();
for(LogEvent__e l : trigger.new)
{
logs.add(new Log__c(Stacktrace__c = l.Stacktrace__c, ...));
}
Database.insert(logs);
}
Conclusion
Salesforce Event Bus as a base for an Error Log is a strong foundation for error logs. All kinds of applications and services can use the error log. The new error log allows to present error messages back to the user, salesforce batch log, while keeping a detailed log in a custom object.
Future Extensions
For a future Version of Universal Log I plan to integrate NewRelic to give even better visibility into the log.
Interesting idea, have you used this in any implementation? 3 years later, what are thoughts on this approach? Thanks