feat: 新增两个 OpenSpec 变更提案 — CMD Checker 增强与前端指标增强
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 单目标深度统计 API
|
||||
系统 SHALL 提供 `GET /api/targets/:id/stats` 端点,返回单个目标在指定时间窗口内的非时序聚合统计指标。
|
||||
|
||||
#### Scenario: 获取目标统计
|
||||
- **WHEN** 客户端请求 `GET /api/targets/1/stats?from=ISO&to=ISO`
|
||||
- **THEN** 系统 SHALL 返回 JSON 对象包含 p95DurationMs、p99DurationMs、avgDurationMs、mttr、longestOutage、incidentCount、currentStreak、totalChecks、upChecks、downChecks、availability
|
||||
|
||||
#### Scenario: from 或 to 参数缺失
|
||||
- **WHEN** 客户端请求 `GET /api/targets/1/stats` 未提供 from 或 to 参数
|
||||
- **THEN** 系统 SHALL 返回 400 状态码和错误信息
|
||||
|
||||
#### Scenario: 目标不存在
|
||||
- **WHEN** 客户端请求 `GET /api/targets/999/stats`
|
||||
- **THEN** 系统 SHALL 返回 404 状态码和错误信息
|
||||
|
||||
#### Scenario: 无效的目标 ID
|
||||
- **WHEN** 客户端请求 `GET /api/targets/abc/stats`
|
||||
- **THEN** 系统 SHALL 返回 400 状态码和错误信息
|
||||
|
||||
### Requirement: P95/P99 延迟计算
|
||||
系统 SHALL 在应用层计算 P95 和 P99 延迟百分位数。
|
||||
|
||||
#### Scenario: 正常计算 P95
|
||||
- **WHEN** 时间窗口内存在成功检查记录(matched=1)
|
||||
- **THEN** 系统 SHALL 取出所有成功检查的 duration_ms,在应用层排序后取第 95 百分位值返回为 p95DurationMs
|
||||
|
||||
#### Scenario: 正常计算 P99
|
||||
- **WHEN** 时间窗口内存在成功检查记录
|
||||
- **THEN** 系统 SHALL 取第 99 百分位值返回为 p99DurationMs
|
||||
|
||||
#### Scenario: 无成功检查记录
|
||||
- **WHEN** 时间窗口内无 matched=1 的记录
|
||||
- **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** 最后一段故障尚未恢复
|
||||
- **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 次事件
|
||||
|
||||
### 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 为连续异常的检查次数
|
||||
|
||||
### Requirement: TargetStatsResponse 共享类型
|
||||
系统 SHALL 在 `src/shared/api.ts` 中定义 `TargetStatsResponse` 类型。
|
||||
|
||||
#### Scenario: 类型定义
|
||||
- **WHEN** 前后端引用 `TargetStatsResponse` 类型
|
||||
- **THEN** 该类型 SHALL 包含 p95DurationMs(number | null)、p99DurationMs(number | null)、avgDurationMs(number | null)、mttr(number | null)、longestOutage(number | null)、incidentCount(number)、currentStreak({ up: boolean; count: number })、totalChecks(number)、upChecks(number)、downChecks(number)、availability(number)
|
||||
Reference in New Issue
Block a user