mcpField
S
sf-debug

sf-debug

github.com/clientell-ai开发21100 次安装33 周前更新
代码仓库

关于 sf-debug

面向 Salesforce 开发者的调试与故障排查指南,可分析日志、异常和性能瓶颈,并给出根因排查方向与修复建议。内容包括 governor limit、CLI 日志操作和性能剖析。

主要功能

  1. 01分析 Salesforce 调试日志与执行过程
  2. 02检查 governor limit 使用情况
  3. 03诊断常见异常并定位根因
  4. 04使用 sf CLI 获取和跟踪日志
  5. 05通过检查点与查询计划排查问题
  6. 06分析 CPU、堆内存及代码性能

适用场景

  1. 01排查 Apex 异常和触发器失败
  2. 02定位 SOQL 或 DML 超限
  3. 03跟踪 Salesforce 组织中的实时日志
  4. 04识别循环查询和高 CPU 等性能问题

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/clientell-ai/salesforce-skills --skill sf-debug

安装后在 Claude Code 中输入/sf-debug确认已加载。

附带文件references/debug-reference.md

详细介绍

Salesforce 调试与故障排查专家

你是一位 Salesforce 调试专家。根据调试日志、治理限制违规、异常和性能瓶颈诊断问题。提供根本原因分析和可执行的修复方案。

1. 调试日志分析

日志级别(从最详细到最简略)
级别使用场景
FINEST完整跟踪——变量值、框架内部调用
FINER详细流程——带参数的方法进入/退出
FINE关键决策点和循环迭代
DEBUG常规诊断信息
INFO高级事务里程碑
WARN可恢复的问题,可能预示故障
ERROR需要立即处理的失败
日志类别
类别捕获内容
Apex_codeApex 执行、System.debug() 输出、变量赋值
Apex_profiling累积资源使用情况——SOQL、DML、CPU、堆
DatabaseSOQL 查询、DML 操作、查询计划、行数
System系统方法、平台事件、公式计算
Validation验证规则、工作流字段更新
Workflow工作流规则、流程构建器、流执行
CalloutHTTP 调用、SOAP 调用、外部服务响应
VisualforceVF 页面渲染、视图状态、控制器操作
NBANext Best Action 策略执行
阅读调试日志——关键行前缀
EXECUTION_STARTED / EXECUTION_FINISHED — transaction boundaries
CODE_UNIT_STARTED / CODE_UNIT_FINISHED — trigger, class, or method execution
SOQL_EXECUTE_BEGIN / SOQL_EXECUTE_END — query with row count
DML_BEGIN / DML_END — DML operation with row count
EXCEPTION_THROWN — exception type and message
FATAL_ERROR — unrecoverable error with stack trace
HEAP_ALLOCATE — heap memory allocation
LIMIT_USAGE_FOR_NS — governor limit summary per namespace
CUMULATIVE_LIMIT_USAGE — end-of-transaction limit summary
USER_DEBUG — System.debug() output
VARIABLE_SCOPE_BEGIN / VARIABLE_ASSIGNMENT — variable tracking (FINEST)
METHOD_ENTRY / METHOD_EXIT — method call tracking (FINER+)
FLOW_START_INTERVIEWS — flow/process builder execution
VALIDATION_RULE — validation rule evaluation
CALLOUT_REQUEST / CALLOUT_RESPONSE — external HTTP calls
日志结构

调试日志按以下顺序记录:

  1. EXECUTION_STARTED — 事务开始
  2. CODE_UNIT_STARTED — 触发器或入口点触发
  3. 前置触发器逻辑(验证、字段更新)
  4. DML 执行和后置触发器逻辑
  5. 工作流规则、流程构建器、流
  6. 如果工作流导致字段更新,则重新评估前置/后置触发器
  7. 提交或回滚
  8. CUMULATIVE_LIMIT_USAGE — 最终治理限制摘要
  9. EXECUTION_FINISHED — 事务结束

2. 治理限制监控

Limits 类方法——触及限制前进行检查
// SOQL
System.debug('SOQL queries: ' + Limits.getQueries() + ' / ' + Limits.getLimitQueries());

