运行 (Pro)
注意:规则引擎 2.0 是 DefectDojo Pro 专属功能。
运行是一条规则的一次执行。无论成功还是失败,每次运行都会被记录,其中的每个节点也都会留下痕迹。规则引擎 2.0 > 运行页面会列出这些记录。
一次运行会记录哪些内容
| Field | Meaning |
|---|---|
| 规则 | 执行该操作的规则。 |
| 触发方式 | 触发此次运行的事件,例如 finding.created、schedule 或 manual。 |
| 触发人 | 在有人手动触发时,指按下"运行"的人,或保存了引发此次运行的发现项的人。对于按计划触发,以及诸如导入或没有用户的 API 调用等无人在场的变更,此字段为空。这与规则的所有者不同,所有者指的是此次运行以谁的身份执行。 |
| 状态 | Running、Success 或 Error。 |
| 开始时间与结束时间 | 运行发生的时间。只有在仍在运行时,结束时间才为空。 |
| 错误 | 若运行失败,导致其结束的错误。 |
| 统计信息 | 按节点统计的总数、级联事件以及延迟处理的工作。 |
| 深度 | 此次运行距离触发它的原始事件经过了多少次级联跳转。 |
| 源运行 | 对于级联触发的运行,指其所发出的事件触发了此次运行的那次运行。 |
节点执行记录
在一次运行中,每个节点都会记录自己的一行数据:
| Field | Meaning |
|---|---|
| 顺序 | 该节点在执行顺序中所处的位置。 |
| 节点 | 节点的 ID、类型,以及(如果设置了)标签。 |
| 状态 | 节点是执行完成还是抛出了错误。 |
| 输入项数 | 进入该节点的项目数量。 |
| 输出项数 | 离开该节点的项目数量,按输出端口分别统计,因此 If / Filter 节点会分别显示其 true 分支和 false 分支的数量。 |
| 摘要 | 该节点报告的各类计数,例如它更改了多少个发现项。 |
| 错误 | 若节点执行失败,其抛出的错误。 |
当一条规则的执行结果不符合预期时,这份执行记录就是你需要查看的内容。如果一个 If / Filter 节点显示输入了 400 个项目,但 true 分支的输出为 0,那么无需猜测你就能知道条件设置有误。
执行模型
节点按拓扑顺序执行:只有当所有输入该节点的上游都执行完毕后,该节点才会执行。一个有多条输入边的节点会接收到所有上游输出拼接后的结果。没有任何上游输入的节点仍会执行,只是输入列表为空。
失败的运行不会造成任何更改
一次运行是原子性的。只要有任何节点抛出错误,此次运行对发现项所做的全部更改都会被回滚。
但执行记录不会随之回滚。节点记录行和 Error 状态是在此之后写入的,因此一次失败的运行能够准确告诉你是哪个节点出了问题,同时不会留下任何只完成一半的更改。这是查看"运行"页面时需要牢记的最重要的一条保证:出错的运行等同于什么都没做的运行。
出站操作也遵循相同的规则。投递记录会在此次运行的事务内被写入,并且只有在事务提交后才会真正发送,因此被回滚的运行不会发出任何内容。
同一时间每条规则只能有一次运行
一条规则同一时间只能有一次运行在进行中。如果同一条规则在仍在运行时被再次触发,第二次触发不会与其产生竞争,而是会等待并重试。
不同的规则会完全并发地运行,因此一条运行缓慢的规则永远不会拖慢其他规则。
如果一次运行由于某种原因被遗弃——例如执行它的工作进程被终止——它的锁会在一个停滞时间窗口(默认 30 分钟)之后被释放,从而避免该规则被永久卡住。一次运行在接近该时间窗口时会先自行停止并干净地回退,因此一次只是运行缓慢的运行绝不会与它自己的替代运行同时执行。
级联
一条更改了发现项的规则,恰好会产生另一条规则可以据以触发的事件。规则引擎 2.0 允许这种情况发生,因此 A -> B -> C 这样的链条是可行的,同时它通过两种独立的方式对此加以限制:
- 深度。 一个事件从引发它的变更开始,最多可以经过 3 次级联跳转。
- 链成员关系。 每个事件都携带其链条中已经经过的规则列表,同一条规则在同一条链中永远不会运行两次。因此,一条规则不能重新触发自身,两条规则之间也不会相互反复触发。
一次运行的深度和源运行字段可以帮助你沿着链条追溯到最初引发它的变更。触发人会沿着整条链条一直传递下去,因此由某人引发的一次级联,在每一跳都仍然可以归因到此人。
由正在运行的规则所做出的更改,会被归因到该规则自身的级联,而不会看起来像是全新的用户操作,因此一条在内部委派工作的规则不会使链条被人为拉长。
规模与限制
一次运行没有数量上限。 无论规则的作用范围匹配到多少内容,规则都会全部处理。一条在处理到第 N 个发现项时就悄悄停止的规则,是不值得信任的规则。
相反,一次运行会以分块的方式处理,默认每次处理 1,000 个发现项。内存中只保留当前这一块的数据,因此对一个非常大的范围进行扫描时,受限的是内存占用,而不是覆盖范围。唯一的例外是预览,它确实设有上限,并且在被截断时会在执行记录中说明这一点。
还有另外两个数值决定了工作是如何被划分的:
- 每个事件的发现项数量,默认值为 500。一次批量更改会被拆分到多个事件中,每个事件各自成为一次独立的运行。对于一次大规模导入而言,实际效果是产生数量可控的若干次运行,而不是每个发现项一次运行。
- 每个发现项的发送上限,默认值为 1,000。若某个出站节点被设置为每个发现项发送一条消息,那么在单次运行中达到此上限后就会停止,并记录一条可见的跳过说明,注明有多少发现项未被发送。这一限制约束了投递记录和排队任务的数量,而分块处理本身已不再对这些内容加以约束。
以上三项都是部署级设置,记录在配置中。
一次运行可以持续多长时间
一次运行在处理完每一块之后都会记录一次心跳。停滞检测读取的是这个心跳,而不是开始时间,因此一次仍在取得进展的长时间扫描,永远不会被误判为工作进程已崩溃。
有两个时间窗口适用,二者均可配置:
- 一次运行如果 30 分钟内没有心跳,就会被视为已遗弃、标记为错误,并释放其锁。
- 一次运行在六小时后会被直接终止,以防止出现永远无法结束的运行。
保留期限
默认情况下,运行记录会连同其各节点的记录行以及发现项溯源信息一起保留 180 天。投递记录则单独保留 180 天。
产品会明确告知这一点,而不是让它隐而不显:一次运行的详情页会显示保留期限,以及该运行将被删除的日期。仍然持有投递记录的运行,会一直保留到这些投递记录被清理为止。
这两个期限都可以配置,并且都可以设置为无限期保留记录。参见配置。
手动运行规则
触发方式为手动运行的规则,可以通过规则列表中的运行操作来执行。其他触发方式的规则,会在其触发条件满足时自动运行。
编辑器中的预览是执行图的另一种方式。它会运行真实的引擎,然后回滚所有更改,不记录任何运行,并强制所有出站操作以模拟方式执行。在构建规则时使用预览,而要查看实际发生了什么,则查看运行记录。
发现项上的溯源信息
运行记录回答的是"这条规则做了什么?",而溯源信息回答的是相反的问题:“这个发现项为什么会发生变化?”
规则所做的每一次更改,都会连同负责的规则、运行及节点一起被记录到对应的发现项上,并以时间线的形式呈现在该发现项本身上。所记录的操作类型有:
| Action | Meaning |
|---|---|
created、updated、closed、reopened | 发现项的生命周期状态发生了变化。 |
duplicate、status_change | 其重复标记或状态标记发生了变化。 |
notified | 已就此发出通知。 |
delivered | 一次出站投递已覆盖此项。 |
字段编辑会记录发生了什么变化,包括每个字段变更前后的值。过长的值会在记录中被截断,这样时间线始终是变更的记录,而不会变成发现项的第二份副本。
通知和投递也会记录在这里。这是刻意为之:否则,一条只发送了消息却没有更改任何字段的规则,将不会在发现项上留下任何痕迹。
溯源信息不依赖于规则而存在。删除一条规则或一次运行时,时间线条目会被保留,只是解除与其的关联,因此当有人进行清理时,历史记录不会消失。
删除带有历史记录的规则
一条已经产生过投递记录的规则,不能在其投递记录仍然存在的情况下被删除。请先删除这些投递记录,或者保留该规则并将其禁用。这是有意为之:投递记录保存着实际发送到外部系统的内容,而级联删除会连同正在进行中的发送一起被删除。