15.1 Debug Logs & Monitoring

Key Takeaways

  • Debug logs capture Apex, SOQL/DML, workflow, validation, callouts, and system events for a traced user, class, or trigger during a request
  • Log levels per category run from ERROR through FINEST (plus NONE); higher verbosity increases detail and the chance of hitting the 20 MB log size limit
  • Trace flags on users, Apex classes, or triggers control who/what is logged and when the flag expires—without an active trace flag you may see no useful log
  • System.debug writes custom messages; combine with execution log limit lines (SOQL, DML, CPU, heap) to diagnose governor and logic failures
  • Apex Exception Email notifies designated users of unhandled exceptions; Event Monitoring provides org-wide audit streams (API, login, URI) beyond single-request debug logs
Last updated: August 2026

15.1 Debug Logs & Monitoring

Quick Answer: A debug log records what the platform did during a request—Apex, SOQL/DML, validation, workflow, callouts, and more—when a trace flag is active for a user, class, or trigger. Set log levels per category (ERROR → FINEST), stay under the ~20 MB log size limit, use System.debug for custom messages, and read limit usage lines to diagnose governors. Apex Exception Email and Event Monitoring extend monitoring beyond a single log file.

Platform Developer I expects you to debug Apex and automation like a working developer: turn on the right logging, find the failing line, interpret governor limit counters, and know what tools exist when a single debug log is not enough.

What a Debug Log Contains

A debug log is a time-ordered trace of one (or more related) execution(s). Typical entries include:

AreaWhat you see
CODE_UNIT_STARTED / FINISHEDControllers, triggers, batch execute, queueable, future, flows invoking Apex
SOQL_EXECUTE_BEGIN / ENDQuery text, rows returned
DML_BEGIN / ENDInsert/update/delete/undelete operations
METHOD_ENTRY / EXITApex method call stack (at fine enough levels)
USER_DEBUGOutput from System.debug
EXCEPTION_THROWN / FATAL_ERRORStack traces and unhandled failures
LIMIT_USAGE / CUMULATIVE_LIMIT_USAGEGovernor consumption (SOQL, DML, CPU, heap, callouts, …)
VALIDATION_RULE / WORKFLOW / FLOWDeclarative automation that fired in the same transaction
CALLOUT_REQUEST / RESPONSEHTTP callout details when logging is enabled for that category

Logs are not a substitute for unit tests, but they are the primary runtime microscope when a bug only appears with real data, sharing rules, or multi-automation order of execution.

Log Levels and Categories

Salesforce assigns a log level to each category. Verbosity from least to most detail:

LevelTypical use
NONESuppress that category
ERRORErrors only
WARNWarnings and errors
INFOHigh-level milestones
DEBUGStandard development detail (common default for Apex Code)
FINEDeeper internal detail
FINERVery verbose
FINESTMaximum detail—large logs fast

Categories you will see on exams and in Setup include (names can vary slightly by UI generation, but the ideas are stable):

  • Apex Code — your classes, triggers, anonymous Apex
  • Apex Profiling — cumulative limits and profiling lines
  • Database — SOQL, SOSL, DML
  • Workflow — workflow rules, some process automation detail
  • Validation — validation rules
  • Callouts — HTTP callouts
  • Visualforce — VF page/controller detail
  • System — platform/system messages

Exam mindset: Raise Apex Code and Database (and Apex Profiling) when hunting SOQL-in-a-loop or limit exceptions. Raise Workflow / Validation when the bug might be declarative. Avoid FINEST on every category for a busy admin user—you will truncate the log before you reach the failure.

Trace Flags: Who Gets Logged

A trace flag tells Salesforce which user, Apex class, or trigger to log and until when. Key points:

  • User-based trace flags log work performed in that user’s context (UI, API, anonymous Apex as that user).
  • Class/trigger trace flags focus logging on specific Apex units—useful when many users hit shared code.
  • Trace flags have an expiration; expired flags stop producing useful logs.
  • Debug logs can be started from Setup → Debug Logs, Developer Console, VS Code / CLI tooling, or related monitoring UIs.

Without an active trace flag covering the executing context, you may run a failing transaction and still have no log—a classic “I reproduced it but there’s nothing in Debug Logs” trap.

Log Size Limits and Truncation

Debug logs have a maximum size commonly tested as 20 MB per log. If the log exceeds that limit, Salesforce truncates it. Truncation often drops the end of the execution—exactly where your exception or final limit dump might have been—so a truncated log can look “fine” until mid-transaction and then stop.

Mitigations developers use:

  1. Lower noisy categories (Workflow FINEST while debugging pure Apex is wasteful).
  2. Narrow the trace (specific class flag vs logging an integration user for an hour).
  3. Reproduce with smaller data volumes or a single record path first.
  4. Use checkpoints (Developer Console) or targeted System.debug near the suspected branch instead of FINEST everywhere.
  5. Prefer unit tests with assertions when the bug is reproducible in Apex tests—logs are for residual runtime mystery.