// DML
System.debug('DML statements: ' + Limits.getDmlStatements() + ' / ' + Limits.getLimitDmlStatements());
System.debug('DML rows: ' + Limits.getDmlRows() + ' / ' + Limits.getLimitDmlRows());

// CPU
System.debug('CPU time (ms): ' + Limits.getCpuTime() + ' / ' + Limits.getLimitCpuTime());

// Heap
System.debug('Heap size (bytes): ' + Limits.getHeapSize() + ' / ' + Limits.getLimitHeapSize());

// Query rows
System.debug('Query rows: ' + Limits.getQueryRows() + ' / ' + Limits.getLimitQueryRows());

// Callouts
System.debug('Callouts: ' + Limits.getCallouts() + ' / ' + Limits.getLimitCallouts());

// Future calls
System.debug('Future calls: ' + Limits.getFutureCalls() + ' / ' + Limits.getLimitFutureCalls());

// Queueable jobs
System.debug('Queueable jobs: ' + Limits.getQueueableJobs() + ' / ' + Limits.getLimitQueueableJobs());
何时检查限制
  • 执行耗费资源的操作前——暂时无法重构的循环内查询或 DML
  • 处理批次后——在 Database.Batchable.execute() 的每个批次末尾
  • 在实用工具/服务类中——在入口和出口记录限制使用情况,以进行性能分析
  • 在 catch 块中——可能即将触及 LimitException 时
  • 切勿在紧密循环中检查——Limits.*() 调用本身也会消耗 CPU
同步与异步限制
资源同步异步(Batch/Future/Queueable)
SOQL 查询100200
DML 语句150150
CPU 时间10,000 ms60,000 ms
堆大小6 MB12 MB
查询行数50,00050,000
调用次数100100
DML 行数10,00010,000

3. 常见错误诊断

错误可能原因修复方向
UNABLE_TO_LOCK_ROW同一记录或主从关系中的父记录遭到并发更新使用 FOR UPDATE 重试,缩小批次范围,使用异步处理,避免不必要地更新父记录
ENTITY_IS_DELETED在同一事务中或由其他用户删除记录后,又对其执行了 DML执行 DML 前检查 isDeleted,使用 try/catch 处理并发,验证触发器顺序
FIELD_CUSTOM_VALIDATION_EXCEPTION验证规则未通过检查对象上的验证规则,确保字段值符合所有条件;使用 Database.insert(records, false) 实现部分成功
INSUFFICIENT_ACCESS_ON_CROSS_REFERENCE_ENTITY无权访问相关记录(查找关系/主从关系中的父记录、所有者、队列)验证共享规则,检查 OWD,确保当前用户有权访问相关记录;仅在有明确理由时使用 without sharing
MIXED_DML_OPERATION在同一事务中对设置对象(User、Group)和非设置对象执行 DML将其中一个 DML 移至 @future,在测试中使用 System.runAs(),或拆分到不同事务
System.LimitException: Too many SOQL queries同步事务中的 SOQL 查询超过 100 次将查询移出循环,使用集合和 Map 进行查找,对大型数据集使用 SOQL for 循环
System.LimitException: Too many DML statements事务中的 DML 语句超过 150 条将记录收集到 List 中,在循环外执行批量 DML
System.CalloutExceptionHTTP 调用失败——超时、端点无效或证书问题检查 Named Credential 配置,验证端点 URL,处理超时并重试,检查远程站点设置
System.NullPointerException在空引用上访问方法或属性访问前添加空值检查,使用安全导航运算符 ?.,访问前确认 SOQL 查询已返回结果
System.QueryException: List has no rows[SELECT ... LIMIT 1] 未返回任何行,却将结果赋给单个 sObject 变量使用 List<SObject> 并检查 .isEmpty(),或使用 try/catch
System.QueryException: List has more than 1 row查询结果被赋给单个变量,但返回了多行添加 LIMIT 1 或使用 List<SObject>;排查数据问题——重复项可能表明数据质量有问题
CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY触发器递归或级联触发器失败实现静态递归保护,检查触发器处理框架是否具备重入保护
System.AsyncException入队的异步任务过多,或达到链式调用限制检查 Limits.getQueueableJobs(),使用 Finalizer 实现批处理链式调用,将每个 Queueable 的入队次数限制为 1 次
System.SerializationExceptionQueueable 或 Platform Event 中包含无法序列化的对象移除瞬态引用,避免在序列化状态中使用带有关系字段的 SObject 类型
STRING_TOO_LONG字段值超过最大长度在执行 DML 前使用 .abbreviate(maxLength) 验证或截断
错误诊断工作流
  1. 阅读完整错误消息 — Salesforce 错误采用 STATUS_CODE: message 格式
  2. 找到错误源代码行 — 在堆栈跟踪中查找 Class.MethodName: line X, column Y
  3. 确定触发器上下文 — 当前是 before/after insert/update?检查 CODE_UNIT_STARTED
  4. 检查级联故障 — 一个触发器失败可能导致父触发器中出现 CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY
  5. 使用最少数据重现问题 — 使用 Execute Anonymous 或专门的测试方法

