Salesforce - Developer - Debugging

salesforce-developer

https://trailhead.salesforce.com/en/modules/apex_basics_dotnet/units/debugging_diagnostics - done reading
http://www.jitendrazaa.com/blog/salesforce/getting-started-with-apex-debug-logs-in-salesforce/
http://www.salesforce.com/us/developer/docs/apexcode/index_Left.htm#StartTopic=Content/apex_methods_system_limits.htm
http://www.salesforce.com/us/developer/docs/apexcode/index_Left.htm#StartTopic=Content/apex_debugging_debug_log.htm
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_debugging.htm
https://trailhead.salesforce.com/en/apex_basics_dotnet/debugging_diagnostics - printed
http://www.jitendrazaa.com/blog/salesforce/advance-apex-debugging-in-salesforce-and-best-practices-videos/
http://salesforce.stackexchange.com/questions/12313/how-to-check-debug-logs-for-installed-app

// Salesforce - Developer - Debugging - General info:

Apex provides debugging support. You can debug your Apex code using the 
Developer Console and debug logs. To aid debugging in your code, Apex supports 
exception statements and custom exceptions. Also, Apex sends emails to developers 
for unhandled exceptions.

// Salesforce - Developer - Debugging:

To output a debug message to the log file:

System.debug('My debug message');

We can also specify one of the following logging levels:

1. NONE
2. ERROR
3. WARN
4. INFO
5. DEBUG
6. FINE
7. FINER
8. FINEST

These log levels runs from lowest to highest and are cumulative.  If we pick the finest 
level, we get all the messages that are logged as error, warn, info, and so on.  There are 
also several debug log categories.

Each debug log must be 2MB or smaller.  If it exceeds this amount, we won't see everything.  Additionally,
each org can retain up to 50MB of debug logs.  The oldest logs are overwritten.

// Using Log Inspector (part of Developer Console):

1. Launch Developer Console
2. Select "Debug -> Change Log Levels"
3. Click the "Add / Change" link in the "General Trace Settings for You"
4. Select "INFO" as the debug level for all columns
5. Click "Done"
6. Click "Done"
7. Select "Debug -> Perspective Manager"
8. Select "All (Predefined)" and click "Set Default"
9. Click "Yes" to change this to your default perspective
10. Close the Developer Console Perspective window
11. Select "Debug -> Open Execute Anonymous Window"
12. Delete the existing code and insert: System.debug(LoggingLevel.INFO, 'My INFO Debug Message');
13. Make sure that "Open Log" check box is checked, and click Execute
14. Select "Debug -> Switch Perspective -> All (Predefined)"
15. Click the "Limits" tab in "Execution Overview".  Notice the amount in the "Request Total" and "Total Available" columns.
16. Examine the results in the Timeline and Execute Units tabs.
17. Under "Execution Log", select the "Filter" option, and enter "FINE".  Because we set the debug level to INFO inside 
     our Apex code, no results appear.
18. Select "Debug -> Change Log Levels"
19. Click the "Add / Change" link in the "General Trace Settings for Your".
20. Change the DebugLevel for Apex code and profiling to FINEST
21. Click Done
22. Click Done
23. Select "Debug -> Open Execute Anonymous Window"
24. Leave the code that is currently there, and click Execute.
25. Under "Execution Log", select the "Filter" option, and enter "FINE".  The filter search is case sensitive.  We now see 
     "My Fine Debug Message" displayed.

// Using Checkpoints (part of Developer Console):

In a cloud-based multi-tenanted environment where everyone share resources, allowing anyone to halt execution and 
keep database connection open is disastrous.  Checkpoints are similar to breakpoints in that they reveal a lot of 
detailed execution information about a line of code.  Unlike breakpoints, checkpoints do not pause execution.  To 
understand how checkpoints works:

1. Launch Developer Console
2. Select "File -> Open"
3. Select "Classes" as the entity type, and "AccountHandler" as the entity.
4. Click "Open"
5. Position our cursor over line 10 in the left margin and click once.  A red dot appears next to the line number.
6. Click .
7. Double-click the latest entry in the "Logs" panel to open the debug log.
8. Select "Debug -> Open Execute Anonymous Window".
9. Delete the existing code and insert the following snippet (see the original article)
10. Make sure that the "Open Log" check box is checked, and click "Execute"
11. Click the Checkpoints tab, and double-click the first entry that appears.  The "Checkpoint Inspector" appears.
12. On the Symbols tab, expand the nodes within the execution tree.  Notice the Key and Value columns.
13. Click the "Heap" tab.  Notice the "Count" and "Total Size" columns

