1
0
Files
DiAL/openspec/specs/probe-api/spec.md
lanyuanxiaoyao 1c5cfafda6 feat: 前端指标体系增强 — Dashboard/Metrics API、2×4 统计区、趋势图面积+异常标记、连续状态列
- 新增 GET /api/dashboard 合并原 summary+targets 首屏接口
- 新增 GET /api/targets/:id/metrics 合并原 stats+trend 概览接口
- 后端指标纯函数:可用率、百分位、故障段分析、连续状态、UTC 小时分桶
- ProbeStore 窗口取数方法替代全量历史查询
- SummaryCards 扩展为 4 卡片(新增异常事件数)+ 数据新鲜度展示
- 表格新增「连续」列(Tag 渲染 capped 状态)
- OverviewTab 重构为 2×4 Statistic 多维度布局
- TrendChart 改为延迟范围面积图 + 红色异常标记点
- 删除旧路由(summary/targets/trend)和 computeTrendStats
- 同步 delta specs 到主 specs 并归档变更
2026-05-14 12:32:41 +08:00

9.8 KiB
Raw Blame History

Purpose

定义拨测系统的 REST API 端点Dashboard 聚合 API、单目标指标 API、带时间范围和分页的历史记录、共享类型定义和 API 错误处理。

Requirements

Requirement: Dashboard 聚合 API

系统 SHALL 提供 GET /api/dashboard 端点,返回 Dashboard 首屏所需的总览统计和目标列表数据。

Scenario: 获取 Dashboard 数据

  • WHEN 客户端请求 GET /api/dashboard?window=24h&recentLimit=30
  • THEN 系统 SHALL 返回 JSON 包含 summary 和 targets 字段

Scenario: summary 字段

  • WHEN Dashboard 响应包含 summary
  • THEN summary SHALL 包含 total总目标数、up当前正常目标数、down当前异常目标数、lastCheckTime最近一次检查时间、incidents指定窗口内异常事件数、windowfrom/to/label字段

Scenario: targets 字段

  • WHEN Dashboard 响应包含 targets
  • THEN targets 数组中每个元素 SHALL 包含目标基本信息id、name、group、type、target、interval、latestCheck、stats、currentStreak 和 recentSamples 字段

Scenario: window 参数缺失

  • WHEN 客户端请求 GET /api/dashboard 未提供 window 参数
  • THEN 系统 SHALL 默认使用 window=24h

Scenario: window 参数语义

  • WHEN 系统处理 Dashboard 请求
  • THEN 系统 SHALL 以服务端当前时间作为 window.to以 window 参数换算 window.from并在响应中回显 window.from、window.to、window.label

Scenario: window 参数有效值

  • WHEN 客户端请求 Dashboard 端点并指定 window 参数
  • THEN 系统 SHALL 接受 24h 作为有效值;其他值 SHALL 返回 400 状态码和错误信息

Scenario: 不支持的 window 参数

  • WHEN 客户端请求 GET /api/dashboard?window=abc
  • THEN 系统 SHALL 返回 400 状态码和错误信息

Scenario: recentLimit 参数缺失

  • WHEN 客户端请求 GET /api/dashboard?window=24h 未提供 recentLimit 参数
  • THEN 系统 SHALL 默认使用 recentLimit=30

Scenario: 不支持的 recentLimit 参数

  • WHEN 客户端请求 GET /api/dashboard?recentLimit=0 或超过系统上限的 recentLimit
  • THEN 系统 SHALL 返回 400 状态码和错误信息

Scenario: 目标无历史记录

  • WHEN 某目标尚未执行过任何拨测
  • THEN 其 latestCheck 为 nullrecentSamples 为空数组stats.totalChecks 为 0stats.availability 为 0currentStreak 为 null

Requirement: Dashboard 指标字段

Dashboard API SHALL 返回基于时间窗口计算的目标统计和连续状态字段。

Scenario: 目标 stats 字段

  • WHEN Dashboard 响应包含目标 stats
  • THEN stats SHALL 包含 totalChecks、upChecks、downChecks、availability 字段,且这些字段 SHALL 基于请求 window 对应的时间范围计算