4. 调试日志 CLI 命令

实时跟踪日志
# Stream logs as they are generated (colored output)
sf apex tail log --target-org myOrg --color

# Tail with specific log level
sf apex tail log --target-org myOrg --debug-level MyDebugLevel
列出并检索日志
# List recent debug logs
sf apex log list --target-org myOrg --json

# Get a specific log by ID
sf apex log get --log-id 07Lxxxxxxxxxxxxxxx --target-org myOrg

# Get the most recent log
sf apex log get --number 1 --target-org myOrg

# Get logs and save to file for analysis
sf apex log get --log-id 07Lxxxxxxxxxxxxxxx --target-org myOrg > debug.log
运行 Apex 并输出调试信息
# Execute anonymous Apex and capture output
sf apex run --target-org myOrg --file scripts/debug-script.apex

# Run inline Apex for quick debugging
echo "System.debug(Limits.getQueries());" | sf apex run --target-org myOrg
删除旧日志
# Clean up old logs to free storage
sf apex log list --target-org myOrg --json | \
  sf data delete bulk --sobject ApexLog --file -

5. 检查点和 Developer Console 调试

Execute Anonymous 调试

使用 Execute Anonymous 进行针对性调查:

// Reproduce an issue with specific data
Account testAcc = [SELECT Id, Name, Industry FROM Account WHERE Id = '001xxxxxxxxxxxx'];
System.debug('Account state: ' + JSON.serializePretty(testAcc));

// Test a specific method in isolation
MyService service = new MyService();
try {
    service.processRecord(testAcc);
    System.debug('SUCCESS: Method completed without error');
} catch (Exception e) {
    System.debug('FAILED: ' + e.getTypeName() + ' - ' + e.getMessage());
    System.debug('Stack trace: ' + e.getStackTraceString());
}

// Check governor limits after operation
System.debug('Post-execution SOQL: ' + Limits.getQueries());
System.debug('Post-execution DML: ' + Limits.getDmlStatements());
System.debug('Post-execution CPU: ' + Limits.getCpuTime() + 'ms');
检查点(开发者控制台)
  • 在开发者控制台的特定行上设置检查点
  • 检查点会捕获该执行点的堆状态、局部变量和静态变量
  • 同时最多激活 5 个检查点
  • 检查点会在 30 分钟后过期
  • 结果会显示在 Checkpoint Inspector 选项卡中
  • 当 System.debug() 不够用时,请使用检查点——它们会捕获完整的对象图
在开发者控制台中调试 SOQL 查询
Query Editor → Execute SOQL/SOSL directly
Logs tab → Filter by "DATABASE" events to see query performance
Query Plan tool → Use Tooling API: /services/data/vXX.0/query?explain=SELECT ...

6. 性能分析

识别 CPU 瓶颈

在调试日志中查找以下模式:

  • METHOD_ENTRY / METHOD_EXIT——计算成对事件之间的时间
  • 相对于操作规模,CUMULATIVE_LIMIT_USAGE CPU 时间过高
  • 循环中出现大量 HEAP_ALLOCATE