Orgs also retain only a limited volume/time window of debug logs (commonly discussed as short retention, on the order of a day, with total storage caps). Download important logs promptly; do not assume last week’s failure is still in Setup.

System.debug and Logging Levels in Code

System.debug('Simple message'); // default level
System.debug(LoggingLevel.ERROR, 'Payment failed: ' + orderId);
System.debug(LoggingLevel.DEBUG, 'Rows: ' + accounts.size());
System.debug(LoggingLevel.FINE, 'Full payload: ' + JSON.serialize(payload));

System.debug emits USER_DEBUG lines. Overloads accept a LoggingLevel so messages appear only when the Apex Code category is at least that verbose. Practical habits:

  • Log Ids and counts, not entire org-sized lists at FINEST.
  • Never log secrets (session IDs, tokens, passwords, full PII) — logs are readable by users with log access.
  • Guard expensive serialization in production paths if heap/CPU matter; debug statements still cost CPU and heap.

Reading Execution Logs for Limits and SOQL

When a transaction hits a governor, the log (or the exception email) usually shows a message such as “Too many SOQL queries: 101” along with CUMULATIVE_LIMIT_USAGE style summaries. Train yourself to scan for:

SignalMeaning
Many SOQL_EXECUTE lines inside a loop patternClassic SOQL-in-loop; bulkify with maps
High Number of DML statementsDML in a loop; collect and perform one DML
CPU time near the limitInefficient loops, repeated describe, heavy JSON
Heap size pressureLarge lists in memory, big debug strings
Row counts vs expectationsWrong filter, missing sharing, unexpected children
Order of CODE_UNIT blocksWhich trigger/class/flow ran before the failure

Workflow for a limit exception:

  1. Open the log for the failing user/time.
  2. Jump to FATAL_ERROR / exception stack.
  3. Note the class and line.
  4. Scroll limit usage sections—confirm which governor was exhausted.
  5. Count SOQL/DML in the hot path; map to bulk patterns (earlier chapters on SOQL/DML and triggers).
  6. Fix, add a regression test, re-run with a modest log level to confirm.

Anonymous Apex and tests produce logs too—use them to isolate a method without clicking through the entire UI.

Apex Exception Email

Apex Exception Email (configured in Setup) sends notifications when unhandled Apex exceptions occur. Designated recipients (often developers or a distribution list) get the exception type, message, and stack-related detail. This is critical for async failures (batch, queueable, future, scheduled) that no user is staring at in the browser.

Exam-relevant ideas:

  • Exception email is not a full debug log substitute, but it points you to the failing class/line.
  • Handled exceptions (try/catch that swallows without rethrow or logging) may never surface—bad catch blocks hide production bugs.
  • Combine exception email with targeted debug logs or App/custom logging objects for recurring jobs.

Event Monitoring (High-Level Awareness)

Event Monitoring (part of broader Salesforce Shield / event log capabilities, product packaging depends on edition and licenses) provides org-level event streams such as API calls, logins, URI/page events, report exports, and other security/compliance-oriented telemetry. Contrast with debug logs:

ConcernDebug logsEvent Monitoring
GrainSingle transaction detail for traced contextOrg-wide event types over time
Typical userDeveloper fixing a bugSecurity, compliance, performance analytics
SOQL line-by-lineYes (when logged)Not a substitute for Apex line debugging
Login/API auditLimitedStrong fit

For Platform Developer I, know that Event Monitoring exists, that it is aimed at audit and usage analytics, and that day-to-day Apex debugging still centers on debug logs + tests + exception email. You are not expected to configure every event type in depth, but you should not claim debug logs are the only monitoring surface in Salesforce.

Putting It Together for the Exam

Scenario stems often ask: Why is there no log? (missing/expired trace flag), Why is the log incomplete? (20 MB truncation / too-verbose levels), How do you see SOQL count? (Database + profiling / limit lines), or How are async failures noticed? (Apex Exception Email). Match the tool to the question:

  1. Trace flag → enable capture for user/class/trigger with expiration.
  2. Log levels → enough detail without truncation.
  3. System.debug → intentional breadcrumbs at appropriate LoggingLevel.
  4. Limit sections → prove which governor and which query/DML pattern failed.
  5. Exception email / Event Monitoring → production awareness beyond one Developer Console session.

Master reading a log end-to-end and you will clear most debugging items quickly—and debug real orgs faster after you pass.

Test Your Knowledge

A developer reproduces a trigger bug as a standard user but finds no new entries under Setup → Debug Logs. What is the most likely cause?

A
B
C
D
Test Your Knowledge

While debugging a bulk update, the debug log stops mid-transaction and never shows the final exception. What should the developer consider first?

A
B
C
D
Test Your Knowledge

Which pairing best matches the monitoring need?

A
B
C
D