afv-library/skills/debugging-apex-logs/references/cli-commands.md
sandipkumar-yadav 37aa84df42
feat: @W-22444026@ Introducing Core Skills, Datacloud Skills, Industries and Utility Skills. (#268)
* Migrating Core Salesforce Skills

* Updating pr comments

* updat reference

* Updating a skill

* Migrating Datacloud skills

* Migrating Industries cloud skills

* Validating - skills fixing

---------

Co-authored-by: Sandip Kumar Yadav <sandipkumar.yadav+sfemu@salesforce.com>
2026-05-14 19:32:15 +05:30

8.8 KiB

Salesforce CLI Debug Commands Reference

Quick Reference

Task Command
List recent logs sf apex list log --target-org my-org
Get specific log sf apex get log --log-id 07Lxx0000000000
Stream real-time sf apex tail log --target-org my-org
Delete log sf data delete record --sobject ApexLog --record-id <id> --target-org my-org

Log Retrieval

List Available Logs

# List all logs for current user
sf apex list log --target-org my-org

# JSON output for parsing
sf apex list log --target-org my-org --json

Output Fields:

  • Id - Log ID for retrieval
  • LogUser.Name - Who generated the log
  • Operation - What triggered the log
  • Status - Success/Failure
  • LogLength - Size in bytes
  • StartTime - When it was generated

Get Specific Log

# Download log by ID
sf apex get log \
  --log-id 07Lxx0000000000AAA \
  --target-org my-org

# Save to file
sf apex get log \
  --log-id 07Lxx0000000000AAA \
  --target-org my-org \
  --output-dir ./logs

# Get most recent log
sf apex list log --target-org my-org --json | \
  jq -r '.result[0].Id' | \
  xargs -I {} sf apex get log --log-id {} --target-org my-org

Stream Logs Real-Time

# Tail logs with color highlighting
sf apex tail log --target-org my-org --color

# Tail with color highlighting
sf apex tail log \
  --target-org my-org \
  --color
# Note: Debug levels are configured via TraceFlag records in Setup, not CLI flags

# Tail with skip flag (don't show historical logs)
sf apex tail log --target-org my-org --skip-trace-flag

Log Management

Delete Logs

Note

: sf apex log delete does not exist in sf CLI v2. Use sf data delete record instead.

# Delete specific log
sf data delete record \
  --sobject ApexLog \
  --record-id 07Lxx0000000000AAA \
  --target-org my-org

Debug Level Configuration

Using Trace Flags

Trace flags control what gets logged and for which users.

# Create trace flag for specific user
sf data create record \
  --sobject TraceFlag \
  --values "TracedEntityId='005xx0000001234' LogType='USER_DEBUG' DebugLevelId='7dlxx0000000000' StartDate='2025-01-01T00:00:00Z' ExpirationDate='2025-01-02T00:00:00Z'" \
  --target-org my-org

# Query existing trace flags
sf data query \
  --query "SELECT Id, TracedEntityId, DebugLevel.MasterLabel, ExpirationDate FROM TraceFlag" \
  --target-org my-org

# Delete trace flag
sf data delete record \
  --sobject TraceFlag \
  --record-id 7tfxx0000000000AAA \
  --target-org my-org

Debug Levels

# List available debug levels
sf data query \
  --query "SELECT Id, MasterLabel, ApexCode, ApexProfiling, Callout, Database, System, Workflow FROM DebugLevel" \
  --target-org my-org

# Create custom debug level
sf data create record \
  --sobject DebugLevel \
  --values "MasterLabel='PerformanceDebug' DeveloperName='PerformanceDebug' ApexCode='FINE' ApexProfiling='FINEST' Database='FINE' System='DEBUG'" \
  --target-org my-org

Advanced Usage

Execute Anonymous with Logging

# Run anonymous Apex and capture log
echo "System.debug('Test'); Account a = [SELECT Id FROM Account LIMIT 1];" | \
  sf apex run --target-org my-org

# Run from file
sf apex run \
  --file ./scripts/debug-script.apex \
  --target-org my-org

# Get the log from that execution
sf apex list log --target-org my-org --json | \
  jq -r '.result[0].Id' | \
  xargs -I {} sf apex get log --log-id {} --target-org my-org

Query Plan Analysis

# Analyze query plan using Tooling API
sf data query \
  --query "SELECT Id FROM Account WHERE Name = 'Test'" \
  --target-org my-org \
  --use-tooling-api
# Note: --explain does not exist. Use REST API for query plans:
# GET /services/data/v66.0/query/?explain=SELECT+Id+FROM+Account+WHERE+Name='Test'

Log Analysis with grep

# Find SOQL queries in log
sf apex get log --log-id 07Lxx0000000000 --target-org my-org | \
  rg "SOQL_EXECUTE"

# Count SOQL queries
sf apex get log --log-id 07Lxx0000000000 --target-org my-org | \
  rg -c "SOQL_EXECUTE_BEGIN"

# Find exceptions
sf apex get log --log-id 07Lxx0000000000 --target-org my-org | \
  rg "EXCEPTION_THROWN|FATAL_ERROR"

# Find limit usage
sf apex get log --log-id 07Lxx0000000000 --target-org my-org | \
  rg "LIMIT_USAGE"

# Find slow operations (method timing)
sf apex get log --log-id 07Lxx0000000000 --target-org my-org | \
  rg "METHOD_EXIT.*\|([0-9]{4,})\|"

Automation Scripts

Save and Analyze Latest Log

#!/bin/bash
# save-latest-log.sh

ORG_ALIAS=${1:-"my-org"}
OUTPUT_DIR=${2:-"./logs"}

mkdir -p $OUTPUT_DIR

# Get latest log ID
LOG_ID=$(sf apex list log --target-org $ORG_ALIAS --json | jq -r '.result[0].Id')

if [ "$LOG_ID" == "null" ]; then
    echo "No logs found"
    exit 1
fi

# Save log
FILENAME="$OUTPUT_DIR/$(date +%Y%m%d_%H%M%S)_$LOG_ID.log"
sf apex get log --log-id $LOG_ID --target-org $ORG_ALIAS > $FILENAME

echo "Log saved to: $FILENAME"

# Quick analysis
echo ""
echo "=== QUICK ANALYSIS ==="
echo "SOQL Queries: $(rg -c 'SOQL_EXECUTE_BEGIN' $FILENAME || echo 0)"
echo "DML Statements: $(rg -c 'DML_BEGIN' $FILENAME || echo 0)"
echo "Exceptions: $(rg -c 'EXCEPTION_THROWN|FATAL_ERROR' $FILENAME || echo 0)"

Monitor for Errors

#!/bin/bash
# monitor-errors.sh

ORG_ALIAS=${1:-"my-org"}

echo "Monitoring $ORG_ALIAS for errors..."
echo "Press Ctrl+C to stop"

sf apex tail log --target-org $ORG_ALIAS --color 2>&1 | \
  while read line; do
    if echo "$line" | rg -q "EXCEPTION|FATAL_ERROR|LimitException"; then
      echo "🔴 ERROR DETECTED: $line"
      # Optional: Send alert
      # osascript -e 'display notification "Error in Salesforce" with title "debugging-apex-logs"'
    fi
  done

Bulk Log Cleanup

#!/bin/bash
# cleanup-logs.sh

ORG_ALIAS=${1:-"my-org"}
DAYS_OLD=${2:-7}

echo "Deleting logs older than $DAYS_OLD days from $ORG_ALIAS..."

# Get old log IDs
OLD_LOGS=$(sf data query \
  --query "SELECT Id FROM ApexLog WHERE StartTime < LAST_N_DAYS:$DAYS_OLD" \
  --target-org $ORG_ALIAS \
  --json | jq -r '.result.records[].Id')

COUNT=0
for LOG_ID in $OLD_LOGS; do
    sf data delete record --sobject ApexLog --record-id $LOG_ID --target-org $ORG_ALIAS --json > /dev/null
    ((COUNT++))
done

echo "Deleted $COUNT logs"

Troubleshooting

No Logs Appearing

  1. Check trace flags exist:

    sf data query \
      --query "SELECT Id, TracedEntityId, ExpirationDate FROM TraceFlag WHERE ExpirationDate > TODAY" \
      --target-org my-org
    
  2. Check log retention:

    sf data query \
      --query "SELECT Id, StartTime FROM ApexLog ORDER BY StartTime DESC LIMIT 5" \
      --target-org my-org
    
  3. Verify user has API access:

    • User must have "API Enabled" permission
    • User must have "Author Apex" for trace flags

Log Too Large

Logs over 2MB are truncated. Solutions:

  1. Reduce debug level:

    ApexCode: DEBUG → INFO
    ApexProfiling: FINEST → FINE
    
  2. Focus on specific operation:

    • Create trace flag just before the operation
    • Delete after capturing
  3. Use targeted logging:

    • Add System.debug() only where needed
    • Use LoggingLevel.ERROR for critical info

Logs Not Persisting

Default log retention is 24 hours. To keep logs longer:

# Export log to file immediately
sf apex get log --log-id 07Lxx0000000000 --target-org my-org > ./saved-log.txt

Integration with debugging-apex-logs Skill

The debugging-apex-logs skill automatically:

  1. Fetches logs when you run sf apex get log or sf apex tail log
  2. Parses content for SOQL in loops, DML in loops, exceptions
  3. Displays analysis with governor limit usage
  4. Suggests fixes using sf-apex skill integration

Example workflow:

# Run a test that generates a log
sf apex run test --class-names MyTestClass --target-org my-org

# Get the log (debugging-apex-logs hook auto-analyzes)
sf apex list log --target-org my-org --json | \
  jq -r '.result[0].Id' | \
  xargs -I {} sf apex get log --log-id {} --target-org my-org

The hook will output analysis like:

============================================================
🔍 DEBUG LOG ANALYSIS
============================================================

🔴 CRITICAL ISSUES
------------------------------------------------------------
   • SOQL in loop detected: 50 queries executed inside loops
   • CPU limit critical: 9500/10000ms (95.0%)

📊 GOVERNOR LIMIT USAGE
------------------------------------------------------------
   ✅ SOQL Queries: 50/100 (50.0%)
   ✅ DML Statements: 25/150 (16.7%)
   🔴 CPU Time (ms): 9500/10000 (95.0%)

🤖 AGENTIC FIX RECOMMENDATIONS
============================================================

For SOQL in loop:
   1. Move query BEFORE the loop
   2. Store results in Map<Id, SObject>
   3. Access from Map inside loop