March 9, 2010

Apex Debugging with Custom Settings

Developers add Apex debugging during development time to figure out complex issues. But that debugging code is usually commented or deleted from Apex Classes when preparing for release or production deployments. We usually remove it to save script statements and processing etc, but that is not really required, Apex is pretty fast on execution, its visualforce that takes time on most of the occasions.

If we keep the debug statements as it is in Apex Code, we can ask customer to goto “Setup > Monitoring > Debug Logs” and create a log record for the user. That log file will be generated when you reproduce the issue next time and the same can be sent to developers to get a digg into the issue. The only issue with this approach is debug log limits and un-necessary debugging, sometimes developers end up in adding too many debug statements, so the logs are no more meaningful.  Though SFDC Spring-10 release came with nice “debug filters” to give you better control on what gets written into the logs. But still there are many pieces connected sometimes for ex. Apex Controllers, Triggers, Email Handlers etc.

So for even more control over logging after Spring-10 debug filters, we can use Custom Settings. The idea is to create a Custom Setting to control “What to debug ?”.  We will start with Custom Setting’s details, followed by Apex Code that uses it.

The Debug Custom Setting

Lets say we create a custom setting named “DebugSettings” to control “What to debug”. This custom setting can be of type “LIST” or “HIERARCHY”, this truly depends on nature of project. Keeping LIST might open debugging for all users in ORG, but on the benefit is its handy to change, with HIERARCHY custom settings, one might need to create an Org Wide value or setup an user/profile based value to get the job done. 

This custom setting can have following fields (All are of Type: CheckBox, Default-Value: FALSE), we have kept default value as false so that on packaging the code all debugging is set to false. So on a production issue you can ask customer to selectively turn on the debugging for required fields only.

  • AccountTrigger: If set to true, debugging will be done for AccountTrigger apex code.
  • MyHelloWorldController: Is set to true, debugging will be done for some visualforce controller named “MyHelloWorldController”.
  • StatusInboundEmailHandler: If set to true, debugging will be done for Inbound Email service handler code.
  • ….
  • …..
  • ….. Similarly one can create custom setting fields for controlling debugging in other apex class/code/triggers/email services etc.

The Apex Code

Using custom settings is pretty easy, but its quite possible to end up in Null Pointer Exceptions. So please refer this article(http://www.tgerm.com/2010/03/custom-settings-null-pointer-exception.html), to ensure you use custom settings in more safer manner. For quick reference here is the code you should try adding before accessing custom setting fields.

if (DebugSettings__c.getInstance() == null) {
        // Assuming DebugSettings is a LIST type custom setting
        upsert new DebugSettings__c (SetupOwnerId = Userinfo.getOrganizationId());          
}

Here is the sample code that shows how to do controlled debugging using custom settings.

// Before insert account trigger
trigger handleAccountChange on Account (before insert)
{
  // .....
  // Your trigger logic 
  // .....

  // Code inside Account Trigger
  if (DebugSettings__c.getInstance().AccountTrigger__c) {
    System.debug('Updating Accounts : ' + Trigger.new);
  }

  // .....
  // Your trigger logic 
  // .....
}

In similar fashion one can adding debugging code to Controller, by adding a check for visual force controller: MyHelloWorldController

// Before insert account trigger
public class MyHelloWorldController
{
  // .....
  // Your Controller logic 
  // .....

  // Code inside Account Trigger
  if (DebugSettings__c.getInstance().MyHelloWorldController__c) {
    System.debug('Processing Request for Parameters : ' + ApexPages.currentPage().getParameters());
  }

  // .....
  // Your Controller logic 
  // .....
}

So on issue in production just create a debug log for the user via “Setup > Monitoring > Debug Logs >  New” and create/update/manage the record for “DebugSettings” custom setting for user/profile/org with required trigger/controller field value as “CHECKED”. Once this is done just execute the flow with the issue and get back to “Setup > Monitoring > Debug Logs” to download the log file. That’s it :-)