feat: 重构配置布局,server.listen/storage/logging + probes.execution 分组
- 新增 server.listen (host/port)、server.storage (dataDir/retention)、 server.logging 分组 - 新增 probes.execution (maxConcurrentChecks) 分组,替代顶层 runtime - 旧配置入口 (runtime/logging/server.host/server.port/server.dataDir) 启动期拒绝 - 更新 types.ts、builder.ts、config-loader.ts 适配新路径 - 更新 probe-config.schema.json、probes.example.yaml、README.md、 DEVELOPMENT.md - 补充 config-loader 和 variables 测试覆盖新路径和旧入口拒绝 - 同步 5 个 delta specs 到主规范 (probe-config, config-variables, data-retention, probe-engine, runtime-logging) - 归档 openspec change reorganize-config-layout
This commit is contained in:
@@ -4,18 +4,37 @@
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: 旧配置入口拒绝
|
||||
系统 SHALL 拒绝旧版顶层 `runtime` 和顶层 `logging` 配置入口。系统 SHALL 拒绝旧版 `server.host`、`server.port` 和 `server.dataDir` 入口,并要求使用 `server.listen` 与 `server.storage` 下的新路径。
|
||||
|
||||
#### Scenario: 顶层 runtime 被拒绝
|
||||
- **WHEN** 配置文件声明顶层 `runtime`
|
||||
- **THEN** 系统 SHALL 以配置错误退出并提示存在未知字段 `runtime`
|
||||
|
||||
#### Scenario: 顶层 logging 被拒绝
|
||||
- **WHEN** 配置文件声明顶层 `logging`
|
||||
- **THEN** 系统 SHALL 以配置错误退出并提示存在未知字段 `logging`
|
||||
|
||||
#### Scenario: server 旧监听字段被拒绝
|
||||
- **WHEN** 配置文件声明 `server.host` 或 `server.port`
|
||||
- **THEN** 系统 SHALL 以配置错误退出并提示 `server` 中存在未知字段
|
||||
|
||||
#### Scenario: server 旧 dataDir 字段被拒绝
|
||||
- **WHEN** 配置文件声明 `server.dataDir`
|
||||
- **THEN** 系统 SHALL 以配置错误退出并提示 `server` 中存在未知字段 `dataDir`
|
||||
|
||||
### Requirement: YAML 配置文件格式
|
||||
系统 SHALL 支持通过 YAML 配置文件定义全部运行参数,包括 server 配置、runtime 配置、可选的 variables 段、checker 默认值和 typed target 列表(含可选 group 字段)。target MUST 使用 `id` 字段作为唯一标识符,MUST 使用 `type` 字段声明 checker 类型,SHALL 支持可选的 `name` 字段作为展示名称元信息,SHALL 支持可选的 `description` 字段作为目标说明。`name` 和 `description` 均 SHALL 允许省略或显式配置为 `null`;省略或显式 null 时解析结果 SHALL 保留为 null。HTTP 领域字段 MUST 放在 `http` 分组,cmd 领域字段 MUST 放在 `cmd` 分组,db 领域字段 MUST 放在 `db` 分组,tcp 领域字段 MUST 放在 `tcp` 分组,icmp 领域字段 MUST 放在 `icmp` 分组,udp 领域字段 MUST 放在 `udp` 分组,LLM 领域字段 MUST 放在 `llm` 分组。HTTP target 的 `http` 分组 SHALL 支持可选的 `ignoreSSL`(布尔值)和 `maxRedirects`(非负整数)字段。Db target 的 `db` 分组 SHALL 支持 `url`(必填)和 `query`(可选)字段。Tcp target 的 `tcp` 分组 SHALL 支持 `host`(必填)、`port`(必填)、`readBanner`(可选)、`bannerReadTimeout`(可选)和 `maxBannerBytes`(可选)字段。Icmp target 的 `icmp` 分组 SHALL 支持 `host`(必填)、`count`(可选,默认 3)和 `packetSize`(可选,默认 56)字段。Udp target 的 `udp` 分组 SHALL 支持 `host`(必填)、`port`(必填)、`payload`(可选,默认空字符串)、`encoding`(可选,默认 `text`)、`responseEncoding`(可选,默认 `text`)和 `maxResponseBytes`(可选,默认 4096)字段。LLM target 的 `llm` 分组 SHALL 支持 `provider`(必填)、`url`(必填)、`model`(必填)、`prompt`(必填)、`mode`(可选,默认 `http`)、`key`(可选,默认空字符串)、`authToken`(可选)、`headers`(可选)、`ignoreSSL`(可选,默认 `false`)、`options`(可选)和 `providerOptions`(可选)字段。
|
||||
系统 SHALL 支持通过 YAML 配置文件定义全部运行参数,包括 server 配置、probes 执行配置、可选的 variables 段、checker 默认值和 typed target 列表(含可选 group 字段)。server 配置 SHALL 将 HTTP 监听参数放在 `server.listen` 分组,将本地数据目录和历史数据保留时长放在 `server.storage` 分组,将运行时日志配置放在 `server.logging` 分组。拨测全局执行策略 SHALL 放在 `probes.execution` 分组。target MUST 使用 `id` 字段作为唯一标识符,MUST 使用 `type` 字段声明 checker 类型,SHALL 支持可选的 `name` 字段作为展示名称元信息,SHALL 支持可选的 `description` 字段作为目标说明。`name` 和 `description` 均 SHALL 允许省略或显式配置为 `null`;省略或显式 null 时解析结果 SHALL 保留为 null。HTTP 领域字段 MUST 放在 `http` 分组,cmd 领域字段 MUST 放在 `cmd` 分组,db 领域字段 MUST 放在 `db` 分组,tcp 领域字段 MUST 放在 `tcp` 分组,icmp 领域字段 MUST 放在 `icmp` 分组,udp 领域字段 MUST 放在 `udp` 分组,LLM 领域字段 MUST 放在 `llm` 分组。HTTP target 的 `http` 分组 SHALL 支持可选的 `ignoreSSL`(布尔值)和 `maxRedirects`(非负整数)字段。Db target 的 `db` 分组 SHALL 支持 `url`(必填)和 `query`(可选)字段。Tcp target 的 `tcp` 分组 SHALL 支持 `host`(必填)、`port`(必填)、`readBanner`(可选)、`bannerReadTimeout`(可选)和 `maxBannerBytes`(可选)字段。Icmp target 的 `icmp` 分组 SHALL 支持 `host`(必填)、`count`(可选,默认 3)和 `packetSize`(可选,默认 56)字段。Udp target 的 `udp` 分组 SHALL 支持 `host`(必填)、`port`(必填)、`payload`(可选,默认空字符串)、`encoding`(可选,默认 `text`)、`responseEncoding`(可选,默认 `text`)和 `maxResponseBytes`(可选,默认 4096)字段。LLM target 的 `llm` 分组 SHALL 支持 `provider`(必填)、`url`(必填)、`model`(必填)、`prompt`(必填)、`mode`(可选,默认 `http`)、`key`(可选,默认空字符串)、`authToken`(可选)、`headers`(可选)、`ignoreSSL`(可选,默认 `false`)、`options`(可选)和 `providerOptions`(可选)字段。
|
||||
|
||||
`defaults.http` 分组 SHALL 仅支持 `headers`(可选)和 `maxBodyBytes`(可选)字段。`defaults.http` 分组 MUST NOT 支持 `method` 字段。`defaults.tcp` 分组 SHALL 仅支持 `bannerReadTimeout`(可选)和 `maxBannerBytes`(可选)字段。`defaults.icmp` 分组 SHALL 仅支持空对象。`defaults.udp` 分组 SHALL 仅支持 `encoding`(可选)、`responseEncoding`(可选)和 `maxResponseBytes`(可选)字段。`defaults.llm` 分组 SHALL 仅支持 `mode`(可选)、`headers`(可选)、`ignoreSSL`(可选)、`options`(可选)和 `providerOptions`(可选)字段。
|
||||
|
||||
#### Scenario: 完整配置文件解析
|
||||
- **WHEN** 系统启动并读取包含 server、runtime、variables、defaults、targets(含 id、group 字段)的 YAML 配置文件
|
||||
- **WHEN** 系统启动并读取包含 server.listen、server.storage、server.logging、probes.execution、variables、defaults、targets(含 id、group 字段)的 YAML 配置文件
|
||||
- **THEN** 系统 SHALL 正确解析所有字段并用于初始化服务、调度引擎和对应 checker runner
|
||||
|
||||
#### Scenario: 最简 HTTP 配置文件解析
|
||||
- **WHEN** 系统读取只包含一个 `type: http` target(含 `id` 和 `http.url`)的 YAML 配置文件(省略 server、runtime、variables、defaults 和 expect)
|
||||
- **THEN** 系统 SHALL 使用内置默认值填充未指定的字段(host=127.0.0.1, port=3000, dir=./data, interval=30s, timeout=10s, runtime.maxConcurrentChecks=20, http.method=GET, http.maxBodyBytes=100MB, http.ignoreSSL=false, http.maxRedirects=0, group="default"),并保留 name=null、description=null
|
||||
- **WHEN** 系统读取只包含一个 `type: http` target(含 `id` 和 `http.url`)的 YAML 配置文件(省略 server、probes、variables、defaults 和 expect)
|
||||
- **THEN** 系统 SHALL 使用内置默认值填充未指定的字段(host=127.0.0.1, port=3000, dataDir=./data, interval=30s, timeout=10s, probes.execution.maxConcurrentChecks=20, server.storage.retention=7d, http.method=GET, http.maxBodyBytes=100MB, http.ignoreSSL=false, http.maxRedirects=0, group="default"),并保留 name=null、description=null
|
||||
|
||||
#### Scenario: 最简 cmd 配置文件解析
|
||||
- **WHEN** 系统读取只包含一个 `type: cmd` target(含 `id` 和 `cmd.exec`)的 YAML 配置文件
|
||||
@@ -136,8 +155,8 @@
|
||||
- **THEN** 系统 SHALL 以错误退出并提示格式错误
|
||||
|
||||
#### Scenario: maxConcurrentChecks 非法
|
||||
- **WHEN** runtime.maxConcurrentChecks 不是正整数
|
||||
- **THEN** 系统 SHALL 以错误退出并提示 runtime.maxConcurrentChecks 格式错误
|
||||
- **WHEN** probes.execution.maxConcurrentChecks 不是正整数
|
||||
- **THEN** 系统 SHALL 以错误退出并提示 probes.execution.maxConcurrentChecks 格式错误
|
||||
|
||||
#### Scenario: interval 或 timeout 解析结果非法
|
||||
- **WHEN** interval 或 timeout 解析结果不是正整数毫秒(如 `0ms` 或 `1.5ms`)
|
||||
@@ -325,14 +344,14 @@
|
||||
- **THEN** 系统 SHALL 将其解析为 524288 bytes
|
||||
|
||||
### Requirement: runtime 并发配置
|
||||
系统 SHALL 支持 `runtime.maxConcurrentChecks` 配置全局最大并发检查数。
|
||||
系统 SHALL 支持 `probes.execution.maxConcurrentChecks` 配置全局最大并发检查数。`probes` 和 `probes.execution` 配置段均 SHALL 为可选,省略时使用默认值。
|
||||
|
||||
#### Scenario: 使用默认并发限制
|
||||
- **WHEN** YAML 中未配置 runtime.maxConcurrentChecks
|
||||
- **WHEN** YAML 中未配置 `probes` 或未配置 `probes.execution.maxConcurrentChecks`
|
||||
- **THEN** 系统 SHALL 使用默认值 20
|
||||
|
||||
#### Scenario: 配置并发限制
|
||||
- **WHEN** YAML 中配置 `runtime.maxConcurrentChecks: 5`
|
||||
- **WHEN** YAML 中配置 `probes.execution.maxConcurrentChecks: 5`
|
||||
- **THEN** 系统 SHALL 将全局最大并发检查数设置为 5
|
||||
|
||||
### Requirement: YAML 配置使用 Bun 内置解析
|
||||
@@ -428,33 +447,33 @@
|
||||
- **THEN** `targets.expect` SHALL 存储变量替换后的 Raw expect JSON,而不是包含 `kind` 或 resolved matcher 的运行期执行计划
|
||||
|
||||
### Requirement: 数据保留配置字段
|
||||
配置 schema 的 `runtime` 段 SHALL 支持 `retention` 字段,类型为字符串,格式为 `<数字><单位>`(单位:`d` 天、`h` 小时、`m` 分钟),用于指定历史数据保留时长。
|
||||
配置 schema 的 `server.storage` 段 SHALL 支持 `retention` 字段,类型为字符串,格式为 `<数字><单位>`(单位:`d` 天、`h` 小时、`m` 分钟),用于指定历史数据保留时长。
|
||||
|
||||
#### Scenario: retention 字段校验通过
|
||||
- **WHEN** 配置文件中 `runtime.retention` 为合法格式(如 `"7d"`、`"24h"`、`"30m"`)
|
||||
- **WHEN** 配置文件中 `server.storage.retention` 为合法格式(如 `"7d"`、`"24h"`、`"30m"`)
|
||||
- **THEN** 配置校验 SHALL 通过
|
||||
|
||||
#### Scenario: retention 字段格式非法
|
||||
- **WHEN** 配置文件中 `runtime.retention` 为非法格式(如 `"abc"`、`"7x"`、`""`)
|
||||
- **WHEN** 配置文件中 `server.storage.retention` 为非法格式(如 `"abc"`、`"7x"`、`""`)
|
||||
- **THEN** 配置校验 SHALL 失败并报告格式错误
|
||||
|
||||
#### Scenario: retention 字段缺省
|
||||
- **WHEN** 配置文件中未指定 `runtime.retention`
|
||||
- **WHEN** 配置文件中未指定 `server.storage.retention`
|
||||
- **THEN** 系统 SHALL 使用默认值 `"7d"`
|
||||
|
||||
### Requirement: 数据目录路径解析
|
||||
配置加载流程 SHALL 将 `server.dataDir` 相对路径基于配置文件所在目录(configDir)解析为绝对路径。绝对路径 SHALL 保持不变。
|
||||
配置加载流程 SHALL 将 `server.storage.dataDir` 相对路径基于配置文件所在目录(configDir)解析为绝对路径。绝对路径 SHALL 保持不变。
|
||||
|
||||
#### Scenario: dataDir 为相对路径
|
||||
- **WHEN** 配置文件位于 `/opt/dial/probes.yaml`,且 `server.dataDir` 配置为 `./data`
|
||||
- **WHEN** 配置文件位于 `/opt/dial/probes.yaml`,且 `server.storage.dataDir` 配置为 `./data`
|
||||
- **THEN** 系统 SHALL 将 dataDir 解析为 `/opt/dial/data`,而非依赖进程 cwd
|
||||
|
||||
#### Scenario: dataDir 为绝对路径
|
||||
- **WHEN** `server.dataDir` 配置为 `/var/lib/dial/data`
|
||||
- **WHEN** `server.storage.dataDir` 配置为 `/var/lib/dial/data`
|
||||
- **THEN** 系统 SHALL 直接使用该绝对路径,不做额外解析
|
||||
|
||||
#### Scenario: dataDir 使用默认值
|
||||
- **WHEN** 未配置 `server.dataDir`(使用默认值 `./data`)
|
||||
- **WHEN** 未配置 `server.storage.dataDir`(使用默认值 `./data`)
|
||||
- **THEN** 系统 SHALL 将默认值 `./data` 基于 configDir 解析为绝对路径
|
||||
|
||||
### Requirement: target 通用元信息字段约束
|
||||
@@ -634,51 +653,51 @@
|
||||
- **THEN** 系统 SHALL 以配置错误退出,提示 expect.stream.firstTokenMs 格式错误
|
||||
|
||||
### Requirement: 日志配置格式
|
||||
系统 SHALL 支持可选的顶层 `logging` 配置,用于定义运行时日志等级、命令行日志等级、文件日志等级、文件路径和滚动策略。`logging` 未配置时 SHALL 使用内置默认值。系统 SHALL NOT 支持 `logging.console.enabled`、`logging.console.format`、`logging.file.enabled`、`logging.file.format` 或 `logging.file.rotation.enabled` 字段。
|
||||
系统 SHALL 支持可选的 `server.logging` 配置,用于定义运行时日志等级、命令行日志等级、文件日志等级、文件路径和滚动策略。`server.logging` 未配置时 SHALL 使用内置默认值。系统 SHALL NOT 支持 `server.logging.console.enabled`、`server.logging.console.format`、`server.logging.file.enabled`、`server.logging.file.format` 或 `server.logging.file.rotation.enabled` 字段。
|
||||
|
||||
#### Scenario: 未配置 logging 使用默认值
|
||||
- **WHEN** 配置文件未声明 `logging`
|
||||
- **THEN** 系统 SHALL 使用 `logging.level=info`、`logging.console.level=info`、`logging.file.level=info`、`logging.file.path=<resolved dataDir>/logs/dial.log`、`logging.file.rotation.size=50MB`、`logging.file.rotation.frequency=daily` 和 `logging.file.rotation.maxFiles=14`
|
||||
- **WHEN** 配置文件未声明 `server.logging`
|
||||
- **THEN** 系统 SHALL 使用 `server.logging.level=info`、`server.logging.console.level=info`、`server.logging.file.level=info`、`server.logging.file.path=<resolved dataDir>/logs/dial.log`、`server.logging.file.rotation.size=50MB`、`server.logging.file.rotation.frequency=daily` 和 `server.logging.file.rotation.maxFiles=14`
|
||||
|
||||
#### Scenario: console 和 file level 继承全局 level
|
||||
- **WHEN** 配置声明 `logging.level: warn` 且未声明 `logging.console.level` 和 `logging.file.level`
|
||||
- **WHEN** 配置声明 `server.logging.level: warn` 且未声明 `server.logging.console.level` 和 `server.logging.file.level`
|
||||
- **THEN** 系统 SHALL 将 console 和 file 的日志等级均解析为 `warn`
|
||||
|
||||
#### Scenario: 显式配置文件日志路径
|
||||
- **WHEN** 配置声明 `logging.file.path`
|
||||
- **WHEN** 配置声明 `server.logging.file.path`
|
||||
- **THEN** 系统 SHALL 使用该路径作为文件日志路径,而不是默认 `<resolved dataDir>/logs/dial.log`
|
||||
|
||||
#### Scenario: 相对日志路径
|
||||
- **WHEN** `logging.file.path` 是相对路径
|
||||
- **WHEN** `server.logging.file.path` 是相对路径
|
||||
- **THEN** 系统 SHALL 基于配置文件所在目录解析为绝对路径
|
||||
|
||||
#### Scenario: 绝对日志路径
|
||||
- **WHEN** `logging.file.path` 是绝对路径
|
||||
- **WHEN** `server.logging.file.path` 是绝对路径
|
||||
- **THEN** 系统 SHALL 原样使用该绝对路径,并允许该路径位于 `dataDir` 之外
|
||||
|
||||
#### Scenario: 不支持日志开关和格式字段
|
||||
- **WHEN** 配置声明 `logging.console.enabled`、`logging.console.format`、`logging.file.enabled`、`logging.file.format` 或 `logging.file.rotation.enabled`
|
||||
- **WHEN** 配置声明 `server.logging.console.enabled`、`server.logging.console.format`、`server.logging.file.enabled`、`server.logging.file.format` 或 `server.logging.file.rotation.enabled`
|
||||
- **THEN** 系统 SHALL 以配置错误退出并提示存在未知字段
|
||||
|
||||
### Requirement: 日志配置校验
|
||||
系统 SHALL 在启动期校验 `logging` 配置。日志等级 SHALL 只能是 `trace`、`debug`、`info`、`warn`、`error` 或 `fatal`。`rotation.size` SHALL 使用有效 size 格式且解析为正整数字节数。`rotation.frequency` SHALL 只能是 `hourly`、`daily` 或 `weekly`。`rotation.maxFiles` SHALL 是正整数。
|
||||
系统 SHALL 在启动期校验 `server.logging` 配置。日志等级 SHALL 只能是 `trace`、`debug`、`info`、`warn`、`error` 或 `fatal`。`rotation.size` SHALL 使用有效 size 格式且解析为正整数字节数。`rotation.frequency` SHALL 只能是 `hourly`、`daily` 或 `weekly`。`rotation.maxFiles` SHALL 是正整数。
|
||||
|
||||
#### Scenario: 非法日志等级
|
||||
- **WHEN** 配置声明 `logging.level: verbose`
|
||||
- **WHEN** 配置声明 `server.logging.level: verbose`
|
||||
- **THEN** 系统 SHALL 以配置错误退出并提示日志等级非法
|
||||
|
||||
#### Scenario: 非法滚动大小
|
||||
- **WHEN** 配置声明 `logging.file.rotation.size: "large"`
|
||||
- **WHEN** 配置声明 `server.logging.file.rotation.size: "large"`
|
||||
- **THEN** 系统 SHALL 以配置错误退出并提示 size 格式非法
|
||||
|
||||
#### Scenario: 非法滚动频率
|
||||
- **WHEN** 配置声明 `logging.file.rotation.frequency: monthly`
|
||||
- **WHEN** 配置声明 `server.logging.file.rotation.frequency: monthly`
|
||||
- **THEN** 系统 SHALL 以配置错误退出并提示 frequency 非法
|
||||
|
||||
#### Scenario: 非法归档数量
|
||||
- **WHEN** 配置声明 `logging.file.rotation.maxFiles: 0`
|
||||
- **WHEN** 配置声明 `server.logging.file.rotation.maxFiles: 0`
|
||||
- **THEN** 系统 SHALL 以配置错误退出并提示 maxFiles 必须为正整数
|
||||
|
||||
#### Scenario: 非法日志路径
|
||||
- **WHEN** 配置声明 `logging.file.path` 为空字符串或空白字符串
|
||||
- **WHEN** 配置声明 `server.logging.file.path` 为空字符串或空白字符串
|
||||
- **THEN** 系统 SHALL 以配置错误退出并提示日志路径非法
|
||||
|
||||
Reference in New Issue
Block a user