1
0

feat: target 软删除机制,配置移除时保留历史数据

This commit is contained in:
2026-05-20 00:43:39 +08:00
parent 9b53c746f6
commit b591dcca97
7 changed files with 294 additions and 38 deletions

View File

@@ -5,19 +5,19 @@
## Requirements
### Requirement: Dashboard 聚合 API
系统 SHALL 提供 `GET /api/dashboard` 端点,返回 Dashboard 首屏所需的总览统计和目标列表数据。
系统 SHALL 提供 `GET /api/dashboard` 端点,返回 Dashboard 首屏所需的总览统计和目标列表数据。targets 列表 SHALL 仅包含活跃目标。
#### Scenario: 获取 Dashboard 数据
- **WHEN** 客户端请求 `GET /api/dashboard?window=24h&recentLimit=30`
- **THEN** 系统 SHALL 返回 JSON 包含 summary 和 targets 字段
- **THEN** 系统 SHALL 返回 JSON 包含 summary 和 targets 字段targets 仅包含 active=1 的目标
#### Scenario: summary 字段
- **WHEN** Dashboard 响应包含 summary
- **THEN** summary SHALL 包含 total目标数、up当前正常目标数、down当前异常目标数、lastCheckTime最近一次检查时间、incidents指定窗口内异常事件数、windowfrom/to/label字段
- **THEN** summary SHALL 仅统计活跃目标:total活跃目标数、up活跃正常目标数、down活跃异常目标数、lastCheckTime最近一次检查时间、incidents活跃目标在指定窗口内异常事件数、windowfrom/to/label字段
#### Scenario: targets 字段
- **WHEN** Dashboard 响应包含 targets
- **THEN** targets 数组中每个元素 SHALL 包含目标基本信息id、name、description、group、type、target、interval、latestCheck、stats、currentStreak 和 recentSamples 字段,其中 name 和 description 均为 null 或字符串
- **THEN** targets 数组中每个元素 SHALL 为活跃目标,包含目标基本信息id、name、description、group、type、target、interval、latestCheck、stats、currentStreak 和 recentSamples 字段,其中 name 和 description 均为 null 或字符串
#### Scenario: target name 字段为 null
- **WHEN** 某个 target 未配置 `name` 或显式配置 `name: null`
@@ -75,25 +75,37 @@ Dashboard API SHALL 返回基于时间窗口计算的目标统计和连续状态
- **THEN** 每个 recentSamples 元素 SHALL 包含 timestamp、durationMs、up 字段,其中 up 为 boolean 且等于 matched
### Requirement: 单目标指标 API
系统 SHALL 提供 `GET /api/targets/:id/metrics` 端点,返回 Drawer 概览所需的单目标统计和趋势数据。端点的详细计算规则P95/P99、MTTR、故障分析、趋势分桶等定义在 `target-metrics-api` 能力中。
系统 SHALL 提供 `GET /api/targets/:id/metrics` 端点,返回 Drawer 概览所需的单目标统计和趋势数据。仅活跃目标的指标 SHALL 可查询。端点的详细计算规则P95/P99、MTTR、故障分析、趋势分桶等定义在 `target-metrics-api` 能力中。
#### Scenario: 指定时间范围查询指标
- **WHEN** 客户端请求 `GET /api/targets/1/metrics?from=ISO&to=ISO&bucket=1h`
- **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: 目标不存在或非活跃
- **WHEN** 客户端请求 `GET /api/targets/999/metrics?from=ISO&to=ISO` 且该目标不存在或 active=0
- **THEN** 系统 SHALL 返回 404 状态码和错误信息
#### Scenario: 无效的目标 ID
- **WHEN** 客户端请求 `GET /api/targets/abc/metrics?from=ISO&to=ISO`
- **THEN** 系统 SHALL 返回 400 状态码和错误信息
#### Scenario: bucket 参数缺失
- **WHEN** 客户端请求 `GET /api/targets/1/metrics?from=ISO&to=ISO` 未提供 bucket 参数
- **THEN** 系统 SHALL 默认使用 bucket=`1h`
#### Scenario: 不支持的 bucket 参数
- **WHEN** 客户端请求 `GET /api/targets/1/metrics?from=ISO&to=ISO&bucket=5m`
- **THEN** 系统 SHALL 返回 400 状态码和错误信息
### Requirement: 历史记录 API
系统 SHALL 保留 `GET /api/targets/:id/history` 端点,支持时间范围筛选和分页返回指定目标的拨测记录。
系统 SHALL 保留 `GET /api/targets/:id/history` 端点,支持时间范围筛选和分页返回指定目标的拨测记录。仅活跃目标的历史记录 SHALL 可查询。
#### Scenario: 获取指定时间范围内的历史记录
- **WHEN** 客户端请求 `GET /api/targets/1/history?from=ISO&to=ISO&page=1&pageSize=20`
- **WHEN** 客户端请求 `GET /api/targets/1/history?from=ISO&to=ISO&page=1&pageSize=20` 且该目标为活跃目标
- **THEN** 系统 SHALL 返回带分页信息的历史记录,包含 items、total、page、pageSize按时间倒序排列
#### Scenario: 使用默认分页参数
@@ -104,6 +116,10 @@ Dashboard API SHALL 返回基于时间窗口计算的目标统计和连续状态
- **WHEN** 客户端请求 `GET /api/targets/1/history` 未提供 from 或 to 参数
- **THEN** 系统 SHALL 返回 400 状态码和错误信息
#### Scenario: 目标不存在或非活跃
- **WHEN** 客户端请求 `GET /api/targets/999/history?from=ISO&to=ISO` 且该目标不存在或 active=0
- **THEN** 系统 SHALL 返回 404 状态码和错误信息
### Requirement: 新增共享类型
系统 SHALL 在 `src/shared/api.ts` 中定义 Dashboard 和 Metrics 相关共享类型。CheckResult SHALL 包含 durationMsnull | number、failureCheckFailure | null、matchedboolean、detailnull | string、observationRecord<string, unknown> | null、timestampstring。其中 detail 替代原 statusDetail 字段名。
@@ -159,12 +175,16 @@ Dashboard API SHALL 返回基于时间窗口计算的目标统计和连续状态
- **THEN** 系统 SHALL 返回与之前格式一致的健康检查响应
### Requirement: API 错误处理
系统 SHALL 对不存在的目标 ID、无效参数和超出范围的分页参数返回适当的 HTTP 错误响应。
系统 SHALL 对不存在的目标 ID、非活跃目标、无效参数和超出范围的分页参数返回适当的 HTTP 错误响应。非活跃目标与不存在的目标 SHALL 返回相同的 404 响应。
#### Scenario: 查询不存在的目标
- **WHEN** 客户端请求 `GET /api/targets/999/metrics?from=ISO&to=ISO`
- **THEN** 系统 SHALL 返回 404 状态码和错误信息
#### Scenario: 查询非活跃目标
- **WHEN** 客户端请求 `GET /api/targets/<id>/metrics?from=ISO&to=ISO` 且该目标 active=0
- **THEN** 系统 SHALL 返回 404 状态码和错误信息
#### Scenario: 无效的 from/to 参数
- **WHEN** 客户端请求 `GET /api/targets/1/metrics?from=invalid&to=ISO`
- **THEN** 系统 SHALL 返回 400 状态码和错误信息