refactor: 规范审查与重组,合并细粒度规范,清理过时内容
- 合并 20+ 细粒度 spec 为粗粒度主题规范:dashboard、data-store、probe-engine、probe-api、probe-config 等 - 删除完全冗余规范:data-retention(被 probe-engine+data-store 覆盖)、backend-code-quality(DEVELOPMENT.md 已记录) - 补充 http-checker 规范至完整标准(配置+执行+expect+校验+observation),匹配代码 440 行实现 - 清理 tcp/udp/llm checker 规范中已废弃 defaults 配置段的残留 Scenario - 清理 checker-cohesion-structure 中的实现路径引用(src/server/...) - 统一所有 spec 格式(## Purpose 开头,去除 # Capability/Title 形式) - 更新 prompt-spec-review.md 审查提示文档
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
## Purpose
|
||||
|
||||
定义拨测系统的 REST API 端点:Dashboard 聚合 API、单目标指标 API、带时间范围和分页的历史记录、共享类型定义和 API 错误处理。
|
||||
定义拨测系统的 REST API 端点:Dashboard 聚合 API、单目标指标 API、历史记录 API、Meta 信息 API、共享类型定义和 API 错误处理。
|
||||
|
||||
## Requirements
|
||||
|
||||
@@ -75,11 +75,11 @@ Dashboard API SHALL 返回基于时间窗口计算的目标统计和连续状态
|
||||
- **THEN** 每个 recentSamples 元素 SHALL 包含 timestamp、durationMs、up 字段,其中 up 为 boolean 且等于 matched
|
||||
|
||||
### Requirement: 单目标指标 API
|
||||
系统 SHALL 提供 `GET /api/targets/:id/metrics` 端点,返回 Drawer 概览所需的单目标统计和趋势数据。仅活跃目标的指标 SHALL 可查询。端点的详细计算规则(P95/P99、MTTR、故障分析、趋势分桶等)定义在 `target-metrics-api` 能力中。
|
||||
系统 SHALL 提供 `GET /api/targets/:id/metrics` 端点,返回单个目标在指定时间窗口内的概览统计和趋势数据。仅活跃目标的指标 SHALL 可查询。
|
||||
|
||||
#### Scenario: 指定时间范围查询指标
|
||||
#### Scenario: 获取目标指标
|
||||
- **WHEN** 客户端请求 `GET /api/targets/1/metrics?from=ISO&to=ISO&bucket=1h` 且该目标为活跃目标
|
||||
- **THEN** 系统 SHALL 返回 targetId、window、stats、trend 字段
|
||||
- **THEN** 系统 SHALL 返回 JSON 对象包含 targetId、window、stats、trend 字段
|
||||
|
||||
#### Scenario: from 或 to 参数缺失
|
||||
- **WHEN** 客户端请求 `GET /api/targets/1/metrics` 未提供 from 或 to 参数
|
||||
@@ -101,6 +101,134 @@ Dashboard API SHALL 返回基于时间窗口计算的目标统计和连续状态
|
||||
- **WHEN** 客户端请求 `GET /api/targets/1/metrics?from=ISO&to=ISO&bucket=5m`
|
||||
- **THEN** 系统 SHALL 返回 400 状态码和错误信息
|
||||
|
||||
### Requirement: 指标统计字段
|
||||
单目标指标 API SHALL 返回基于时间窗口计算的完整统计字段。
|
||||
|
||||
#### Scenario: stats 字段
|
||||
- **WHEN** metrics 响应包含 stats
|
||||
- **THEN** stats SHALL 包含 totalChecks、upChecks、downChecks、availability、avgDurationMs、p95DurationMs、p99DurationMs、mttr、longestOutage、incidentCount、currentStreak 字段
|
||||
|
||||
#### Scenario: trend 字段
|
||||
- **WHEN** metrics 响应包含 trend
|
||||
- **THEN** trend SHALL 为数组,每个元素包含 bucketStart、avgDurationMs、minDurationMs、maxDurationMs、availability、totalChecks、upChecks、downChecks 字段
|
||||
|
||||
### Requirement: P95/P99 延迟计算
|
||||
系统 SHALL 在后端应用层计算 P95 和 P99 延迟百分位数。
|
||||
|
||||
#### Scenario: 正常计算 P95
|
||||
- **WHEN** 时间窗口内存在成功检查记录(matched=1 且 duration_ms 不为 null)
|
||||
- **THEN** 系统 SHALL 取出所有成功检查的 duration_ms,在后端应用层排序后取第 95 百分位值返回为 p95DurationMs
|
||||
|
||||
#### Scenario: 正常计算 P99
|
||||
- **WHEN** 时间窗口内存在成功检查记录
|
||||
- **THEN** 系统 SHALL 取第 99 百分位值返回为 p99DurationMs
|
||||
|
||||
#### Scenario: 无成功检查记录
|
||||
- **WHEN** 时间窗口内无 matched=1 且 duration_ms 不为 null 的记录
|
||||
- **THEN** p95DurationMs 和 p99DurationMs SHALL 返回 null
|
||||
|
||||
#### Scenario: 百分位计算方法
|
||||
- **WHEN** 计算第 N 百分位
|
||||
- **THEN** 系统 SHALL 将 duration_ms 升序排列,取 index = ceil(count * N / 100) - 1 位置的值
|
||||
|
||||
### Requirement: MTTR 计算
|
||||
系统 SHALL 在后端应用层计算平均恢复时间(Mean Time To Recovery)。
|
||||
|
||||
#### Scenario: 存在已恢复的故障段
|
||||
- **WHEN** 时间窗口内存在至少一个已恢复的故障段(连续 matched=0 后跟 matched=1)
|
||||
- **THEN** 系统 SHALL 计算所有已恢复故障段的平均持续时间(从首个 matched=0 的 timestamp 到恢复后首个 matched=1 的 timestamp 之差),返回为 mttr(毫秒)
|
||||
|
||||
#### Scenario: 无已恢复的故障段
|
||||
- **WHEN** 时间窗口内无已恢复的故障段(全部正常,或当前仍在故障中且无历史恢复)
|
||||
- **THEN** mttr SHALL 返回 null
|
||||
|
||||
#### Scenario: 当前正在故障中
|
||||
- **WHEN** 时间窗口内最后一段故障尚未恢复
|
||||
- **THEN** 该未恢复的故障段 SHALL 不计入 MTTR 平均值
|
||||
|
||||
#### Scenario: 窗口起始即为故障且后续恢复
|
||||
- **WHEN** 时间窗口内第一条记录即为 matched=0(故障跨越了 from 边界),且该故障段在窗口内恢复
|
||||
- **THEN** 该故障段 SHALL 不计入 MTTR 平均值(因无法确定真实故障开始时间),但 SHALL 计入 incidentCount
|
||||
|
||||
### Requirement: 最长故障时长
|
||||
系统 SHALL 在后端应用层计算时间窗口内最长的单次故障持续时间。
|
||||
|
||||
#### Scenario: 存在故障段
|
||||
- **WHEN** 时间窗口内存在故障段
|
||||
- **THEN** 系统 SHALL 返回最长故障段的持续时间为 longestOutage(毫秒)
|
||||
|
||||
#### Scenario: 无故障
|
||||
- **WHEN** 时间窗口内无 matched=0 的记录
|
||||
- **THEN** longestOutage SHALL 返回 null
|
||||
|
||||
#### Scenario: 窗口起始即为故障
|
||||
- **WHEN** 时间窗口内第一条记录即为 matched=0
|
||||
- **THEN** 该故障段的持续时间 SHALL 从 from 参数开始计算
|
||||
|
||||
#### Scenario: 当前正在故障中
|
||||
- **WHEN** 最后一段故障尚未恢复
|
||||
- **THEN** 该故障段的持续时间 SHALL 计算为从故障开始到时间窗口 to 参数的时间差
|
||||
|
||||
### Requirement: 故障事件计数
|
||||
系统 SHALL 在后端应用层计算时间窗口内的故障事件次数。
|
||||
|
||||
#### Scenario: 计算故障事件数
|
||||
- **WHEN** 时间窗口内存在状态翻转(matched 从 1 变为 0)
|
||||
- **THEN** 系统 SHALL 返回翻转次数为 incidentCount
|
||||
|
||||
#### Scenario: 无故障事件
|
||||
- **WHEN** 时间窗口内所有检查均为 matched=1
|
||||
- **THEN** incidentCount SHALL 返回 0
|
||||
|
||||
#### Scenario: 窗口起始即为故障
|
||||
- **WHEN** 时间窗口内第一条记录即为 matched=0 且无前序记录可判断翻转
|
||||
- **THEN** 该故障 SHALL 计为 1 次事件
|
||||
|
||||
#### Scenario: 连续异常只计一次
|
||||
- **WHEN** 某目标连续 10 次 matched=0
|
||||
- **THEN** 该连续异常段 SHALL 仅计为 1 次事件
|
||||
|
||||
### Requirement: 当前连续状态
|
||||
系统 SHALL 返回目标当前的连续状态信息。
|
||||
|
||||
#### Scenario: 当前连续正常
|
||||
- **WHEN** 目标最近的检查记录连续为 matched=1
|
||||
- **THEN** currentStreak SHALL 返回 `{ up: true, count: N }`,N 为连续正常的检查次数
|
||||
|
||||
#### Scenario: 当前连续异常
|
||||
- **WHEN** 目标最近的检查记录连续为 matched=0
|
||||
- **THEN** currentStreak SHALL 返回 `{ up: false, count: N }`,N 为连续异常的检查次数
|
||||
|
||||
#### Scenario: 连续状态达到取数上限
|
||||
- **WHEN** 连续状态次数达到后端取数或计算上限
|
||||
- **THEN** currentStreak SHALL 返回 `{ up: boolean, count: N, capped: true }`,前端据此展示上限标记
|
||||
|
||||
#### Scenario: 无检查记录
|
||||
- **WHEN** 目标没有任何检查记录
|
||||
- **THEN** currentStreak SHALL 返回 null
|
||||
|
||||
### Requirement: 趋势数据应用层分桶
|
||||
系统 SHALL 在后端应用层按 UTC 小时分桶生成趋势数据。
|
||||
|
||||
#### Scenario: 按小时生成趋势
|
||||
- **WHEN** metrics 请求 bucket=`1h`
|
||||
- **THEN** 系统 SHALL 按 UTC 小时生成 trend 数组,每个点包含该小时内的 totalChecks、upChecks、downChecks、availability、avgDurationMs、minDurationMs、maxDurationMs
|
||||
|
||||
#### Scenario: 小时内无成功检查
|
||||
- **WHEN** 某小时内存在检查记录但无成功检查记录
|
||||
- **THEN** avgDurationMs、minDurationMs、maxDurationMs SHALL 返回 null,availability SHALL 基于 upChecks/totalChecks 返回 0
|
||||
|
||||
#### Scenario: 小时内无检查记录
|
||||
- **WHEN** 某小时内没有任何检查记录
|
||||
- **THEN** 系统 MAY 不返回该小时对应的 trend 点
|
||||
|
||||
### Requirement: 无数据口径
|
||||
系统 SHALL 对无数据窗口返回稳定的空指标口径。
|
||||
|
||||
#### Scenario: 窗口内无检查记录
|
||||
- **WHEN** 指定时间窗口内没有任何检查记录
|
||||
- **THEN** stats SHALL 返回 totalChecks=0、upChecks=0、downChecks=0、availability=0、avgDurationMs=null、p95DurationMs=null、p99DurationMs=null、mttr=null、longestOutage=null、incidentCount=0、currentStreak=null,trend SHALL 返回空数组
|
||||
|
||||
### Requirement: 历史记录 API
|
||||
系统 SHALL 保留 `GET /api/targets/:id/history` 端点,支持时间范围筛选和分页返回指定目标的拨测记录。仅活跃目标的历史记录 SHALL 可查询。
|
||||
|
||||
@@ -221,16 +349,20 @@ Dashboard API SHALL 返回基于时间窗口计算的目标统计和连续状态
|
||||
- **THEN** API SHALL 返回 failure 为 null
|
||||
|
||||
### Requirement: Meta 信息 API
|
||||
系统 SHALL 提供 `GET /api/meta` 端点,返回系统运行时元数据。未匹配 method SHALL 按 API 通配符处理为 JSON 404,不再保留自定义 HEAD/405 语义。
|
||||
系统 SHALL 提供 `GET /api/meta` 端点,返回系统运行时元数据,包括应用版本号和 checker 类型列表。未匹配 method SHALL 按 API 通配符处理为 JSON 404。
|
||||
|
||||
#### Scenario: 获取 checker 类型列表
|
||||
#### Scenario: 获取 checker 类型列表和版本号
|
||||
- **WHEN** 客户端请求 `GET /api/meta`
|
||||
- **THEN** 系统 SHALL 返回 JSON `{ checkerTypes: string[] }`,包含所有已注册的 checker 类型标识符
|
||||
- **THEN** 系统 SHALL 返回 JSON `{ checkerTypes: string[], version: string }`,其中 `checkerTypes` 包含所有已注册的 checker 类型标识符,`version` 为当前运行实例的 `MAJOR.MINOR.PATCH` 应用版本
|
||||
|
||||
#### Scenario: 类型列表来源
|
||||
- **WHEN** 系统启动并注册了 checker
|
||||
- **THEN** `/api/meta` 返回的 `checkerTypes` SHALL 与 `CheckerRegistry.supportedTypes` 完全一致
|
||||
|
||||
#### Scenario: 版本号来源
|
||||
- **WHEN** 系统启动并确定应用版本
|
||||
- **THEN** `/api/meta` 返回的 `version` SHALL 与启动时注入的应用版本完全一致
|
||||
|
||||
#### Scenario: 不支持的 method 请求
|
||||
- **WHEN** 客户端使用 POST/PUT/DELETE/HEAD 等未声明 method 请求 `/api/meta`
|
||||
- **THEN** `/api/*` 通配符 SHALL 返回 JSON 404 响应
|
||||
@@ -240,4 +372,4 @@ Dashboard API SHALL 返回基于时间窗口计算的目标统计和连续状态
|
||||
|
||||
#### Scenario: MetaResponse 类型定义
|
||||
- **WHEN** 前后端引用 `MetaResponse` 类型
|
||||
- **THEN** 该类型 SHALL 包含 `checkerTypes: string[]` 字段
|
||||
- **THEN** 该类型 SHALL 包含 `checkerTypes: string[]` 和 `version: string` 字段
|
||||
|
||||
Reference in New Issue
Block a user