# PRD 计划执行：异常项趋势告警

> 模块：服务监测（service_monitor）
> 优先级：P1
> 创建日期：2026-07-23
> 需求文档：`PRD_需求文档_异常项趋势告警.md`

---

## 执行计划

### 阶段一：后端告警检测逻辑（预估 2h）

**任务清单**：

- [ ] 1.1 新增告警检测函数
  - 文件：`skill/code/web/service_monitor/services/report_service.py`
  - 函数：`check_consecutive_abnormal(target_id, current_report)`
  - 函数：`_get_alert_config(target_id)` - 获取告警配置
  - 函数：`_get_abnormal_items(report, alert_level)` - 提取异常项
  - 函数：`_get_recent_reports(target_id, count)` - 查询最近报告
  - 函数：`_is_consecutive(item_key, recent_reports, threshold)` - 检查连续性

- [ ] 1.2 实现冷却期机制
  - 变量：`_ALERT_COOLDOWN` 字典（内存缓存）
  - 函数：`_in_cooldown(target_id, item_key)` - 检查冷却期
  - 函数：`_set_cooldown(target_id, item_key)` - 设置冷却期

- [ ] 1.3 报告完成回调集成
  - 文件：`skill/code/web/service_monitor/services/runner_service.py`
  - 位置：`_finish_run()` 函数内
  - 逻辑：报告保存后调用 `check_consecutive_abnormal()`

**验收标准**：
- 连续异常检测逻辑正确
- 冷却期机制生效
- 回调集成无误

---

### 阶段二：通知发送集成（预估 1h）

**任务清单**：

- [ ] 2.1 新增告警消息模板
  - 文件：`skill/code/web/service_monitor/services/runner_service.py`
  - 函数：`_build_consecutive_alert_message(target_name, items)` - 构建告警消息
  - 模板：文本格式 + Markdown 格式（钉钉/企微）

- [ ] 2.2 复用现有通知发送
  - 调用：`_send_notification()` 函数
  - 参数：目标配置中的通知渠道
  - 逻辑：批量发送告警消息

- [ ] 2.3 消息链接生成
  - 报告链接：包含 access_token（如果有）
  - 格式：`{base_url}/service-monitor/report/{report_id}?token={token}`

**验收标准**：
- 消息模板格式正确
- 通知发送成功
- 链接可访问

---

### 阶段三：前端配置页（预估 1h）

**任务清单**：

- [ ] 3.1 修改通知配置页
  - 文件：`skill/code/web/templates/service_monitor/notification.html`
  - 新增：连续异常告警配置区
  - 元素：开关、连续次数输入框、告警级别下拉框、通知渠道多选框

- [ ] 3.2 配置保存逻辑
  - 复用：现有 `saveNotificationConfig()` 函数
  - 扩展：表单数据包含 `alert_on_consecutive` 字段

- [ ] 3.3 配置加载逻辑
  - 复用：现有加载函数
  - 渲染：根据配置显示开关状态和配置值

**验收标准**：
- 配置区正常显示
- 开关控制生效
- 保存/加载正常

---

### 阶段四：单元测试（预估 1h）

**任务清单**：

- [ ] 4.1 新增测试文件
  - 文件：`skill/code/tests/test_consecutive_alert.py`
  - 用例：
    - 连续异常检测（3 次、5 次）
    - 告警级别过滤（仅严重 / 警告+严重）
    - 冷却期机制
    - 无历史报告/报告不足情况

- [ ] 4.2 覆盖率目标
  - 目标：告警逻辑 > 80%

**验收标准**：
- 所有测试用例通过
- 覆盖率达标

---

### 阶段五：集成测试 + 部署（预估 1h）

**任务清单**：

- [ ] 5.1 本地集成测试
  - 测试：完整流程（配置 → 巡检 → 告警）
  - 验证：边界情况（配置禁用、无历史报告）

- [ ] 5.2 部署到 5.60
  - 更新：`deploy/upload_to_server.py` 文件清单
  - 执行：部署脚本
  - 验证：健康检查 + 功能测试

- [ ] 5.3 更新文档
  - 更新：`HANDOFF_服务监测.md`
  - 提交：Git commit

**验收标准**：
- 本地测试通过
- 部署成功
- 5.60 功能验证通过

---

## 关键文件清单

### 修改文件

| 文件 | 改动 |
|------|------|
| `service_monitor/services/report_service.py` | 新增连续异常检测函数 |
| `service_monitor/services/runner_service.py` | 新增告警消息模板 + 回调集成 |
| `templates/service_monitor/notification.html` | 新增连续异常告警配置区 |

### 新增文件

| 文件 | 说明 |
|------|------|
| `tests/test_consecutive_alert.py` | 单元测试 |

---

## 风险与注意事项

### 风险 1：内存冷却期丢失

**问题**：服务重启后 `_ALERT_COOLDOWN` 内存字典清空，可能重复告警

**缓解**：
- 可接受（重启频率低）
- 后续可改为持久化存储（Redis/SQLite）

### 风险 2：历史报告查询性能

**问题**：大目标历史报告多，查询最近 N 份可能耗时

**缓解**：
- 查询时限制数量（`limit=N`）
- 报告数据已按时间索引，查询效率可接受

### 风险 3：通知发送失败

**问题**：钉钉/企微 API 可能超时或限流

**缓解**：
- 复用现有通知重试机制
- 发送失败记录日志，不阻断巡检流程

---

## 依赖关系

- 依赖现有通知配置结构（`targets.json`）
- 依赖现有通知发送机制（`runner_service._send_notification()`）
- 无外部依赖新增

---

## 完成定义（DoD）

- [ ] 所有阶段任务完成
- [ ] 单元测试覆盖率 > 80%
- [ ] 本地集成测试通过
- [ ] 部署到 5.60 成功
- [ ] 功能验证通过
- [ ] 文档更新并提交