1
0
Files
DiAL/openspec/specs/icmp-checker/spec.md
lanyuanxiaoyao 550c427814 feat: 新增 ICMP/Ping checker,支持跨平台主机存活检测与延迟监控
实现 type: ping checker,通过 Bun.spawn 调用系统 ping 命令,自行实现跨平台
输出解析器(Linux/macOS/Windows 含中文 locale),支持 alive、丢包率、延迟、
耗时等 expect 断言,复用现有 checker 架构零外部依赖。

包含完整的类型定义、TypeBox schema、语义校验、命令构建、解析、断言、执行、
注册、配置加载测试,以及 probe-config.schema.json 更新和文档更新。

审查修复:提取 buildPingCommand 为独立纯函数并补充跨平台单测,补充
maxDurationMs/maxAvgLatencyMs 类型非法和空字符串 host 边界测试用例。

变更已归档,delta specs 已同步至 main specs。
2026-05-18 10:45:17 +08:00

11 KiB
Raw Blame History

Purpose

定义 ICMP/Ping checker 的配置格式、命令执行、跨平台输出解析、expect 校验、失败结构和状态摘要。

Requirements

Requirement: ping target 配置

系统 SHALL 支持 type: ping 的 target 配置,通过 ping.host 描述目标主机地址,并通过可选字段控制探测行为。

Scenario: 解析最简 ping target

  • WHEN YAML 中 target 配置 type: pingping.host: "10.0.0.1"
  • THEN 系统 SHALL 将其解析为 ping checker并填充 count=3packetSize=56、interval、timeout、group 和 expect 配置

Scenario: ping target 缺少 host

  • WHEN YAML 中 target 配置 type: ping 但缺少 ping.host
  • THEN 系统 SHALL 以配置错误退出,并提示该 target 缺少 ping.host 字段

Scenario: ping host 类型非法

  • WHEN YAML 中 ping target 的 ping.host 不是非空字符串
  • THEN 系统 SHALL 以配置错误退出,提示 ping.host 必须为非空字符串

Scenario: ping count 配置

  • WHEN YAML 中 ping target 配置 ping.count: 5
  • THEN 系统 SHALL 使用 5 作为 ICMP 包发送数量

Scenario: ping count 非法

  • WHEN YAML 中 ping target 的 ping.count 不是 1 到 100 之间的正整数
  • THEN 系统 SHALL 以配置错误退出,提示 ping.count 必须为 1-100 的正整数

Scenario: ping packetSize 配置

  • WHEN YAML 中 ping target 配置 ping.packetSize: 1472
  • THEN 系统 SHALL 使用 1472 作为 ICMP 包大小bytes

Scenario: ping packetSize 非法

  • WHEN YAML 中 ping target 的 ping.packetSize 不是 1 到 65500 之间的正整数
  • THEN 系统 SHALL 以配置错误退出,提示 ping.packetSize 必须为 1-65500 的正整数

Scenario: ping 分组未知字段失败

  • WHEN YAML 中 ping target 的 ping 分组包含 timeout: 5 等未知字段
  • THEN 系统 SHALL 以配置错误退出,提示 ping 分组包含未知字段

Scenario: ping 序列化展示摘要

  • WHEN 系统同步 ping target 到 targets 表
  • THEN target 展示摘要 SHALL 为 ping <host>config JSON SHALL 包含 resolved 后的 host、count 和 packetSize

Requirement: ping checker 执行

系统 SHALL 通过调用系统 ping 命令执行 ICMP 探测,记录完整执行耗时,并在命令不可用、超时或解析失败时产生结构化失败信息。

Scenario: ping 命令构建Linux

  • WHEN 系统平台为 linuxping target 配置 host="10.0.0.1"、count=3、packetSize=56且外层 timeoutMs=10000
  • THEN 系统 SHALL 执行 ping -c 3 -s 56 -W 10 10.0.0.1-W 单位为秒,向上取整)

Scenario: ping 命令构建macOS

  • WHEN 系统平台为 darwinping target 配置 host="10.0.0.1"、count=3、packetSize=56且外层 timeoutMs=10000
  • THEN 系统 SHALL 执行 ping -c 3 -s 56 -W 10000 10.0.0.1-W 单位为毫秒)

Scenario: ping 命令构建Windows

  • WHEN 系统平台为 win32ping target 配置 host="10.0.0.1"、count=3、packetSize=56且外层 timeoutMs=10000
  • THEN 系统 SHALL 执行 ping -n 3 -l 56 -w 10000 10.0.0.1-w 单位为毫秒)

