1
0
Files
DiAL/docs/development/checker.md
lanyuanxiaoyao 77c6015b3a refactor: 将 checker normalize 职责下沉到各 runner 目录
- 新增 CheckerDefinition.normalize 必需方法,typecheck 兜底遗漏实现
- 新增 expect/normalize.ts 共享 helper(compactExpect、normalizeValue、
  normalizeContent、normalizeKeyed)
- 为 HTTP、Cmd、DB、TCP、UDP、ICMP、LLM、WS、DNS 各新增独立 normalize.ts
- 简化 normalizer.ts:删除所有 checker type switch,改为 registry 委托
- 修复 DNS authoring 简写 bug:durationMs、valueCount、result 等字段
  现可通过完整加载链路
- 新增 DNS 回归测试和 registry 级合同测试
- 更新 docs/development/checker.md:补充 normalize 规范、文件结构、
  测试要求和 checklist
2026-05-25 16:16:41 +08:00

10 KiB
Raw Permalink Blame History

Checker 开发

Checker 是 DiAL 的核心扩展单元。每个 checker 是 src/server/checker/runner/<type>/ 下的自包含目录包含类型、schema、语义校验、执行逻辑、序列化和断言。

适用场景:新增 checker、修改 checker 配置或 expect、调整 checker 注册机制、改动 checker 测试或用户文档同步规则。

新增或修改 checker 前必须阅读 开发入口配置文件校验规则Checker 用户文档。还应阅读现有同类 checker 的实现和测试,例如 src/server/checker/runner/http/tests/server/checker/runner/http/

设计原则

  • 每个 checker 必须自包含在 src/server/checker/runner/<type>/
  • checker 专属类型、schema、validate、execute、expect、normalize 和协议辅助逻辑放在同一目录。
  • 注册只修改 src/server/checker/runner/index.ts,中间层不新增 type switch。
  • schema 层只描述契约,语义规则放入 validate.ts
  • resolve() 只做默认值填充、路径解析和单位转换,不执行校验。
  • execute() 必须支持 CheckerContext.signal 超时取消。
  • expect 字段必须选择合适断言模型,不为了统一而滥用 ValueMatcher。
  • failure phase 命名遵循去单位后缀规则,例如 durationMs 对应 duration

架构目标

checkerRegistry
  ├── runner/index.ts
  ├── schema/builder.ts
  ├── schema/validate.ts
  ├── config-loader.ts
  ├── engine.ts
  └── store.ts

注册后,中间层通过 registry 自动委托 schema 生成、契约校验、配置 normalize、配置 resolve、执行和序列化。新增 checker 不应在中间层新增 switch/case 或类型分支。

标准文件结构

文件 职责
index.ts 模块入口re-export Checker 类
types.ts Checker 专属类型
schema.ts TypeBox 契约 schema包含 config 和 expect
validate.ts 启动期语义校验
normalize.ts Checker 专属 authoring expect 归一化
execute.ts Checker 类,实现 normalize、resolve、execute、serialize
expect.ts Checker 专用断言函数
其他文件 协议解析、编码、provider 适配、平台命令封装等专属逻辑

类型定义

types.ts 中定义:

  • RawXxxTargetConfig
  • RawXxxExpectConfig
  • ResolvedXxxExpectConfig
  • ResolvedXxxTarget extends ResolvedTargetBase

不需要修改顶层 checker/types.ts。base interface 使用 index signature 支持扩展。

Schema

checker 必须提供 CheckerSchemas,包含 Authoring 和 Normalized 两套 config/expect 片段。Authoring 描述用户 YAML 可写 DSLNormalized 描述 normalizer 输出。

常用 fragments

Fragment 用途
durationSchema 时长字符串
sizeSchema 大小单位
statusCodePatternSchema HTTP 状态码或范围
stringMapSchema headers、env 等字符串映射
createValueMatcherSchema() ValueMatcher
createContentExpectationsSchema() ContentExpectations
createKeyedExpectationsSchema() KeyedExpectations

默认对象策略为 additionalProperties: false。只有明确的动态键值表可以开放任意键名。

语义校验

validate.ts 中实现 JSON Schema 无法表达的规则,统一返回 ConfigValidationIssue[],不要直接拼接最终错误字符串。

共享校验工具包括:

函数 用途
validateRawValueExpectation 校验 Raw ValueExpectation
validateRawContentExpectations 校验 ContentExpectations
validateRawKeyedExpectations 校验 KeyedExpectations
validateJsonPath 校验项目支持的 JSONPath 子集
isJsonValue 判断合法 JSON value

normalize 规范

normalize()CheckerDefinition 中定义为必需方法,负责将 authoring expect DSL 转换为 normalized 形态。输入为变量已解析后的 target输出为适配 normalized schema 的 target。该方法在 resolve() 和 normalized contract 校验之前执行。

