# PRD — 服务监测模块（service-monitor）

> 版本：v0.1（草稿，待确认） ｜ 日期：2026-07-16 ｜ 模块 ID：`service-monitor`
> 参考实现：`临时目录/服务器监测/`（PowerShell + Bash 模块化架构 v4.0）

---

## 1. 背景与目标

### 1.1 背景
平台化改造已完成（见 `HANDOFF.md`），`modules.py` 已预留 `service-monitor` 模块（`enabled: false`）。本次将其落地为真实功能模块。

### 1.2 目标
为运维人员提供**服务状态巡检**能力：
- 监控服务器（本机 / 远程）上的系统资源与服务状态，发现异常
- 一键巡检 + 分类报告 + 异常项高亮
- **只做监测，不做修复**（修复接口预留，本期不实现）

### 1.3 用户角色
- **管理员**：可配置监测目标（本机/远程）、可触发巡检、可查看完整报告
- **普通用户**：仅可查看巡检报告（不可触发巡检、不可操作目标）

---

## 2. 核心概念（沿用参考脚本的设计）

| 概念 | 说明 |
|------|------|
| **监测目标 (Target)** | 一台被监测的服务器：`本地` 或 `远程(SSH)` |
| **检测项 (Check Item)** | 最小检测单元，输出 `KEY:VALUE`，如 `CPU_USAGE:85.3%` |
| **检测模块 (Module)** | 一组相关检测项的集合，分 `system` / `service` 两大类 |
| **状态等级 (Level)** | `正常` / `警告` / `严重`，由阈值判定 |
| **阈值 (Threshold)** | 触发警告/严重的临界值，集中配置可调 |

### 2.1 模块分类（沿用参考脚本编号）

**system 类（系统资源）**
- 01 系统基础信息 / 02 CPU / 03 内存 / 04 磁盘 / 05 OOM / 06 进程 / 07 网络
- 11 计划任务 / 12 端口检测
- 40 综合诊断 / 43 安全合规 / 44 系统日志 / 45 时间同步

**service 类（应用服务）**
- 20-21 Docker（基础+深度） / 22-23 MySQL / 24-25 Redis
- 26-27 EMQX / 28 Java / 29 Python / 30/34 Nginx / 31/35 Nacos / 32/36 FastDFS / 33 应用日志

**本期范围（核心子集）**：system(01/02/03/04) + Docker-basic + MySQL-basic + Redis-basic
后续迭代逐步补充其余模块。

---

## 3. 功能需求

### 3.1 监测目标管理
- [F1] **目标列表**：展示已配置的监测目标（名称、类型[本地/远程]、主机、端口、状态）
- [F2] **新增目标**：录入远程主机（地址、SSH 端口、用户名、凭据）
- [F3] **编辑/删除目标**：本地目标不可删（系统内置），远程目标可增删改
- [F4] **连通性测试**：保存前测试远程目标 SSH 是否可达

### 3.2 巡检执行
- [F5] **触发巡检**：选择目标 + 选择模块范围（全量/自定义子集）→ 执行
- [F6] **本机监测**：目标=本地时，直接在容器内执行检测模块（不走 SSH）
- [F7] **远程监测**：目标=远程时，走 SSH 连接执行检测模块
- [F8] **执行进度反馈**：巡检耗时长（全量约数分钟），需进度反馈（SSE 流式 or 轮询）
- [F9] **取消巡检**：长时间任务可中断

### 3.3 巡检报告
- [F10] **报告展示**：按模块分组展示检测结果（名称、当前值、阈值、状态等级）
- [F11] **异常高亮**：警告/严重项置顶 + 颜色标识
- [F12] **报告历史**：保留历次巡检报告，可回看对比
- [F13] **报告导出**：导出 Markdown / JSON（沿用参考脚本的 MD 报告格式）

### 3.4 阈值配置
- [F14] **阈值管理**：管理员可查看/调整各项阈值（CPU/内存/磁盘等告警临界值）