Scenario: ping 命令不存在

  • WHEN 系统未安装 ping 命令spawn 抛出 ENOENT
  • THEN 系统 SHALL 记录 matched=falsefailure 的 kind 为 errorphase 为 pingpath 为 spawnmessage 包含 "ping 命令不可用" 和原始错误信息

Scenario: ping 执行超时

  • WHEN 引擎注入的 ctx.signal 在 ping 命令执行过程中 abort
  • THEN 系统 SHALL 调用 proc.kill() 终止子进程,记录 matched=falsefailure 的 kind 为 errorphase 为 pingmessage 包含超时信息

Scenario: ping 目标可达

  • WHEN ping target 指向可达主机,且 ping 命令正常返回
  • THEN 系统 SHALL 解析 stdout 获取统计数据,并按断言链执行 expect 校验

Scenario: ping 目标不可达

  • WHEN ping target 指向不可达主机,且 ping 命令返回 100% packet loss
  • THEN 系统 SHALL 解析 stdout 获取统计数据,alive 为 false延迟字段为 null

Scenario: duration 覆盖完整执行

  • WHEN ping 命令执行完成
  • THEN 结果中的 durationMs SHALL 覆盖从 spawn 到进程退出的完整耗时

Requirement: 跨平台 ping 输出解析

系统 SHALL 实现跨平台 ping 输出解析器,支持 Linux、macOS 和 Windows含多语言 locale从 stdout 中提取 transmitted、received、packetLoss、minLatencyMs、avgLatencyMs、maxLatencyMs。

Scenario: 解析 Linux ping 输出

  • WHEN 平台为 linuxstdout 包含 "3 packets transmitted, 3 received, 0% packet loss" 和 "rtt min/avg/max/mdev = 1.234/2.345/3.456/0.567 ms"
  • THEN 系统 SHALL 解析为 transmitted=3, received=3, packetLoss=0, minLatencyMs=1.234, avgLatencyMs=2.345, maxLatencyMs=3.456

Scenario: 解析 macOS ping 输出

  • WHEN 平台为 darwinstdout 包含 "3 packets transmitted, 3 packets received, 0.0% packet loss" 和 "round-trip min/avg/max/stddev = 1.234/2.345/3.456/0.567 ms"
  • THEN 系统 SHALL 解析为 transmitted=3, received=3, packetLoss=0, minLatencyMs=1.234, avgLatencyMs=2.345, maxLatencyMs=3.456

Scenario: 解析 Windows 英文 ping 输出

  • WHEN 平台为 win32stdout 包含 "Packets: Sent = 3, Received = 3, Lost = 0 (0% loss)" 和 "Minimum = 1ms, Maximum = 3ms, Average = 2ms"
  • THEN 系统 SHALL 解析为 transmitted=3, received=3, packetLoss=0, minLatencyMs=1, avgLatencyMs=2, maxLatencyMs=3

Scenario: 解析 Windows 中文 ping 输出

  • WHEN 平台为 win32stdout 包含 "数据包: 已发送 = 3已接收 = 3丢失 = 0 (0% 丢失)" 和 "最短 = 1ms最长 = 3ms平均 = 2ms"
  • THEN 系统 SHALL 解析为 transmitted=3, received=3, packetLoss=0, minLatencyMs=1, avgLatencyMs=2, maxLatencyMs=3

Scenario: 解析全部丢包(无延迟行)

  • WHEN stdout 包含丢包统计行但无延迟统计行100% packet loss
  • THEN 系统 SHALL 解析为 alive=false延迟字段min/avg/max均为 null

Scenario: 输出无法解析

  • WHEN stdout 不匹配任何已知的统计行格式
  • THEN 系统 SHALL 记录 matched=falsefailure 的 kind 为 errorphase 为 pingpath 为 parsemessage 包含 "无法解析 ping 输出"

Requirement: ping expect 校验

系统 SHALL 支持 ping 专属 expect包括 alivemaxPacketLossmaxAvgLatencyMsmaxMaxLatencyMsmaxDurationMs,并按 alive、packetLoss、avgLatency、maxLatency、duration 的阶段顺序快速失败。

Scenario: 默认 alive 成功语义

  • WHEN ping target 未显式配置 expect.alive
  • THEN 系统 SHALL 使用默认 expect.alive: true 进行校验

Scenario: alive 校验通过

  • WHEN ping target 配置 expect.alive: true,且目标主机可达
  • THEN 系统 SHALL 判定 alive 阶段通过