normalize.ts 中实现 normalizeTargetExpect 函数,execute.ts 中的 normalize 方法委托到该函数。

共享 normalize helper 位于 src/server/checker/expect/normalize.ts

函数 用途
compactExpect 合并两个 expect record过滤 undefined 字段
normalizeValue ValueMatcher 原始值简写展开为 {equals: value}
normalizeContent ContentExpectations 简写展开为 normalized 形态
normalizeKeyed KeyedExpectations 对象形态展开为 [{key, matcher}] 数组
import { compactExpect, normalizeContent, normalizeKeyed, normalizeValue } from "../../expect/normalize";

export function normalizeTargetExpect(target: RawTargetConfig): RawTargetConfig {
  if (target.expect === undefined || !isPlainObject(target.expect)) return target;
  const raw = target.expect as Record<string, unknown>;
  return {
    ...target,
    expect: compactExpect(raw, {
      /* checker 专属字段映射 */
    }),
  };
}

expect 字段的归一化规则ValueMatcher 字段调用 normalizeValue()ContentExpectations 字段调用 normalizeContent()KeyedExpectations 字段调用 normalizeKeyed()boolean/enum/array 等非断言模型字段直接透传。

resolve 规范

resolve() 只做内置默认值填充、路径解析、单位转换,不执行校验。输入已经通过 Normalized schema 和语义校验expect 已是 normalized 形态。

const expect = target.expect as ResolvedXxxExpectConfig | undefined;
const resolvedExpect: ResolvedXxxExpectConfig = expect
  ? { ...expect, status: expect.status ?? [200] }
  : { status: [200] };

返回值使用 satisfies ResolvedXxxTarget 确保类型正确。

execute 规范

  • 始终记录 timestampstart = performance.now()
  • 通过 ctx.signal 支持超时取消。
  • 首个 expect 失败即停止,返回带 failure 的结果。
  • 成功时 failure: null, matched: true
  • 异常时使用 errorFailure()
  • 不匹配时使用 mismatchFailure()
  • expected 参数应传用户可读值,必要时使用 displayValueExpectation()

expect 字段选择

场景 模型
状态类结果且集合小而稳定 enum 或 boolean
单值数字指标或字符串元数据 ValueMatcher
文本、JSON、HTML、XML 或半结构化内容 ContentExpectations
动态键值表 KeyedExpectations

不要为了统一而把状态类字段改成 ValueMatcher。一个 expect 字段只能对应一种断言模型。

注册

  1. 创建 src/server/checker/runner/<type>/index.ts
  2. src/server/checker/runner/index.ts 添加导入。
  3. 在 registry 初始化数组中添加 checker 实例。

注册后schema builder、validate、config-loader、engine、store 会自动按 registry 分发。

测试要求

测试文件放在 tests/server/checker/runner/<type>/,结构镜像源文件。

测试类别 覆盖内容
契约测试 TypeBox schema 与 JSON Schema 导出一致性
语义校验测试 合法和非法配置
normalize 测试 authoring expect 简写展开和 normalized contract 通过
resolve 测试 默认值合并、路径解析、单位转换
execute 测试 成功、失败、超时、expect 组合
注册测试 registry 注册行为
配置加载测试 含新 checker 的 YAML 完整加载流程

文档和 schema 更新

新增或修改 checker 时通常需要更新:

  • probes.example.yaml
  • probe-config.schema.json,通过 bun run schema 生成
  • docs/user/checkers/<type>.md
  • docs/user/checkers/README.md
  • docs/user/expectations.md,仅当断言模型、状态模型或通用规则变化
  • docs/user/configuration.md,仅当 target 通用字段或配置加载形态变化
  • docs/development/checker.md,仅当 checker 开发机制、测试要求或 checklist 变化
  • docs/README.mdopenspec/config.yaml,仅当文档同步规则变化

验证命令

新增或修改 checker 后通常需要运行:

bun run schema
bun run schema:check
bun run check

影响构建、Docker 或发布包时追加运行 bun run verify

完成检查清单

□ checker 类型、schema、validate、normalize、resolve、execute、serialize 已实现
□ checker 已在 runner/index.ts 注册
□ 配置契约、语义校验和 JSON Schema 导出已同步
□ probes.example.yaml 已添加或更新示例
□ tests/server/checker/runner/<type>/ 已覆盖契约、校验、normalize、resolve、execute、注册和配置加载
□ docs/user/checkers/<type>.md 已添加或更新
□ docs/user/checkers/README.md 已添加或更新
□ 文档影响分析已完成,必要文档已同步
□ bun run schema 和 bun run schema:check 已通过
□ bun run check 已通过
□ bun run verify 已通过或记录未执行原因

更新触发条件

修改 checker 开发机制、目录结构、schema/validate/normalize/resolve/execute/expect 约定、测试要求、验证命令或文档同步 checklist 时,必须更新本文档。