How do I start debugging an error in Salesforce?
How do I start debugging an error in Salesforce?
This post is dedicated to all the newbie in salesforce who have just started exploring the wide arena of customization that can be done on the force.com platform. Do you often get stumbled when you see an error suddenly popping up while saving a record because of a trigger that you have written or on a recently written Visual force page?
Well, it is very obvious to have errors in the code while development, especially when you are new to apex code development and not at all error messages are self explanatory to conclude to a solution. So, what do we do to resolve the error?
Yes, Debug Log is the solution.
I have seen most neo developers get scared in the name of Debug Log. They would do everything from Google search to post in forums but not go through the Debug Log.
Debug Log redirects us to the source of the error.
Once you are comfortable reading the Debug and understand the key techniques of error solving, you can analyse any error and find the root cause.
In this blog, we will focus on the techniques to be used to avoid obvious errors and then how to be comfortable with the Debug log.
Techniques to Reduce Error
These are some of key techniques or principles that you can follow to minimize errors while coding –
- Minimize the need to debug – Build your code hierarchically and in a modular fashion which will minimize the need to debug at the first place.
- Think like a Tester – Try to think through all the positive and negative use cases and document them as unit test cases to rule out any missed scenarios even before you start writing the code.
- Let your diagrams come out First – Get into a habit of designing your code with a carefully conceived flowchart/sequence diagrams and class diagrams representing your logic or requirement.
- Follow a Design Pattern – For all complex business logic, break your code into layers for ease of maintenance, easy to scale and debug. SOC (Separation of Concern) is what I recommend for Apex and Factory Pattern for Triggers which gives the flexibility to turn on/off business logic.
- Push out the Runtime Exceptions – Try to avoid all runtime exceptions like NullPointer, IndexOutOfBoundsException and have all the necessary validations done on the code.
- Do it right the first time – Last but not the least and is a very important principle. Revisit all the best practices, have that engraved in you and follow them from the very first line of code.
Debug an Error
* What is captured in a Debug Log?
A debug log can record database operations, system processes, and errors that occur when executing a transaction or running unit tests. Debug logs can contain information about:
- Database changes
- HTTP callouts
- Apex errors
- Resources used by Apex
- Automated workflow processes, such as:
- Workflow rules
- Assignment rules
- Approval processes
- Validation rules
* How to access a Debug Log?
Debug logs can be accessed either from
- Setup>Monitor>Logs>Debug Log – The User has to be set with the datetime range within which the transaction would be executed or else entry would not be recorded.
- Developer Console – Logs open in Log Inspector. Log Inspector is a context-sensitive execution viewer that shows the source of an operation, what triggered the operation, and what occurred afterward. Use this tool to inspect debug logs that include database events, Apex processing, workflow, and validation logic.
* Simple Steps to start Debugging
- Step 1 – Knowing the prerequisites
- Developer Console is most convenient location to locate the Debug Logs.
You have 3 options to view the debug log –
Open Log – The formatted log file with the options to filter based on keyword, view debug only, execution points. Recommended
Open Raw – The detailed log file
Download Log – Option to download the detailed log file.
- Understanding the Trace Flags and Debug Levels
To specify the information captured in a debug log, debug level and trace flag needs to be set for a user.
- Debug Levels – Each debug level includes one of the following log levels for each Log Category. The levels are listed from lowest to highest
Log Levels
- NONE
- ERROR
- WARN
- INFO
- DEBUG
- FINE
- FINER
- FINEST
Log Categories
Database | Includes information about database activity, including every data manipulation language (DML) statement or inline SOQL or SOSL query. |
Workflow | Includes information for workflow rules, flows, and processes, such as the rule name and the actions taken. |
Validation | Includes information about validation rules, such as the name of the rule and whether the rule evaluated true or false. |
Callout | Includes the request-response XML that the server is sending and receiving from an external web service. Useful when debugging issues related to using Force.com web service API calls or troubleshooting user access to external objects via an OData adapter for Salesforce Connect. |
Apex Code | Includes information about Apex code. Can include information such as log messages generated by DML statements, inline SOQL or SOSL queries, the start and completion of any triggers, and the start and completion of any test method. |
Apex Profiling | Includes cumulative profiling information, such as the limits for your namespace and the number of emails sent. |
Visualforce | Includes information about Visualforce events, including serialization and deserialization of the view state or the evaluation of a formula field in a Visualforce page. |
System | Includes information about calls to all system methods such as the System.debugmethod. |
- Trace Flag – It is required to be set for a user to produce Debug Logs. A trace flag includes a debug level, a start time, an end time, and a log type. The log types are DEVELOPER_LOG, USER_DEBUG, and CLASS_TRACING. A standard SFDC_DevConsole debug level is shared by all DEVELOPER_LOG trace flags in the org
- Step 2 – Know to read the Log file
A debug log has the following sections –
- Header – The header contains the following information.
- The version of the API used during the transaction.
- The log category and level used to generate the log
37.0 APEX_CODE,DEBUG;APEX_PROFILING,INFO;CALLOUT,INFO;DB,INFO;SYSTEM,DEBUG; VALIDATION,INFO;VISUALFORCE,INFO;WORKFLOW, INFO
- Execution Units – An execution unit is equivalent to a transaction. It contains everything that occurred within the transaction.
EXECUTION_STARTED and EXECUTION_FINISHED delimit an execution unit.
- Code Units – A code unit is a discrete unit of work within a transaction. For example, a trigger is one unit of code, as is a webService method or a validation rule. CODE_UNIT_STARTED and CODE_UNIT_FINISHED delimit units of code. Units of work can embed other units of work.
- Log Lines – Log lines are included inside units of code and indicate which code or rules are being executed. Log lines can also be messages written to the debug log.
- Other Information – The log also contains information regarding
- Cumulative resource usage is logged at the end of many code units. Among these code units are triggers, executeAnonymous, batch Apex message processing, @futuremethods, Apex test methods, Apex web service methods, and Apex lead convert.
- Cumulative profiling information is logged once at the end of the transaction and contains information about DML invocations, expensive queries, and so on. “Expensive” queries use resources heavily.
Sample Log File
28.0 APEX_CODE,FINEST;APEX_PROFILING,INFO;CALLOUT,INFO;DB,INFO;SYSTEM,DEBUG;VALIDATION,INFO;VISUALFORCE,INFO;WORKFLOW,INFO
06:39:44.0 (497737)|USER_INFO|[EXTERNAL]|005P0000001IlQR|jinaxxxx@xxxxxxxxx|Eastern Standard Time|GMT-04:00
06:39:44.0 (551067)|EXECUTION_STARTED
06:39:44.0 (557744)|CODE_UNIT_STARTED|[EXTERNAL]|066d0000001yiuM|VF: /apex/ForecastVsActual
06:39:44.0 (9354860)|SYSTEM_MODE_ENTER|true
06:39:44.0 (9852436)|HEAP_ALLOCATE|[72]|Bytes:3
06:39:44.0 (9915332)|HEAP_ALLOCATE|[77]|Bytes:152
06:39:44.0 (9935344)|HEAP_ALLOCATE|[342]|Bytes:408
06:39:44.0 (9953745)|HEAP_ALLOCATE|[355]|Bytes:408
06:39:44.0 (9970882)|HEAP_ALLOCATE|[467]|Bytes:48
06:39:44.0 (723237895)|VARIABLE_ASSIGNMENT|[EXTERNAL]|this|{"CurrDate":"2016-08-17T00:00:00.000Z","dummyAcc":"0x512ac13","month":"0x62303a5b","numRows":0,"selectedAlphabet":"A","selectedCustType":"Both","selectedYear":"2016","summRowIndex":"0x8fee0eb","thismonth":8,"thisyear":2016,"unitMonth":"0x7e02f5da"}|0x505c60d3
06:39:44.0 (723289332)|HEAP_ALLOCATE|[310]|Bytes:120
06:39:44.0 (723356053)|VARIABLE_ASSIGNMENT|[EXTERNAL]|this|{"CurrDate":"2016-08-17T00:00:00.000Z","dummyAcc":"0x512ac13","month":"0x62303a5b","numRows":0,"selectedAlphabet":"A","selectedCustType":"Both","selectedYear":"2016","summRowIndex":"0x8fee0eb","thismonth":8,"thisyear":2016,"unitMonth":"0x7e02f5da"}|0x505c60d3
06:39:44.0 (723399946)|HEAP_ALLOCATE|[310]|Bytes:120
06:39:44.0 (723460895)|VARIABLE_ASSIGNMENT|[EXTERNAL]|this|{"CurrDate":"2016-08-17T00:00:00.000Z","dummyAcc":"0x512ac13","month":"0x62303a5b","numRows":0,"selectedAlphabet":"A","selectedCustType":"Both","selectedYear":"2016","summRowIndex":"0x8fee0eb","thismonth":8,"thisyear":2016,"unitMonth":"0x7e02f5da"}|0x505c60d3
06:39:44.0 (749003340)|VARIABLE_ASSIGNMENT|[EXTERNAL]|this|{"AccId":"","AccName":"Summary - ","AccType":"","isSummary":true,"strStyleClass":"summaryRowx","xc":"0x6f5e7d95"}|0x44ae41b9
06:39:44.0 (847259119)|SYSTEM_MODE_ENTER|true
06:39:44.0 (895274477)|VF_SERIALIZE_VIEWSTATE_BEGIN|066d0000001yiuM
06:39:44.0 (908887836)|VF_SERIALIZE_VIEWSTATE_END
06:39:44.921 (921787493)|CUMULATIVE_LIMIT_USAGE
06:39:44.921 (921787493)|LIMIT_USAGE_FOR_NS|(default)|
Number of SOQL queries: 3 out of 100
Number of query rows: 2 out of 50000
Number of SOSL queries: 0 out of 20
Number of DML statements: 0 out of 150
Number of DML rows: 0 out of 10000
Maximum CPU time: 0 out of 10000
Maximum heap size: 0 out of 6000000
Number of callouts: 0 out of 100
Number of Email Invocations: 0 out of 10
Number of future calls: 0 out of 50
Number of queueable jobs added to the queue: 0 out of 50
Number of Mobile Apex push calls: 0 out of 10
06:39:44.921 (921787493)|CUMULATIVE_LIMIT_USAGE_END
06:39:44.0 (921859878)|CODE_UNIT_FINISHED|VF: /apex/ForecastVsActual
06:39:44.0 (923528947)|EXECUTION_FINISHED
- Step 3 – Set the Log Levels
Debug logs have a limit of 2 MB and often you might hit the limit for bigger functionality. The log captures the last portion of the file. Check if you have ‘Skipped lines of code’, in case you have that the debug log is truncated. So it is necessary to set the appropriate log level. If you are only debugging Apex code, you can set all the Log Categories to ‘None’ and Apex Code to ‘Debug’.
If the error still persists, there are option to set Log Level for specific Classes and Triggers and setting the entire Debug Level to ‘None’.
4. Step 4 – Add Meaningful Debug Statements
Debug Statements should be added at strategic points to help you identify the error. You can have them at each entry and exit points and have meaningful and searchable text so that they can be easily located in the Debug.
You can also log Debug Statements as Error instead of Debug for bigger logs to help you locate the debugs
Use System.debug(LogLevel.ERROR, ‘***Error Message***’).
- Step 5 – Use of execute anonymous blocks
Use the ‘Execute Anonymous’ window of Developer console to run specific classes and methods within the class to reproduce the issue.
- Step 6 – Follow the Rule of Elimination
In case you are not able to find the exact location of the error, follow the ‘Rule of Elimination’. Start with minimal code and keep adding the code to help you identify the exact location. Test Classes is also another great way to identify the issues with various combinations of test data.
References