Scenario: alive 校验失败

  • WHEN ping target 配置 expect.alive: true,且目标主机不可达
  • THEN 系统 SHALL 返回 matched=falsefailure 的 kind 为 mismatchphase 为 alive

Scenario: 反向 alive 断言

  • WHEN ping target 配置 expect.alive: false,且目标主机不可达
  • THEN 系统 SHALL 判定 alive 阶段通过(matched=true

Scenario: 反向 alive 断言失败

  • WHEN ping target 配置 expect.alive: false,但目标主机可达
  • THEN 系统 SHALL 返回 matched=falsefailure 的 kind 为 mismatchphase 为 alive

Scenario: maxPacketLoss 校验通过

  • WHEN ping target 配置 expect.maxPacketLoss: 10,且实际丢包率为 0%
  • THEN 系统 SHALL 判定 packetLoss 阶段通过

Scenario: maxPacketLoss 校验失败

  • WHEN ping target 配置 expect.maxPacketLoss: 10,且实际丢包率为 33%
  • THEN 系统 SHALL 返回 matched=falsefailure 的 kind 为 mismatchphase 为 packetLoss

Scenario: maxAvgLatencyMs 校验通过

  • WHEN ping target 配置 expect.maxAvgLatencyMs: 200,且实际平均延迟为 12ms
  • THEN 系统 SHALL 判定 avgLatency 阶段通过

Scenario: maxAvgLatencyMs 校验失败

  • WHEN ping target 配置 expect.maxAvgLatencyMs: 100,且实际平均延迟为 156ms
  • THEN 系统 SHALL 返回 matched=falsefailure 的 kind 为 mismatchphase 为 avgLatency

Scenario: maxMaxLatencyMs 校验通过

  • WHEN ping target 配置 expect.maxMaxLatencyMs: 500,且实际最大延迟为 340ms
  • THEN 系统 SHALL 判定 maxLatency 阶段通过

Scenario: maxMaxLatencyMs 校验失败

  • WHEN ping target 配置 expect.maxMaxLatencyMs: 200,且实际最大延迟为 340ms
  • THEN 系统 SHALL 返回 matched=falsefailure 的 kind 为 mismatchphase 为 maxLatency

Scenario: maxDurationMs 校验

  • WHEN ping target 配置 expect.maxDurationMs: 5000,且完整执行耗时超过 5000ms
  • THEN 系统 SHALL 返回 matched=falsefailure 的 phase 为 duration

Scenario: alive=false 时跳过延迟断言

  • WHEN ping target 配置 expect.alive: trueexpect.maxAvgLatencyMs: 100,且目标不可达
  • THEN 系统 SHALL 在 alive 阶段即返回失败,不执行后续延迟断言

Scenario: ping expect 未知字段失败

  • WHEN YAML 中 ping target 的 expect 包含 status: [200] 或其他非 ping expect 字段
  • THEN 系统 SHALL 以配置错误退出,提示 expect 包含未知字段

Scenario: maxPacketLoss 类型非法

  • WHEN YAML 中 ping target 的 expect.maxPacketLoss 不是 0 到 100 之间的数字
  • THEN 系统 SHALL 以配置错误退出,提示 expect.maxPacketLoss 必须为 0-100 的数字

Scenario: maxAvgLatencyMs 类型非法

  • WHEN YAML 中 ping target 的 expect.maxAvgLatencyMs 不是非负有限数字
  • THEN 系统 SHALL 以配置错误退出,提示 expect.maxAvgLatencyMs 格式错误

Scenario: maxMaxLatencyMs 类型非法

  • WHEN YAML 中 ping target 的 expect.maxMaxLatencyMs 不是非负有限数字
  • THEN 系统 SHALL 以配置错误退出,提示 expect.maxMaxLatencyMs 格式错误

Requirement: ping statusDetail 摘要

系统 SHALL 在 ping 执行成功后生成结构化 statusDetail 摘要,展示关键指标。

Scenario: 目标可达无丢包

  • WHEN ping 结果为 alive=true, avg=12ms, packetLoss=0%, transmitted=3, received=3
  • THEN statusDetail SHALL 为 alive, avg 12ms, loss 0% (3/3)

Scenario: 目标可达有丢包

  • WHEN ping 结果为 alive=true, avg=156ms, max=340ms, packetLoss=33%, transmitted=3, received=2
  • THEN statusDetail SHALL 包含 avg、max 和 loss 信息

Scenario: 目标不可达

  • WHEN ping 结果为 alive=false, transmitted=3, received=0
  • THEN statusDetail SHALL 为 unreachable (0/3 received)