Scenario: 目标 currentStreak 字段

  • WHEN Dashboard 响应包含目标 currentStreak
  • THEN currentStreak SHALL 为 { up: boolean, count: number, capped?: boolean } 或 null

Scenario: currentStreak 达到 recentLimit

  • WHEN 连续状态次数达到 recentLimit 上限
  • THEN currentStreak.capped SHALL 为 true

Scenario: recentSamples 字段

  • WHEN Dashboard 响应包含 recentSamples
  • THEN 每个 recentSamples 元素 SHALL 包含 timestamp、durationMs、up 字段,其中 up 为 boolean 且等于 matched

Requirement: 单目标指标 API

系统 SHALL 提供 GET /api/targets/:id/metrics 端点,返回 Drawer 概览所需的单目标统计和趋势数据。端点的详细计算规则P95/P99、MTTR、故障分析、趋势分桶等定义在 target-metrics-api 能力中。

Scenario: 指定时间范围查询指标

  • WHEN 客户端请求 GET /api/targets/1/metrics?from=ISO&to=ISO&bucket=1h
  • THEN 系统 SHALL 返回 targetId、window、stats、trend 字段

Scenario: from 或 to 参数缺失

  • WHEN 客户端请求 GET /api/targets/1/metrics 未提供 from 或 to 参数
  • THEN 系统 SHALL 返回 400 状态码和错误信息

Scenario: bucket 参数缺失

  • WHEN 客户端请求 GET /api/targets/1/metrics?from=ISO&to=ISO 未提供 bucket 参数
  • THEN 系统 SHALL 默认使用 bucket=1h

Requirement: 历史记录 API

系统 SHALL 保留 GET /api/targets/:id/history 端点,支持时间范围筛选和分页返回指定目标的拨测记录。

Scenario: 获取指定时间范围内的历史记录

  • WHEN 客户端请求 GET /api/targets/1/history?from=ISO&to=ISO&page=1&pageSize=20
  • THEN 系统 SHALL 返回带分页信息的历史记录,包含 items、total、page、pageSize按时间倒序排列

