关于 nebula-logger-plugin-development
面向 Salesforce Apex 开发者的 Nebula Logger 插件开发指南,介绍触发器与批处理扩展点、元数据注册、项目结构、执行顺序和测试;插件框架仅适用于 unlocked package。
主要功能
- 01Apex 触发器与批处理接口
- 02通过自定义元数据注册插件
- 03执行顺序与插件组合
- 04项目结构和打包指南
- 05测试模式与发布检查清单
适用场景
- 01在触发器处理中丰富日志记录
- 02日志清理前归档或应用策略
- 03为新日志注册外发通知
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ jongpie/ nebulalogger --skill nebula-logger-plugin-development安装后在 Claude Code 中输入/nebula-logger-plugin-development确认已加载。
详细介绍
为 Nebula Logger 构建插件
包兼容性
插件框架仅在解锁包中可用。托管包(命名空间 Nebula)目前不公开插件扩展点。
如果计划编写插件,请安装解锁包。请参阅 nebula-logger-install 了解如何选择。
请注意,LoggerPlugin、LoggerPlugin.Triggerable、LoggerPlugin.Batchable、LoggerTriggerableContext 和 LoggerBatchableContext 都是 public(而非 global)。在本技能集合的其他部分,指导原则都是“仅依赖 global”(参见 nebula-logger-instrumentation 的“支持的 API 表面”一节)。插件框架是一个有意为之的例外:这些扩展点是 public,因为它们只能在解锁包自身的编译单元内访问。与任何 public 表面一样,可能会发生破坏性变更——请将插件固定到你已测试过的 Nebula Logger 版本,并在升级后重新验证。
插件框架概述
Nebula Logger 的插件框架允许你注册 Apex 类,在以下两个扩展点中运行:
- 触发器扩展点 - 在
LoggerSObjectHandler执行期间,响应LogEntryEvent__e、Log__c、LogEntry__c、LogEntryTag__c、LoggerScenario__c和LoggerTag__c上的触发器运行。可用于添加字段、丰富数据,或在创建日志时发送外部通知。 - 批处理扩展点 - 在
LogBatchPurger执行期间运行。可用于将日志归档到外部系统、应用自定义清理策略,或在删除记录前为已清理的记录生成指标。
两个扩展点都由 LoggerPlugin__mdt 记录驱动。添加插件的步骤是:编写实现相应接口(如果插件同时承担触发器和批处理职责,则实现两个接口)的 Apex 类,然后创建指向该类的 LoggerPlugin__mdt 记录。
两个扩展点都强烈建议优先使用 Apex,而不是 Flow。 框架在技术上支持通过 SObjectHandlerFlowName__c / BatchPurgerFlowName__c 使用基于 Flow 的插件,但 Flow 支持目前存在已知问题,且没有确定的修复时间——未来版本中甚至可能会完全弃用。新插件应实现以下 Apex 接口,并将 LoggerPlugin__mdt 记录上的 Flow 字段留空。
两个接口
这两个接口都位于 Nebula Logger - Core 包的 LoggerPlugin 中。
LoggerPlugin.Triggerable(触发器扩展点)
实现一个方法:
void execute(LoggerPlugin__mdt configuration, LoggerTriggerableContext input);
configuration是注册该插件的LoggerPlugin__mdt记录——可用它读取插件专属设置。input描述当前触发器上下文,并公开sobjectType、triggerOperationType、triggerNew、triggerNewMap、triggerOldMap,以及一个triggerRecords列表;该列表按记录配对旧版和新版记录(用于便于 Flow 访问)。
LoggerPlugin.Batchable(批处理扩展点)
实现与 Database.Batchable 生命周期相匹配的三个方法:
void start(LoggerPlugin__mdt configuration, LoggerBatchableContext input);
void execute(LoggerPlugin__mdt configuration, LoggerBatchableContext input, List<SObject> scopeRecords);
void finish(LoggerPlugin__mdt configuration, LoggerBatchableContext input);
scopeRecords 是 LogBatchPurger 即将处理的当前批次记录。LogBatchPurger 会从层级最低的对象开始向上遍历(LogEntryTag__c,然后是 LogEntry__c,再然后是 Log__c),筛选父级 Log__c.LogRetentionDate__c 已过期的记录。如果插件行为需要因对象而异,请检查 input.sobjectType。
LoggerPlugin__mdt 配置
每个插件都会有一条 LoggerPlugin__mdt 记录。关键字段:
| 字段 | 用途 |
|---|---|
DeveloperName / Label | 标识插件。 |
IsEnabled__c | 无需删除记录即可切换启用状态。标记为 SubscriberControlled,以便管理员在已安装的组织中切换此项。 |
SObjectHandlerApexClass__c | 实现 LoggerPlugin.Triggerable 的 Apex 类名。设置此字段以在触发器扩展点注册该类。 |
SObjectHandlerFlowName__c | 基于 Flow 的触发器插件的 Flow API 名称。留空 - 参见上文“优先使用 Apex”的说明。 |
SObjectHandlerExecutionOrder__c | 对同一处理程序上的多个插件进行排序的整数。数字越小,越先运行。若顺序相同,则按开发者名称排序。 |
BatchPurgerApexClass__c | 实现 LoggerPlugin.Batchable 的 Apex 类名。设置此字段以在批处理扩展点注册该类。 |
BatchPurgerFlowName__c | 基于 Flow 的批处理插件的 Flow API 名称。留空 - 参见上文“优先使用 Apex”的说明。 |
BatchPurgerExecutionOrder__c | 对多个批处理插件进行排序。 |
Description__c / Link__c / VersionNumber__c | 显示在 Logger Console 中的元数据,便于管理员了解。 |
根据类实现的接口,设置相应的 Apex 类字段组合:对于 LoggerPlugin.Triggerable,设置 SObjectHandlerApexClass__c;对于 LoggerPlugin.Batchable,设置 BatchPurgerApexClass__c;如果同一个类实现两个接口(如 LogEntryArchivePlugin),则两个字段都指向该类。Flow 字段留空。
插件文件夹布局
nebula-logger/plugins/<name>/ 下的现有插件都遵循一致的布局。创建新插件时,请参照此布局:
nebula-logger/plugins/<name>/
plugin/
classes/ # Apex classes (both implementation and *_Tests.cls test classes)
customMetadata/ # LoggerPlugin.<Name>.md-meta.xml
objects/ # Any plugin-specific custom objects/fields (optional)
permissionsets/ # <Name>PluginAdmin.permissionset-meta.xml (optional)
testSuites/ # <Name>Plugin.testSuite-meta.xml grouping the plugin's test classes
README.md
测试类与被测代码放在同一个 plugin/classes/ 文件夹中,不会单独放在顶层的 tests/ 文件夹下。Slack 插件的 plugin/slack/ 子文件夹是打包共享 core/main 元数据时产生的特定布局;新插件应省去这层嵌套,将所有内容直接放在 plugin/ 下。
LoggerPlugin.<Name>.md-meta.xml 文件是注册记录 - 按照上述说明填入 SObjectHandlerApexClass__c 和/或 BatchPurgerApexClass__c。可参考以下现有插件:
nebula-logger/plugins/slack/- 发送 Slack 通知的触发器插件。nebula-logger/plugins/log-retention-rules/- 根据 CMDT 规则设置LogRetentionDate__c的触发器插件。nebula-logger/plugins/big-object-archiving/- 单个类(LogEntryArchivePlugin)实现了两个接口 - 触发器端将记录捕获到大对象中,批处理端则在清除前进行归档。nebula-logger/plugins/async-failure-additions/- 为FlowExecutionErrorEvent、意外的批处理失败和 Queueable 最终处理器添加日志记录。
排序与组合
- 针对某个对象的触发器插件会在该对象的内置
LoggerSObjectHandler逻辑之后运行。 - 同一处理器上的多个插件按
SObjectHandlerExecutionOrder__c排序运行(空值排在最后,然后按DeveloperName排序)。 - 会修改触发器记录(添加标签、填充字段)的插件应先于发布出站通知的插件运行,这样通知才能获取已丰富的数据。
测试插件
- 每个插件都应随附一个匹配的
<PluginClass>_Tests.cls,并与实现类一起放在plugin/classes/中。 - 将插件的测试类添加到
plugin/testSuites/下的<Name>Plugin.testSuite-meta.xml中(可参考LoggerLogEntryArchivePlugin.testSuite-meta.xml和LoggerLogRetentionRulesPlugin.testSuite-meta.xml中的模式)。测试套件将作为sf apex run test --suite-names <Name>Plugin命令的目标。目前只有核心包有专用的npm run test:apex:suite:core脚本;插件套件通过npm run test:apex(运行RunLocalTests)或临时调用sf apex run test --suite-names进行测试。 - 对于触发器插件,手动构造一个包含要测试的触发器记录的
LoggerTriggerableContext,然后直接调用execute(configuration, input)。测试中无需实际触发触发器。 - 对于批处理插件,构造一个
LoggerBatchableContext,并传入合成的scopeRecords列表。断言其副作用(DML、通过System.Test.setMock模拟的调用、已发布的事件)。
新插件检查清单
发布新插件前:
- Apex 类至少实现
LoggerPlugin.Triggerable和LoggerPlugin.Batchable中的一个;如果同一个类需要响应触发器事件并参与清理批处理,也可以两者都实现。 - 存在
LoggerPlugin.<Name>.md-meta.xml,其IsEnabled__c=true(如果设为选择启用,则为false),并填写与类所实现接口对应的类名字段:Triggerable对应SObjectHandlerApexClass__c,Batchable对应BatchPurgerApexClass__c;如果类实现两个接口,则填写这两个字段。 <Name>PluginAdmin.permissionset-meta.xml授予对插件自有对象和 CMDT 的完整访问权限。<PluginClass>_Tests.cls覆盖正常路径、空范围和禁用配置等情况。- 插件文件夹中的
README.md说明安装步骤和任何前置条件。 sfdx-project.json包含该插件的packageDirectories条目,以便将其构建并作为独立的未锁定包安装。
相关技能
- nebula-logger-console - 控制台中的
LoggerPlugin__mdt列表视图是管理员启用和停用插件的位置。 - nebula-logger-purging-and-retention - 了解
LoggerPlugin.Batchable插件的接入方式。