// Salesforce - Developer - Debugging - Using the Debugger Add-on for Eclipse:

The Debugger Add-on is not free.  It is available for purchase after Winter
2016.  It only works in sandbox environments.

Install the debugger add-on for the Eclipse plug-in.

Apex has a System class called Limits that lets you output debug messages for 
each governor limit. There are two versions of every method: the first returns 
the amount of the resource that has been used in the current context, while the 
second version contains the word limit and returns the total amount of the 
resource that is available for that context. 

The following example shows how to embed these types of statements in your code 
and ultimately determine if or when you are about to exceed any governor limits. 
Using either the System Log or Debug Logs, you can evaluate the output to see 
how the specific code is performing against the governor limits. Additionally, 
you can embed logic in the Apex code directly to throw error messages before 
reaching a governor limit. The code sample below has an IF statement to evaluate 
if the trigger is about to update too many Opportunities. 

Here is an example of how you can use a combination of System.debug statements 
and the Limits Apex class to generate some very useful output as it relates to 
governor limits and the overall efficiency of your code. 

trigger accountLimitExample on Account (after delete, after insert, after update) {
  System.debug('Total Number of SOQL Queries allowed in this Apex code context: ' 
    +  Limits.getLimitQueries());
  System.debug('Total Number of records that can be queried  in this Apex code 
    context: ' +  Limits.getLimitDmlRows());
  System.debug('Total Number of DML statements allowed in this Apex code context: ' 
    +  Limits.getLimitDmlStatements() );
  System.debug('Total Number of CPU usage time (in ms) allowed in this Apex 
    code context: ' +  Limits.getLimitCpuTime());

  // Query the Opportunity object 
  List<Opportunity> opptys = [
    select id, description, name, accountid,  closedate, stagename 
    from Opportunity 
    where accountId IN: Trigger.newMap.keySet()
  ];

  System.debug('1. Number of Queries used in this Apex code so far: ' 
    + Limits.getQueries());
  System.debug('2. Number of rows queried in this Apex code so far: ' 
    + Limits.getDmlRows());
  System.debug('3. Number of DML statements used so far: ' 
    +  Limits.getDmlStatements());    
  System.debug('4. Amount of CPU time (in ms) used so far: ' 
    + Limits.getCpuTime());

  // NOTE:Proactively determine if there are too many Opportunities to update 
  // and avoid governor limits
  if (opptys.size() + Limits.getDMLRows() > Limits.getLimitDMLRows()) {
    System.debug('Need to stop processing to avoid hitting a governor limit. 
      Too many related Opportunities to update in this trigger');
    System.debug('Trying to update ' + opptys.size() + ' opportunities but 
      governor limits will only allow ' + Limits.getLimitDMLRows());
    for (Account a&nbsp;: Trigger.new) {
      a.addError('You are attempting to update the addresses of too many 
        accounts at once. Please try again with fewer accounts.');
    }
  } else {
    System.debug('Continue processing. Not going to hit DML governor limits');
    System.debug('Going to update ' + opptys.size() + ' opportunities and 
      governor limits will allow ' + Limits.getLimitDMLRows());
    for (Account a&nbsp;: Trigger.new) {
      System.debug('Number of DML statements used so far: ' 
        + Limits.getDmlStatements());
      for (Opportunity o: opptys) { 
        if (o.accountid == a.id) {
          o.description = 'testing';
        }
      }
    }
    update opptys;
    System.debug('Final number of DML statements used so far: ' 
      + Limits.getDmlStatements());
    System.debug('Final heap size: ' +  Limits.getHeapSize());
  }
}

The above example illustrates how valuable the Limits Apex class can be when 
debugging and analyzing the efficiency of your code. It also demonstrates how 
you can proactively check if you are going to run into governor limits and 
better handle those scenarios. 

Additionally, you can enable Apex governor limit warning emails. When an 
end-user invokes Apex code that surpasses more than 50% of any governor limit, 
you can specify a user in your organization to receive an email notification of 
the event with additional details. To enable email warnings: 

1. Log in to Salesforce as an administrator user.
2. Click Setup | Manage Users | Users.
3. Click Edit next to the name of the user who should receive the email 
   notifications.
4. Select the Send Apex Warning Emails option.
5. Click Save.

Salesforce does not have the traditional log files like other applications.  If we want 
to debug something we may have to take extra step.  If we wish to debug a particular 
class, we have to enable the trace flag.  To enable the trace flag for a class:
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License