Debugging Tools & Techniques

0/2 in this phase0/41 across the roadmap

📖 Concept

Effective debugging in Salesforce requires mastering multiple tools — debug logs, Developer Console, VS Code debugging, and monitoring tools.

Debugging tools:

  1. Debug Logs

    • Configure via Setup → Debug Logs
    • Set log levels per category (Database, Apex, Workflow, etc.)
    • Each log has a size limit (5MB for Developer Console, 20MB total)
    • Persist for 24 hours (or until overwritten)
    • Critical sections: SOQL_EXECUTE, DML_BEGIN, USER_DEBUG, LIMIT_USAGE
  2. Developer Console

    • Execute anonymous Apex
    • View and analyze debug logs
    • Query Plan tool for SOQL optimization
    • Test runner with code coverage
    • Performance profiling via timeline
  3. VS Code with Salesforce Extensions

    • Replay Debugger — step through debug logs
    • ISV Debugger — real-time debugging (ISV only)
    • Apex Test Sidebar — run/debug tests
    • SOQL Builder — visual query construction
  4. Monitoring & Alerting

    • Event Monitoring (Shield) — user activity tracking
    • Apex Exception Emails — automatic error notifications
    • Custom error logging — Error_Log__c custom object
    • Health Check — security scanning
    • Salesforce Optimizer — org health analysis

Debug log anatomy:

EXECUTION_STARTED         — Transaction begins
CODE_UNIT_STARTED         — Trigger/class entry
SOQL_EXECUTE_BEGIN/END    — Each SOQL query with timing
DML_BEGIN/END             — Each DML operation
USER_DEBUG                — System.debug() output
VARIABLE_SCOPE_BEGIN/END  — Variable values (FINER level)
LIMIT_USAGE_FOR_NS        — Governor limit consumption
CUMULATIVE_LIMIT_USAGE    — Total limits used in transaction
EXECUTION_FINISHED        — Transaction complete

💻 Code Example