### 3.5 修复预留（本期不实现）
- [F-预留] 报告中异常项预留「修复」按钮位与接口契约，本期点击提示「修复能力开发中」

---

## 4. 本地 vs 远程的执行差异（关键设计）

| 维度 | 本地（local） | 远程（remote） |
|------|---------------|----------------|
| 执行方式 | 容器内直接 `subprocess` 调 bash 模块 | SSH（paramiko） |
| 模块部署 | 模块文件已在容器内 | 需将模块文件上传到远程 `/tmp/check_modules/` 再执行 |
| 凭据 | 无需 | SSH 密码/密钥，加密存储 |
| 连通性 | 默认可达 | 保存前需测试连通 |

**已确认决策**：
- ✅ Q3：远程连接用 **paramiko**（纯 Python）
- ✅ Q7：不同服务器容器名不一致 → **模糊匹配**（`docker ps | grep -i 模式`），`config.sh.template` 设容器名模式而非写死
- ✅ Q10：区分**快速巡检**（核心子集）与**全量巡检**（全部模块）两种模式

---

## 5. 架构原则：与服务端代码完全隔离

**核心原则**：服务监测模块是一个**自包含的子包**，不往 `routes/`、`services/`、`utils/` 目录写任何文件，避免与问题排查助手产生代码纠缠。

### 5.1 目录结构（子包方案）

```
skill/code/web/service_monitor/          # ★ 自包含子包
├── __init__.py                          #   导出 bp（Blueprint 实例）
├── routes.py                            #   路由定义
├── services/                            #   业务层（不涉及 troubleshoot 的 services/）
│   ├── __init__.py
│   ├── target_service.py               #   监测目标 CRUD 业务
│   ├── runner_service.py               #   巡检执行编排
│   └── report_service.py               #   报告管理
├── utils/                               #   工具层（不涉及 troubleshoot 的 utils/）
│   ├── __init__.py
│   ├── executor.py                      #   执行器 LocalExecutor / SSHExecutor
│   ├── parser.py                        #   解析 KEY:VALUE（移植 Parse-ModuleResult）
│   ├── thresholds.py                    #   阈值表 + 状态判定
│   └── check_modules.py                #   检测模块清单与元数据
├── templates/                           #   模板（templates/service_monitor/ 下）
│   └── service_monitor/
│       ├── targets.html                 #   目标管理页
│       ├── run.html                     #   巡检执行页
│       └── report.html                  #   报告详情页
├── assets/                              #   bash 检测模块（静态资源）
│   ├── config.sh.template              #   config 模板（占位符运行时渲染）
│   ├── common.sh                       #   通用函数库
│   ├── system/                         #   系统类模块
│   │   ├── 01_system_basic.sh
│   │   ├── 02_cpu_check.sh
│   │   └── ...
│   └── service/                        #   服务类模块
│       ├── 20_docker_basic.sh
│       ├── 22_mysql_basic.sh
│       └── ...
└── data/                                #   数据文件（独立于 records/）
    ├── targets.json                     #   监测目标列表
    └── reports/                         #   巡检报告归档
```

### 5.2 对外接口（极少，仅两处）

整个模块只通过两个点接入平台：

| 接入点 | 位置 | 代码 |
|--------|------|------|
| Blueprint 注册 | `server.py` | `from service_monitor import bp; app.register_blueprint(bp)` |
| 首页入口 | 已有 `modules.py` | `url: "/service-monitor"`（已配好） |

- **没有共享的 config**：服务监测的配置独立在 `service_monitor/` 内部管理
- **没有共享的工具函数**：不用 `utils/paths.py`、`utils/response.py` 等，自己管理
- **没有依赖冲突**：移除模块只需删除 `service_monitor/` 目录 + 去掉注册行

### 5.3 与问题排查助手的责任边界

