- CheckResult: statusDetail -> observation (持久化) + detail (API 动态派生) - 存储: status_detail 列 -> observation TEXT (JSON) - CheckerDefinition: 新增 buildDetail(observation) 方法 - 各 checker 返回结构化 observation,API 层通过 registry 调用 buildDetail - HTTP: bodyPreview 在 status/header 失败时也提前采集 - UDP: observation 包含 durationMs,未响应归为 error failure - CMD: 超时/输出超限时保留已收集 observation - TCP: connectTimeMs 仅含连接建立耗时,不含 banner 等待 - 新增 buildDetail 单测和 mapCheckResult 覆盖测试 - 同步 openspec 主规范,归档 checker-observation 变更
8.1 KiB
Purpose
定义 Cmd 类型拨测目标:通过 type: cmd 配置执行本地命令(如进程检查、脚本健康检测),捕获 exit code、stdout、stderr,按 expect 规则校验并生成 matched 判定。
Requirements
Requirement: cmd target 配置
系统 SHALL 支持 type: cmd 的 target 配置,通过 cmd.exec 和 cmd.args 描述本地命令,并使用 cmd 专用字段配置工作目录、环境变量和输出限制。
Scenario: 解析 cmd target
- WHEN YAML 中 target 配置
type: cmd、cmd.exec: "pgrep"和cmd.args: ["nginx"] - THEN 系统 SHALL 将其解析为 cmd checker,并保留 exec、args、cwd、env、maxOutputBytes、interval、timeout 和 expect 配置
Scenario: cmd target 缺少 exec
- WHEN YAML 中 target 配置
type: cmd但缺少cmd.exec - THEN 系统 SHALL 以配置错误退出,并提示该 target 缺少 cmd.exec 字段
Scenario: cwd 相对配置文件目录解析
- WHEN cmd target 配置
cmd.cwd: "scripts"且配置文件位于/opt/checker/probes.yaml - THEN 系统 SHALL 将 cwd 解析为
/opt/checker/scripts
Scenario: cmd 不使用 shell
- WHEN cmd target 配置
exec和args - THEN 系统 MUST 直接执行该程序和参数,不通过 shell 解释整段命令字符串
Scenario: env 默认继承并允许覆盖
- WHEN cmd target 配置
cmd.env: {LANG: "C"}且当前进程环境包含PATH - THEN 系统 SHALL 继承当前进程的全部环境变量,并将
LANG覆盖为"C"
Scenario: 不支持 stdin
- WHEN cmd target 配置并执行命令
- THEN 系统 MUST NOT 向子进程 stdin 写入数据,避免命令因等待输入而阻塞
Requirement: cmd checker 执行
系统 SHALL 按 cmd target 配置执行本地命令,记录执行耗时、退出码、stdout 和 stderr observation,并在执行失败时产生结构化错误信息。
Scenario: 命令正常退出
- WHEN cmd target 执行的进程正常退出且 exit code 为 0
- THEN 系统 SHALL 记录
durationMs和包含 exitCode、stdoutPreview、stderrPreview 的 observation,并进入 expect 校验;API detail SHALL 为exitCode=0
Scenario: 命令非零退出
- WHEN cmd target 执行的进程正常退出但 exit code 为 1
- THEN 系统 SHALL 记录包含 exitCode、stdoutPreview、stderrPreview 的 observation,并由 expect.exitCode 决定 matched 结果;API detail SHALL 为
exitCode=1
Scenario: 命令启动失败
- WHEN cmd target 的 exec 不存在或无法启动
- THEN 系统 SHALL 记录
matched=false,observation SHALL 为 null,并在 failure 中写入 kind=error和可读错误信息
Scenario: 命令超时
- WHEN cmd target 在 timeout 时间内未结束
- THEN 系统 MUST 终止该子进程,记录
matched=false,并在 failure 中写入命令超时信息;如已收集输出片段,observation SHALL 包含 stdoutPreview、stderrPreview 和 error
Scenario: 命令输出超限
- WHEN cmd target 的 stdout 和 stderr 合计输出超过
maxOutputBytes - THEN 系统 MUST 停止收集输出并终止该检查,记录
matched=false,并在 failure 中写入输出超限信息;observation SHALL 包含已截断输出预览和 error
Requirement: cmd expect 校验
系统 SHALL 支持 cmd 专用 expect,包括 exitCode、durationMs、stdout 和 stderr,并按 exitCode、durationMs、stdout、stderr 的阶段顺序快速失败。exitCode SHALL 保持有限整数数组语义,未配置时默认 [0]。durationMs SHALL 使用共享 ValueMatcher 校验完整命令执行耗时。stdout 和 stderr MUST 使用共享 ContentRules 数组,直接 matcher 作用于对应输出文本,json extractor SHALL 支持对 JSON CLI 输出执行 JSONPath 断言。
Scenario: 默认 exitCode 成功语义
- WHEN cmd target 未显式配置
expect.exitCode - THEN 系统 SHALL 使用默认
expect.exitCode: [0]进行校验
Scenario: 显式 exitCode 校验
- WHEN cmd target 配置
expect.exitCode: [0, 2]且实际 exit code 为 2 - THEN 系统 SHALL 判定 exitCode 阶段通过,并继续后续 expect 阶段
Scenario: exitCode 不匹配快速失败
- WHEN cmd target 配置
expect.exitCode: [0]且实际 exit code 为 1 - THEN 系统 SHALL 立即返回
matched=false,并在 failure 中写入 phase=exitCode、path=exitCode、expected 和 actual
Scenario: durationMs 校验
- WHEN cmd target 配置
expect.durationMs: {lte: 1000}且实际执行耗时为 1500ms - THEN 系统 SHALL 返回
matched=false,failure 的 phase 为duration
Scenario: stdout 按配置顺序校验
- WHEN cmd target 配置
expect.stdout为两个 ContentRules,第一条通过且第二条失败 - THEN 系统 SHALL 先执行第一条 stdout 规则,再执行第二条,并将 failure.path 指向失败的
stdout[1]
Scenario: stderr 校验为空
- WHEN cmd target 配置
expect.stderr: [{empty: true}]且实际 stderr 为空字符串 - THEN 系统 SHALL 判定 stderr 阶段通过
Scenario: stdout JSON 输出校验
- WHEN cmd target 输出 stdout 为
{"status":"ok"}且配置expect.stdout: [{json: {path: "$.status", equals: "ok"}}] - THEN 系统 SHALL 判定 stdout 阶段通过
Scenario: stdout 失败后不检查 stderr
- WHEN cmd target 同时配置 stdout 和 stderr 规则,且 stdout 规则失败
- THEN 系统 SHALL 快速失败并 MUST NOT 继续执行 stderr 规则
Requirement: cmd checker 启动期配置校验
系统 SHALL 在启动期对 cmd checker 的配置契约和语义执行严格校验。Cmd target 的 cmd 分组 SHALL 只允许 exec、args、cwd、env、maxOutputBytes 字段。Cmd expect SHALL 只允许 exitCode、durationMs、stdout、stderr 字段。未知字段、非法类型、不可编译正则和 ReDoS 风险正则 MUST 导致启动期配置错误。expect.exitCode SHALL 保留原有有限整数数组语义,不限制到特定平台范围。
Scenario: cmd args 类型非法
- WHEN YAML 中 cmd target 配置
cmd.args不是字符串数组 - THEN 系统 SHALL 以配置错误退出,提示 cmd.args 格式错误
Scenario: cmd env 值类型非法
- WHEN YAML 中 cmd target 配置
cmd.env,且任一环境变量值不是字符串 - THEN 系统 SHALL 以配置错误退出,提示 cmd.env 对应变量值必须为字符串
Scenario: cmd expect exitCode 类型非法
- WHEN YAML 中 cmd target 配置
expect.exitCode不是整数数组 - THEN 系统 SHALL 以配置错误退出,提示 expect.exitCode 必须为整数数组
Scenario: cmd expect durationMs 非法
- WHEN YAML 中 cmd target 配置
expect.durationMs不是合法ValueMatcher - THEN 系统 SHALL 以配置错误退出,提示 expect.durationMs 格式错误
Scenario: stdout 必须为 ContentRules 数组
- WHEN YAML 中 cmd target 配置
expect.stdout但其值不是数组 - THEN 系统 SHALL 以配置错误退出,提示 expect.stdout 必须为数组
Scenario: stderr 必须为 ContentRules 数组
- WHEN YAML 中 cmd target 配置
expect.stderr但其值不是数组 - THEN 系统 SHALL 以配置错误退出,提示 expect.stderr 必须为数组
Scenario: stdout text rule 空对象非法
- WHEN YAML 中 cmd target 配置
expect.stdout: [{}] - THEN 系统 SHALL 以配置错误退出,提示 stdout 规则必须包含至少一个合法 matcher 或 extractor
Scenario: stderr text rule 未知字段非法
- WHEN YAML 中 cmd target 配置
expect.stderr: [{foo: "bar"}] - THEN 系统 SHALL 以配置错误退出,提示 stderr 规则包含未知 matcher 或未知 extractor
Scenario: stdout regex 正则非法
- WHEN YAML 中 cmd target 配置
expect.stdout: [{regex: "[invalid"}] - THEN 系统 SHALL 在启动期配置校验失败,而不是延迟到运行期抛错
Scenario: cmd expect 未知字段失败
- WHEN YAML 中 cmd target 的 expect 包含
status: [200]、maxDurationMs: 1000或其他非 cmd expect 字段 - THEN 系统 SHALL 以配置错误退出,提示 expect 包含未知字段