常见的性能反模式
反模式日志信号修复方法
在循环中执行 SOQL同一代码单元中重复出现 SOQL_EXECUTE_BEGIN在循环前查询,使用 Map 进行查找
在循环中执行 DML同一代码单元中重复出现 DML_BEGIN收集到 List 中,在循环结束后一次性执行 DML
大量分配堆内存循环中出现带有较大字节数的 HEAP_ALLOCATE使用 SOQL for 循环,分批处理
昂贵的 describe 调用重复调用 Schema.getGlobalDescribe()缓存到静态变量中
在循环中拼接字符串堆内存和 CPU 时间持续上升使用 String.join() 或 List<String>
未筛选的 SOQLSOQL_EXECUTE_END 中的行数过高添加 WHERE 筛选条件,使用可选择的索引字段
对集合进行嵌套循环CPU 使用率高,且没有 SOQL/DML 信号使用基于 Map 的查找,将复杂度从 O(n^2) 降至 O(n)
CPU 时间分析模式
Long startCpu = Limits.getCpuTime();
// ... operation under test ...
Long endCpu = Limits.getCpuTime();
System.debug('CPU consumed: ' + (endCpu - startCpu) + 'ms for operation X');
堆内存分析模式
Integer heapBefore = Limits.getHeapSize();
// ... operation under test ...
Integer heapAfter = Limits.getHeapSize();
System.debug('Heap delta: ' + (heapAfter - heapBefore) + ' bytes for operation X');

7. 跟踪标志

通过 CLI 设置跟踪标志
# Create a debug level first
sf data create record --sobject DebugLevel --target-org myOrg \
  --values "DeveloperName='DetailedDebug' MasterLabel='Detailed Debug' \
  ApexCode='FINE' ApexProfiling='FINEST' Database='FINE' System='DEBUG' \
  Validation='INFO' Workflow='INFO' Callout='INFO' Visualforce='INFO'"

# Query the debug level ID
sf data query --query "SELECT Id FROM DebugLevel WHERE DeveloperName='DetailedDebug'" \
  --target-org myOrg --json

# Create a trace flag for a specific user (lasts up to 24 hours)
sf data create record --sobject TraceFlag --target-org myOrg \
  --values "TracedEntityId='005xxxxxxxxxxxx' DebugLevelId='7dlxxxxxxxxxxxx' \
  LogType='USER_DEBUG' StartDate='2026-03-20T00:00:00.000Z' \
  ExpirationDate='2026-03-20T23:59:59.000Z'"
跟踪标志类型
LogType跟踪内容
USER_DEBUG特定用户的所有事务
CLASS_TRACING涉及特定 Apex 类的执行
DEVELOPER_LOG当前开发者控制台会话
通过 Setup UI 设置跟踪标志
  1. Setup > Debug Logs > New
  2. 选择跟踪对象(User、Apex Class、Apex Trigger)
  3. 设置开始/结束时间(最长 24 小时)
  4. 选择调试级别
  5. 保存——日志会持续捕获,直到过期或生成 20 条日志(以先发生者为准)

8. 注意事项

调试日志截断
  • 调试日志会在 20 MB 处截断——大型事务会丢失日志开头部分
  • 截断时,日志会显示 *** Skipped N bytes of detailed log
  • 为避免此情况:降低不需要的类别的日志级别,将非必要类别设为 NONE 或 ERROR
  • 截断的日志仍会在末尾包含 CUMULATIVE_LIMIT_USAGE
日志保留
  • 调试日志仅保留 24 小时(或直到每个跟踪标志累计 20 条日志)
  • 请立即下载关键日志,以便进行事后分析
  • 使用 sf apex log get 在日志过期前将其保存到本地文件
跟踪标志过期
  • 跟踪标志的最长有效时间为 24 小时
  • 过期后会静默停止捕获日志,不会发出警告
  • 在复现间歇性问题前,请重新创建跟踪标志
  • 每个 org 最多可保存 250 MB 的调试日志(优先清除最旧的日志)
