ANJARGHOLI.COM

Yolande Anjargholi Online

Most of us make use of all the development goodies that Salesforce has to offer, to extend and mold functionality to meet very specific business requirements. As we embark on our journey of designing, developing, implementing, and maintaining custom capabilities, we inevitably face the dull, and daunting task of squinting through the debug log to identify an issue.  Although it may be a headache inducing experience, inspecting the debug log that Salesforce provides is normally very useful for issue resolution, so why should we invest additional effort in creating a more persistent framework for debugging?

  • Consider the situation where a user encounters an issue with a custom feature that you introduced -  As a developer, you know that troubleshooting will require that you re-create the scenario before you can attempt any kind of debugging.

  • Each debug log must be 2MB or smaller. Debug logs that are larger than 2 MB are reduced in size by removing older log lines. However, log lines can be removed from any location, not just the start of the debug log. (What do you do when you have a batch with high record counts and you can't see what the error was, because the log was truncated... figure out if a different log level can work, or try to implement some limits?)

  • How do we make it easy for an administrator to pull a report to review and share any potential issues?

An alternative approach that help address some of these points, is to store exceptions in a custom object. We can accomplish this fairly quickly, and you don't need to be Jedi Apex developer to get it done. (One call out: please review the extended exception class, and modify / enhance it to fit your own requirements to raise custom exceptions. This is just a basic start, that can be improved on) 

1. Create an object to store your exceptions in:

CustomExceptionObject

 2. From the developer console, create a class that extends the built-in Exception Class

(you can get more details here: https://developer.salesforce.com/docs/atlas.en-us.apex_workbook.meta/apex_workbook/apex7_5.htm)

 public class HandleException extends Exception {
    public static void LogException(Exception e){
        try{
            String QueryLimit = '1. SOQL Queries used / SOQL Queries allowed: ' + Limits.getQueries() + '/' + Limits.getLimitQueries();
			String DMLimit = '2. Number of records queried so far /  Number allowed: ' + Limits.getDmlRows() + '/' + Limits.getLimitDmlRows();
			String DMLStat = '3. Number of DML statements used so far / Number allowed: ' +  Limits.getDmlStatements() + '/' + Limits.getLimitDmlStatements();   
			String CPUT = '4. Amount of CPU time (in ms) used so far / CPU usage time (in ms) allowed: ' + Limits.getCpuTime() + '/' + Limits.getLimitCpuTime();
            
            //Create exception record
            CustomException__c exc = new CustomException__c();
            exc.Gov_Limit_Tracking_in_Executed_Code_Cont__c = String.format('{0}\n{1}\n{2}\n{3}',new List{QueryLimit, DMLimit,DMLStat,CPUT});
            exc.Error_Message__c = e.getMessage();
            exc.Exception_Type__c = e.getTypeName();
            exc.Line_Number__c = e.getLineNumber();
            exc.Stack_Trace__c = e.getStackTraceString();
            database.insert(exc);            
        } catch (Exception exc) {
        }            
    } //end method
} //end class
3. You are done. Now all you need is to put your work to the test - create a class that will raise an exception

(In my example below, I am inserting a Merchandise record without a value for required fields)

 public class YolandeTestClass {
    public static void MainProcessing() {
        try {
            Merchandise__c m = new Merchandise__c();
            insert m;
        } catch (Exception e) {
            HandleException.LogException(e);
        }    
    } //end method
} //end class

Run the code in your Execute Anonymous window. YolandeTestClass.mainProcessing();

4. Take a look at the CustomException record that was created

CustomExceptionRecord