codeTap to expand ⛶
1// Debugging Patterns & Techniques
2
3public class DebuggingService {
4
5 // 1. Structured debug logging
6 public static void debugLog(String className, String methodName, String message) {
7 System.debug(LoggingLevel.INFO,
8 '[' + className + '.' + methodName + '] ' + message);
9 }
10
11 public static void debugLog(String className, String methodName,
12 String message, Object data) {
13 System.debug(LoggingLevel.INFO,
14 '[' + className + '.' + methodName + '] ' + message +
15 ' | Data: ' + JSON.serialize(data));
16 }
17
18 // 2. Transaction-level debugging
19 public static void debugTransaction(String context) {
20 System.debug(LoggingLevel.INFO, '=== Transaction Debug: ' + context + ' ===');
21 System.debug(LoggingLevel.INFO, 'User: ' + UserInfo.getUserId());
22 System.debug(LoggingLevel.INFO, 'SOQL: ' + Limits.getQueries() + '/' + Limits.getLimitQueries());
23 System.debug(LoggingLevel.INFO, 'DML: ' + Limits.getDmlStatements() + '/' + Limits.getLimitDmlStatements());
24 System.debug(LoggingLevel.INFO, 'CPU: ' + Limits.getCpuTime() + 'ms/' + Limits.getLimitCpuTime() + 'ms');
25 System.debug(LoggingLevel.INFO, 'Heap: ' + Limits.getHeapSize() + '/' + Limits.getLimitHeapSize());
26 }
27
28 // 3. Conditional debugging (avoid heap in production)
29 private static Boolean isDebugEnabled = false;
30
31 public static void enableDebug() { isDebugEnabled = true; }
32
33 public static void conditionalDebug(String message, Object data) {
34 if (isDebugEnabled) {
35 System.debug(LoggingLevel.DEBUG, message + ': ' + JSON.serialize(data));
36 }
37 }
38
39 // 4. Error tracking with custom object
40 public static void logError(Exception e, String context) {
41 try {
42 insert new Error_Log__c(
43 Class_Name__c = context,
44 Error_Message__c = e.getMessage()?.left(255),
45 Stack_Trace__c = e.getStackTraceString()?.left(32000),
46 Error_Type__c = e.getTypeName(),
47 Line_Number__c = e.getLineNumber(),
48 User__c = UserInfo.getUserId(),
49 Timestamp__c = Datetime.now(),
50 Transaction_Id__c = Request.getCurrent().getRequestId()
51 );
52 } catch (Exception logError) {
53 System.debug(LoggingLevel.ERROR, 'Failed to log error: ' + logError.getMessage());
54 }
55 }
56
57 // 5. Trigger debugging — trace what triggered the execution
58 public static void debugTriggerContext() {
59 System.debug(LoggingLevel.INFO, '=== Trigger Context ===');
60 System.debug(LoggingLevel.INFO, 'isBefore: ' + Trigger.isBefore);
61 System.debug(LoggingLevel.INFO, 'isAfter: ' + Trigger.isAfter);
62 System.debug(LoggingLevel.INFO, 'isInsert: ' + Trigger.isInsert);
63 System.debug(LoggingLevel.INFO, 'isUpdate: ' + Trigger.isUpdate);
64 System.debug(LoggingLevel.INFO, 'isDelete: ' + Trigger.isDelete);
65 System.debug(LoggingLevel.INFO, 'size: ' + Trigger.size);
66 System.debug(LoggingLevel.INFO, 'new: ' + (Trigger.new != null ? Trigger.new.size() : 0));
67 System.debug(LoggingLevel.INFO, 'old: ' + (Trigger.old != null ? Trigger.old.size() : 0));
68 }
69
70 // 6. Anonymous Apex debugging scripts
71 // Execute in Developer Console → Execute Anonymous
72
73 // Quick data check
74 // List<Account> accs = [SELECT Id, Name, Industry FROM Account LIMIT 5];
75 // System.debug(JSON.serializePretty(accs));
76
77 // Test a specific method
78 // try {
79 // OpportunityService.closeDeals(new Set<Id>{'006xxxxxxxxxxxx'});
80 // System.debug('SUCCESS');
81 // } catch (Exception e) {
82 // System.debug('ERROR: ' + e.getMessage());
83 // System.debug('STACK: ' + e.getStackTraceString());
84 // }
85
86 // Check sharing visibility
87 // List<AccountShare> shares = [
88 // SELECT AccountId, UserOrGroupId, AccountAccessLevel, RowCause
89 // FROM AccountShare WHERE AccountId = '001xxxxxxxxxxxx'
90 // ];
91 // System.debug(JSON.serializePretty(shares));
92}

🏋️ Practice Exercise

Debugging Practice:

  1. Set up debug logs for your user and analyze a complex transaction (trigger → flow → trigger)
  2. Use the Developer Console Timeline to identify the slowest operation in a transaction
  3. Write a structured logging utility that captures class, method, and context
  4. Create an Error_Log__c object and build an error tracking system
  5. Use Anonymous Apex to reproduce and debug a specific production issue
  6. Set up the VS Code Replay Debugger to step through a captured debug log
  7. Build a debugging dashboard that shows error trends over time
  8. Implement conditional debugging that can be toggled per user via Custom Setting
  9. Write a script that audits all sharing rules affecting a specific record
  10. Create a production monitoring alert that fires when error rates exceed thresholds

⚠️ Common Mistakes

  • Leaving System.debug statements in production code — they consume CPU time and heap even if no one reads the logs. Use conditional debugging or remove before deploy

  • Debug log size truncation — logs over 5MB are truncated. Reduce log levels for categories you don't need (set to WARN or NONE)

  • Not using structured log format — random debug messages are impossible to search. Always include class name, method name, and context

  • Debugging production with FINEST level — this generates massive logs and can impact org performance. Use INFO/DEBUG for production

  • Not checking CUMULATIVE_LIMIT_USAGE — the section at the end of debug logs shows total limit consumption, including all triggers and automations

💼 Interview Questions

🎤 Mock Interview

Mock interview is powered by AI for Debugging Tools & Techniques. Login to unlock this feature.