Files
hms/docs/superpowers/plans/2026-04-26-observability-and-ops.md
iven b410fa9f78
Some checks failed
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
CI / security-audit (push) Has been cancelled
docs: 5 份实施计划 — 性能/安全/事件/前端/可观测性
对应 5 份设计规格,共 75 个 Task:

1. 性能优化 (12 Task) — 批量INSERT/N+1内联name/合并COUNT/按需重绘/chunk拆分
2. 安全纵深防御 (8 Task) — RLS/行级数据范围/Redis session_key/审计哈希链
3. 事件驱动架构 (10 Task) — 11个缺失事件补发/LISTEN+NOTIFY/schema版本化
4. 前端工程化 (10 Task) — hook统一/组件拆分/Bundle优化
5. 可观测性运维 (10 Task) — 深度健康检查/Prometheus/OTel/生产Docker/告警
2026-04-27 08:00:50 +08:00

201 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 可观测性与运维基础设施实施计划
> 设计规格: `docs/superpowers/specs/2026-04-26-observability-and-ops-design.md`
> 日期: 2026-04-26 | 总周期: 7-9 天
---
## Phase 1: 健康检查 + Prometheus 指标Day 1-2
### Task 1: 深度健康检查端点
**涉及文件**:
- 修改: `crates/erp-server/src/handlers/health.rs`
**步骤**:
1. 拆分为两个端点:
- `GET /health/live` — 存活探针(仅返回 `{ status: "ok" }`,不依赖任何外部服务)
- `GET /health/ready` — 就绪探针(验证 DB ping + Redis ping + 模块状态)
2. `/health/ready` 实现:
```rust
async fn health_ready(State(state): State<AppState>) -> Json<HealthResponse> {
let db_ok = sql_query("SELECT 1").execute(&state.db).await.is_ok();
let redis_ok = state.redis.ping().await.is_ok();
Json(HealthResponse { status: if db_ok && redis_ok { "ok" } else { "degraded" }, db: db_ok, redis: redis_ok, ... })
}
```
3. 保持旧 `GET /health` 兼容(重定向到 `/health/ready`
**验收**: `/health/ready` 在 DB/Redis 正常时返回 200任一不可达时返回 503 + 降级详情
### Task 2: Prometheus 指标基础
**涉及文件**:
- 修改: `crates/erp-server/Cargo.toml`(添加 `metrics` + `metrics-exporter-prometheus` 依赖)
- 新增: `crates/erp-server/src/middleware/metrics.rs`
- 修改: `crates/erp-server/src/main.rs`(注册 metrics middleware + 路由)
**步骤**:
1.`Cargo.toml` 添加:
```toml
metrics = "0.24"
metrics-exporter-prometheus = "0.16"
```
2. 创建 `metrics.rs` Axum middleware
- 记录每个请求的 `http_request_duration_seconds`(直方图,按 method/path/status 标签)
- 记录 `http_requests_total`(计数器)
3.`main.rs` 启动 Prometheus exporter`/metrics` 端点,端口 9090
4. 在 AppState 中注册 metrics recorder
**验收**: `curl localhost:9090/metrics` 返回 Prometheus 格式指标,包含请求延迟直方图
### Task 3: DB 连接池 + EventBus 积压指标
**涉及文件**:
- 修改: `crates/erp-server/src/main.rs`
- 修改: `crates/erp-core/src/events.rs`
**步骤**:
1. DB 连接池指标:每 30 秒采样 `db_pool_connections_active` / `db_pool_connections_idle`
2. EventBus 积压指标:在 `publish()` 中递增 `eventbus_pending_total`,在 relay 处理后递减
3.`/metrics` 端点暴露
**验收**: `/metrics` 包含 DB 连接池使用率和事件积压计数
---
## Phase 2: OpenTelemetry + 生产 DockerDay 3-5
### Task 4: OpenTelemetry 条件集成
**涉及文件**:
- 修改: `crates/erp-server/Cargo.toml`(添加 `opentelemetry` + `tracing-opentelemetry` + `opentelemetry-otlp`optional feature
- 新增: `crates/erp-server/src/telemetry.rs`
- 修改: `crates/erp-server/src/main.rs`
**步骤**:
1. 添加 optional 依赖:
```toml
[features]
tracing = ["opentelemetry", "tracing-opentelemetry", "opentelemetry-otlp"]
```
2. 创建 `telemetry.rs`:条件初始化 OpenTelemetry tracer环境变量 `ERP__TELEMETRY__ENABLED=true` 时启用)
3. 配置 OTLP exporter默认 `http://localhost:4317`,可通过环境变量覆盖)
4.`main.rs` 的 tracing subscriber 中条件注册 OpenTelemetry layer
5. 在 SeaORM 的 `DatabaseConnection` 包装中添加 span记录查询耗时
**验收**: 启用后 Jaeger/Tempo 可看到请求 → SQL 查询 → 事件发布的完整链路;不启用时零开销
### Task 5: 生产 Docker 多阶段构建
**涉及文件**:
- 新增: `Dockerfile`(项目根目录)
- 新增: `docker/docker-compose.production.yml`
**步骤**:
1. 多阶段 Dockerfile:
```dockerfile
# Stage 1: Build
FROM rust:1.82-bookworm AS builder
COPY . /app
RUN cargo build --release -p erp-server
# Stage 2: Runtime
FROM debian:bookworm-slim
COPY --from=builder /app/target/release/erp-server /usr/local/bin/
COPY --from=builder /app/crates/erp-server/config/default.toml /etc/erp/config.toml
EXPOSE 3000 9090
CMD ["erp-server"]
```
2. `docker-compose.production.yml`:
- erp-server 服务(限制 1 CPU / 512MB
- PostgreSQL 16 + Redis 7 作为独立服务
- 健康检查配置(使用 /health/ready
- 环境变量注入JWT secret / DB URL / Redis URL 通过 secrets
**验收**: `docker build -t hms-server .` 成功,运行时镜像 < 80MB
### Task 6: 前端生产构建 + Nginx
**涉及文件**:
- 新增: `apps/web/Dockerfile`
- 新增: `apps/web/nginx.conf`
**步骤**:
1. 多阶段构建node 构建 → nginx 运行
2. Nginx 配置SPA fallback + `/api` 代理到后端 3000 端口
**验收**: Docker 内前端可正常访问API 代理工作
---
## Phase 3: 日志聚合 + 告警Day 5-7
### Task 7: Grafana Loki 日志集成
**涉及文件**:
- 新增: `docker/loki-config.yaml`
- 修改: `docker/docker-compose.production.yml`
**步骤**:
1. 在 production compose 中添加 Loki + Promtail 服务
2. Promtail 配置:读取 erp-server 的 JSON 日志输出
3. Grafana 数据源配置Loki + Prometheus
**验收**: Grafana 可查询和过滤后端日志
### Task 8: Prometheus 告警规则
**涉及文件**:
- 新增: `docker/alert-rules.yml`
**步骤**:
1. 定义 5 条告警规则:
```yaml
- alert: HighRequestLatency # P95 > 2s 持续 5 分钟
- alert: HighErrorRate # 5xx 比率 > 5% 持续 3 分钟
- alert: EventBusBacklog # 积压事件 > 100 持续 5 分钟
- alert: DatabasePoolExhausted # 活跃连接 > 90% 持续 2 分钟
- alert: HealthCheckDegraded # /health/ready 非 ok 持续 1 分钟
```
2. 配置 Alertmanager 通知渠道Webhook/邮件)
**验收**: 触发告警条件时 Alertmanager 发送通知
### Task 9: Grafana Dashboard 模板
**涉及文件**:
- 新增: `docker/grafana/dashboards/hms-overview.json`
**步骤**:
1. 创建 HMS Overview Dashboard包含面板
- 请求速率 + 延迟分布P50/P95/P99
- 错误率趋势(按 status code 分组)
- DB 连接池使用率
- EventBus 发布/消费速率
- 健康检查状态
**验收**: Dashboard 展示实时指标
### Task 10: 运维文档
**涉及文件**:
- 新增: `wiki/observability.md`
**步骤**:
1. 记录监控端点(/health/live, /health/ready, /metrics
2. 记录告警规则和响应流程
3. 记录日志查询方法Grafana Loki
4. 记录 Docker 部署命令
**验收**: 新团队成员可通过文档独立部署和排查问题
---
## 执行原则
1. **条件编译** — OpenTelemetry 使用 feature gate不启用时零开销
2. **渐进式** — Phase 1 可独立上线无外部依赖Phase 2/3 需要 Docker 环境
3. **性能优先** — 指标收集使用 `metrics` crate 的无锁实现,不影响请求延迟
4. **端口分离** — 业务 API (3000) + Metrics (9090) 分离,避免暴露内部指标