Scenario: 使用默认分页参数

  • WHEN 客户端请求 GET /api/targets/1/history?from=ISO&to=ISO(未指定 page 或 pageSize
  • THEN 系统 SHALL 使用默认 page=1, pageSize=20

Scenario: from 或 to 参数缺失

  • WHEN 客户端请求 GET /api/targets/1/history 未提供 from 或 to 参数
  • THEN 系统 SHALL 返回 400 状态码和错误信息

Requirement: 新增共享类型

系统 SHALL 在 src/shared/api.ts 中定义 Dashboard 和 Metrics 相关共享类型。

Scenario: DashboardResponse 类型

  • WHEN 前后端共享 DashboardResponse 类型
  • THEN 该类型 SHALL 包含 summary 和 targets 字段

Scenario: TargetStatus 类型

  • WHEN 前后端共享 TargetStatus 类型
  • THEN 该类型 SHALL 包含 statstotalChecks、upChecks、downChecks、availability、currentStreak 和 recentSamples 字段

Scenario: TargetMetricsResponse 类型

  • WHEN 前后端共享 TargetMetricsResponse 类型
  • THEN 该类型 SHALL 包含 targetId、window、stats 和 trend 字段

Scenario: TrendPoint 类型

  • WHEN 前后端共享 TrendPoint 类型
  • THEN 该类型 SHALL 包含 bucketStart、avgDurationMs、minDurationMs、maxDurationMs、availability、totalChecks、upChecks、downChecks 字段

Scenario: CheckResult 类型

  • WHEN 前后端共享 CheckResult 类型
  • THEN 该类型 SHALL 包含 timestamp: stringmatched: booleandurationMs: number | nullstatusDetail: string | nullfailure 字段,不包含 success 字段

Scenario: RecentSample 类型

  • WHEN 前后端共享 RecentSample 类型
  • THEN 该类型 SHALL 包含 timestamp: stringdurationMs: number | nullup: boolean 字段,其中 up 为 boolean 且等于 matched

Scenario: HistoryResponse 类型

  • WHEN 前后端共享 HistoryResponse 类型
  • THEN 该类型 SHALL 包含 items: CheckResult[]total: numberpage: numberpageSize: number 字段

Requirement: 保留健康检查端点

系统 SHALL 保留 GET /health 端点,不受拨测功能影响。

Scenario: 访问健康检查

  • WHEN 客户端请求 GET /health
  • THEN 系统 SHALL 返回与之前格式一致的健康检查响应

Requirement: API 错误处理

系统 SHALL 对不存在的目标 ID、无效参数和超出范围的分页参数返回适当的 HTTP 错误响应。

Scenario: 查询不存在的目标

  • WHEN 客户端请求 GET /api/targets/999/metrics?from=ISO&to=ISO
  • THEN 系统 SHALL 返回 404 状态码和错误信息

Scenario: 无效的 from/to 参数

  • WHEN 客户端请求 GET /api/targets/1/metrics?from=invalid&to=ISO
  • THEN 系统 SHALL 返回 400 状态码和错误信息

Scenario: from 晚于 to

  • WHEN 客户端请求 GET /api/targets/1/metrics?from=<较晚时间>&to=<较早时间>
  • THEN 系统 SHALL 返回 400 状态码和错误信息,提示 from 必须早于 to

Scenario: 无效的分页参数

  • WHEN 客户端请求 GET /api/targets/1/history?from=ISO&to=ISO&page=abc
  • THEN 系统 SHALL 返回 400 状态码和错误信息

Scenario: pageSize 超过上限

  • WHEN 客户端请求 GET /api/targets/1/history?from=ISO&to=ISO&pageSize=201
  • THEN 系统 SHALL 返回 400 状态码和错误信息,提示 pageSize 不能超过 200

Scenario: pageSize 等于上限

  • WHEN 客户端请求 GET /api/targets/1/history?from=ISO&to=ISO&pageSize=200
  • THEN 系统 SHALL 正常返回数据

Scenario: 无效的目标 ID

  • WHEN 客户端请求 GET /api/targets/abc/metrics?from=ISO&to=ISO
  • THEN 系统 SHALL 返回 400 状态码和错误信息

Requirement: 失败信息 API 契约

系统 SHALL 通过 API 返回结构化 failure 信息,供 Dashboard 展示和后续排查。

Scenario: 返回 expect 不匹配信息

  • WHEN 最近一次检查结果包含 failure.kind=mismatch
  • THEN /api/targets/api/targets/:id/history SHALL 返回该 failure 的 kind、phase、path、expected、actual、message 字段

Scenario: 无失败信息

  • WHEN 检查结果 matched=true
  • THEN API SHALL 返回 failure 为 null

Requirement: Meta 信息 API

系统 SHALL 提供 GET /api/meta 端点,返回系统运行时元数据。未匹配 method SHALL 按 API 通配符处理为 JSON 404不再保留自定义 HEAD/405 语义。

Scenario: 获取 checker 类型列表

  • WHEN 客户端请求 GET /api/meta
  • THEN 系统 SHALL 返回 JSON { checkerTypes: string[] },包含所有已注册的 checker 类型标识符

Scenario: 类型列表来源

  • WHEN 系统启动并注册了 checker
  • THEN /api/meta 返回的 checkerTypes SHALL 与 CheckerRegistry.supportedTypes 完全一致

Scenario: 不支持的 method 请求

  • WHEN 客户端使用 POST/PUT/DELETE/HEAD 等未声明 method 请求 /api/meta
  • THEN /api/* 通配符 SHALL 返回 JSON 404 响应

Requirement: MetaResponse 共享类型

系统 SHALL 在 src/shared/api.ts 中定义 MetaResponse 类型。

Scenario: MetaResponse 类型定义

  • WHEN 前后端引用 MetaResponse 类型
  • THEN 该类型 SHALL 包含 checkerTypes: string[] 字段