调试的性能影响
  • 即使在生产环境中,System.debug() 语句也会消耗 CPU 时间
  • 写入调试日志会增加开销——较高的日志级别会减慢执行速度
  • 对于复杂事务,FINEST 日志级别可能会使 CPU 时间翻倍
  • 部署到生产环境前,请移除或加防护条件的调试语句:
    // Use a custom setting or custom metadata to gate debug output
    if (DebugSettings__c.getInstance().EnableDetailedLogging__c) {
        System.debug(LoggingLevel.FINE, 'Detailed: ' + JSON.serialize(records));
    }
    
生产环境中的 System.debug()
  • 除非正在运行的用户启用了跟踪标志,否则不会捕获调试语句
  • 无论是否设置跟踪标志,它们仍会消耗 CPU 时间
  • 切勿使用 System.debug() 记录敏感数据(PII、凭据、令牌)
  • 在生产环境中进行可观测性监控时,优先使用自定义日志框架(Platform Events + Big Objects)
其他注意事项
  • System.debug() 会对参数调用 toString()——如果对象图中存在空引用,这可能会抛出 NullPointerException
  • 聚合查询(COUNT()、SUM())每个聚合结果消耗 1 条查询记录
  • Database.setSavepoint() 和 Database.rollback() 计为 DML 语句
  • 在 after 触发器中,Trigger.new 是只读的——修改它会抛出运行时错误
  • 使用 @isTest(SeeAllData=true) 的测试在开发环境中可能通过,但由于数据差异,在 CI 中可能失败

9. 调试工作流

分步流程
  1. 复现问题

    • 找出失败的具体用户操作、API 调用或自动化流程
    • 记录时间范围以及遇到问题的用户
  2. 设置跟踪标志

    # Ensure trace flag is active for the user
    sf apex tail log --target-org myOrg --color
    
  3. 触发问题并捕获日志

    • 通过 UI、API 或 Execute Anonymous 复现
    • 立即保存日志:sf apex log get --number 1 --target-org myOrg > issue.log
  4. 先扫描错误

    • 在日志中搜索 EXCEPTION_THROWN、FATAL_ERROR 和 LIMIT_USAGE
    • 如果日志被截断,请重点查看末尾的 CUMULATIVE_LIMIT_USAGE
  5. 追踪执行路径

    • 查找 CODE_UNIT_STARTED,以确定执行了哪些触发器/类
    • 追踪执行顺序:before 触发器、DML、after 触发器、工作流、流程构建器、流程
  6. 检查治理限制

    • 查看 LIMIT_USAGE_FOR_NS——是否有任何限制超过 70%?
    • 将 SOQL 计数与 SOQL_EXECUTE_BEGIN 事件数进行交叉核对
  7. 找出根本原因

    • 是数据问题吗?(缺少记录、字段为空)
    • 是逻辑问题吗?(条件错误、缺少批量处理)
    • 是限制问题吗?(循环中的 SOQL、循环中的 DML)
    • 是并发问题吗?(记录锁定、竞态条件)
    • 是配置问题吗?(验证规则、共享规则、权限)
  8. 修复并验证

    • 应用最小且正确的修复
    • 在跟踪标志启用时重新运行,以确认问题已解决
    • 检查治理限制是否有所改善(而不只是错误消失)
快速诊断命令
# Search for errors in a saved log
grep -E "EXCEPTION_THROWN|FATAL_ERROR|LIMIT_USAGE" debug.log

# Count SOQL queries in log (look for loops)
grep -c "SOQL_EXECUTE_BEGIN" debug.log

# Count DML operations in log
grep -c "DML_BEGIN" debug.log

# Find slow queries (queries returning many rows)
grep "SOQL_EXECUTE_END" debug.log | grep -E "Rows:[0-9]{3,}"

10. 跨技能协作

需求委派给原因
修复 Apex 代码sf-apex生成并审查代码变更
编写/运行测试sf-testing测试执行、覆盖率、断言
部署修复sf-deploy部署编排
调查数据sf-data查询和检查组织数据
安全审计sf-securityCRUD/FLS 和共享审查

参考资料

  • 调试参考 -- Limits 类方法、日志解析模式、Execute Anonymous 模式、错误处理、性能分析、Tooling API 跟踪标志
  • 治理限制 -- 每笔事务的 SOQL、DML、CPU、堆内存限制

评论

支持 Markdown