| 维度 | 问题排查助手 | 服务监测模块 |
|------|-------------|-------------|
| 目录 | `routes/` `services/` `utils/` | `service_monitor/` 子包 |
| 数据 | `records.json` / `搜索索引.json` | `targets.json` / `reports/` |
| 模板 | `templates/index.html` | `templates/service_monitor/` |
| 配置 | `config.json` | 独立管理 |
| 对外 API | `/api/troubleshoot` / `/api/health` | `/api/service-monitor/*` |
| 页面路由 | `/troubleshoot` | `/service-monitor` |

数据存储：
- `service_monitor/data/targets.json` — 监测目标列表
- `service_monitor/data/reports/` — 巡检报告（每次一个 JSON）
- 阈值放 `service_monitor/assets/config.sh.template` 中管理
- ✅ Q5：JSON 文件
- ✅ Q6：SSH 密码加密存储（Fernet 对称加密，密钥从 `MONITOR_ENC_KEY` 环境变量读，缺失则派生自 `SECRET_KEY`）
- ✅ Q8：进度反馈用 SSE
- ✅ Q9：报告历史默认保留 14 天，可在配置中调整（不做定时自动巡检，本期纯手动触发）

---

## 6. 关键流程

### 6.1 触发巡检（远程为例）
1. 前端选目标 + 模块范围 → POST `/api/service-monitor/run`
2. `monitor_runner_service` 据目标类型选 executor
3. `SSHExecutor`：测试连通 → 上传模块 → 逐模块执行 → 收集原始输出
4. `monitor_parser` 解析 KEY:VALUE → `monitor_thresholds` 判定状态
5. 汇总写报告文件 + 缓存结果摘要
6. 前端 SSE 接收进度，完成后展示报告

### 6.2 状态判定
- 参考 `Get-StatusByValue`：按 KEY 查阈值规则（`>85%` 警告 / `>95%` 严重等），值类型可能是数值/百分比/布尔/文本
- 解析模块输出时已大量过滤错误行（中文冒号、整数表达式报错等），需移植这套过滤逻辑

---

## 7. 安全与凭据
- SSH 密码/密钥**禁止硬编码**，存 `targets.json` 时用 Fernet 加密
- 远程执行命令需防注入（用户名/主机做白名单校验）
- 巡检报告可能含敏感信息（密码不落报告，连接错误脱敏）

---

## 8. 决策确认（已与用户对齐）

| 编号 | 决策 |
|------|------|
| Q1 | 普通用户仅查看，不可操作；仅管理员可操作目标/触发巡检 |
| Q2 | 本期先做核心子集（system 01/02/03/04 + Docker/MySQL/Redis basic）验证链路，后续完善 |
| Q3 | 远程 SSH 用 paramiko |
| Q4 | bash 模块搬进项目 + config 外置 |
| Q5 | 数据存储用 JSON 文件 |
| Q6 | SSH 密码加密存储（Fernet） |
| Q7 | 不同服务器容器名不一致 → 通过容器名称**模糊匹配**发现，config 用模式而非写死名 |
| Q8 | 进度反馈用 SSE |
| Q9 | 报告历史默认保留 14 天，可配置；本期不做定时自动巡检 |
| Q10 | 区分快速巡检（核心子集）与全量巡检（全部模块）两种模式 |

---

## 9. 验收标准（待细化）
- [ ] 管理员可增删改查监测目标，远程目标保存前可测连通
- [ ] 本地目标一键巡检，报告正确解析、状态判定准确
- [ ] 远程目标一键巡检，SSH 上传模块+执行+回传结果全链路通
- [ ] 报告按模块分组、异常高亮、可导出 MD/JSON
- [ ] 阈值可在配置中调整并生效
- [ ] 单元测试覆盖 parser/thresholds/executor（mock SSH）

---

> 下一步：等用户解答 Q1-Q10 后，输出 `PRD_计划执行_服务监测模块.md` 详细实现计划。
