valdomirosouza/AgenticAI-2-Incident-Response
GitHub: valdomirosouza/AgenticAI-2-Incident-Response
基于 Claude 多智能体协作的 IT 事件响应副驾驶系统,通过四大黄金信号并行分析生成结构化诊断报告,以降低事件响应的 MTTD 和 MTTR。
Stars: 0 | Forks: 0
# AgenticAI-2-Incident-Response
探索**Agentic AI 作为副驾驶**以降低 IT 事件响应中 **MTTD**(平均检测时间)和 **MTTR**(平均恢复时间)的研究项目 —— 作为 **PPGCA / Unisinos** 硕士论文的一部分开发。
## 工作原理 —— 非专业人士概述
该系统分为两个不同的阶段:**持续数据收集**和**基于 AI 的按需分析**。
```
sequenceDiagram
autonumber
actor HA as 🌐 HAProxy (Load Balancer)
participant API as 📡 API de Ingestão
(porta 8000) participant DB as 🗄️ Redis
(Banco de Métricas) actor ENG as 👩💻 Engenheiro On-call participant ORC as 🎯 Orquestrador
(Agente IA) participant CL as 🧠 Claude
(LLM da Anthropic) rect rgb(220, 240, 255) Note over HA,DB: FASE 1 — Coleta contínua de dados (acontece o tempo todo) HA ->> API: Envia log de cada requisição HTTP recebida API ->> DB: Atualiza contadores de erros, latência e tráfego Note over DB: Métricas acumuladas em tempo real end rect rgb(220, 255, 220) Note over ENG,CL: FASE 2 — Análise com IA (disparada pelo engenheiro) ENG ->> ORC: POST /analyze — "Analise o estado do sistema agora" par 4 especialistas trabalham ao mesmo tempo ⚡ ORC ->>+ CL: Especialista de Latência consulta P50/P95/P99 DB -->> CL: dados de tempo de resposta CL -->>- ORC: "P99 = 1.500ms — CRÍTICO (limite: 1.000ms)" and ORC ->>+ CL: Especialista de Erros consulta taxas 4xx/5xx DB -->> CL: dados de erros HTTP CL -->>- ORC: "Taxa 5xx = 12% — CRÍTICO (limite: 5%)" and ORC ->>+ CL: Especialista de Saturação consulta uso de memória DB -->> CL: dados de memória e conexões Redis CL -->>- ORC: "Memória em 45%, sem conexões rejeitadas — OK" and ORC ->>+ CL: Especialista de Tráfego consulta requisições/minuto DB -->> CL: histórico de RPS dos últimos 10 minutos CL -->>- ORC: "RPS caiu a zero há 6 minutos — CRÍTICO (possível outage)" end ORC ->>+ CL: "3 de 4 especialistas reportaram CRÍTICO. Sintetize o diagnóstico." CL -->>- ORC: Título · Diagnóstico · Recomendações priorizadas ORC -->> ENG: 📋 Relatório de Incidente completo Note over ENG: Diagnóstico em ~10 segundos
em vez de minutos ou horas end ``` ## 架构 ### 系统概述 ``` flowchart LR HA["HAProxy\nLoad Balancer"] ENG(["Engenheiro\nOn-call"]) subgraph PLATFORM["Backend — AgenticAI · Incident Response"] subgraph INGESTION["Log Ingestion & Metrics · :8000"] LOGS["POST /logs"] MET["GET /metrics/*"] PROMED["GET /prometheus"] end REDIS[("Redis :6379\nP50·P95·P99\nRPS · errors")] subgraph OBS["Observability"] PROM["Prometheus"] GRAF["Grafana"] JAEG["Jaeger · Loki"] end subgraph AGENT["Incident Response Agent · :8001"] ORCH["Orchestrator\nasyncio.gather"] LAT["Latency\nP50/P95/P99"] ERR["Errors\n4xx / 5xx"] SAT["Saturation\nRedis memory"] TRF["Traffic\nRPS drops"] end CLAUDE["Claude API\nclaude-sonnet-4-6\nTool-use Loop"] REPORT[/"📋 IncidentReport"/] PM[["Post-mortems\nINC-001 · INC-002\nINC-003 · INC-004"]] end HA -->|"① POST /logs"| LOGS LOGS -->|"② persiste"| REDIS REDIS --> MET PROMED -.->|"③ scrape"| PROM PROM --> GRAF & JAEG ENG -->|"④ POST /analyze"| ORCH ORCH -->|"⑤ spawn parallel"| LAT & ERR & SAT & TRF LAT & ERR & SAT & TRF -->|"⑥ GET /metrics/*"| MET LAT & ERR & SAT & TRF <-->|"⑦ tool-use loop"| CLAUDE LAT & ERR & SAT & TRF -->|"⑧ findings"| ORCH ORCH -->|"⑨ síntese final"| REPORT REPORT --> ENG & PM ``` ### 内部架构 ``` flowchart TB subgraph sources["Log Sources"] HA["HAProxy / Load Balancer"] end subgraph compose["Docker Compose"] subgraph agent["Incident-Response-Agent · FastAPI :8001"] direction TB ORCH["Orchestrator\nasyncio.gather — runs specialists in parallel"] subgraph specialists["Specialist Agents (Claude claude-sonnet-4-6 + tool use)"] SLA["Latency\nP50 · P95 · P99"] SEA["Errors\n4xx / 5xx rates"] SSA["Saturation\nRedis resources"] STA["Traffic\nRPS / backends"] end ORCH -->|"spawn"| specialists specialists -->|"SpecialistFinding"| ORCH end subgraph service["Log-Ingestion-and-Metrics · FastAPI :8000"] direction TB subgraph middleware["Middleware"] RLM["RequestLoggingMiddleware\nX-Request-ID · JSON access log"] SHM["SecurityHeadersMiddleware\nX-Content-Type-Options · CORP"] end subgraph routers["Routers"] RI["POST /logs"] RM["GET /metrics/*\noverview · status-codes · backends\nfrontends · response-times · rps · saturation"] RH["GET /health"] RP["GET /prometheus/metrics"] end subgraph services["Services"] SI["ingestion.py\nprocess_log()"] SM["metrics.py\nget_overview() · get_saturation()\nget_response_time_percentiles()"] end subgraph observability["Observability"] OT["OpenTelemetry SDK\nFastAPI + Redis auto-instrumentation"] PI["prometheus-fastapi-instrumentator\nLatency · Traffic · Errors · Saturation"] JL["python-json-logger\nStructured JSON stdout"] end end REDIS[("Redis :6379\n─────────────────\nmetrics:requests:total\nmetrics:status:{code}\nmetrics:errors:4xx / 5xx\nmetrics:response_times ← P50/P95/P99\nmetrics:rps:{YYYY-MM-DDTHH:MM}\nmetrics:backend:{name}\nmetrics:frontend:{name}")] end subgraph obs_backends["Observability Backends (external / optional)"] PROM["Prometheus"] GRAFANA["Grafana"] COLLECTOR["OTel Collector"] JAEGER["Jaeger / Tempo"] LOKI["Loki / ELK / Splunk"] end %% Ingestion path HA -->|"POST /logs (JSON)"| RI RI --> SI SI -->|"pipeline: INCR · ZADD · EXPIRE"| REDIS %% Metrics query path RM --> SM SM -->|"MGET · ZRANGE · INFO"| REDIS %% Health check RH -->|"PING"| REDIS %% Agent queries metrics service specialists -->|"GET /metrics/*"| RM %% Observability outputs RP -->|"scrape"| PROM PROM --> GRAFANA OT -->|"OTLP gRPC"| COLLECTOR COLLECTOR --> JAEGER JL -->|"stdout JSON"| LOKI %% Middleware wraps all routes middleware -.->|"wraps"| routers ``` ### 四大黄金信号覆盖范围 | 信号 | 测量方式 | | -------------- | -------------------------------------------------------------------------------------------------------------------------- | | **延迟 (Latency)** | P50 / P95 / P99 通过 `GET /metrics/response-times` 获取 · 直方图通过 `GET /prometheus/metrics` 获取 | | **流量 (Traffic)** | 每分钟 RPS 通过 `GET /metrics/rps` 获取 · Prometheus 中的 `http_requests_total` 计数器 | | **错误 (Errors)** | 错误计数 + 错误率 (%) 通过 `GET /metrics/overview` 获取 · Prometheus 中的 `http_requests_total{status="5xx"}` | | **饱和度 (Saturation)** | Redis 内存、客户端数、拒绝连接数通过 `GET /metrics/saturation` 获取 · Prometheus 中的 `http_requests_inprogress` 仪表盘 | ## 模块 ### `Incident-Response-Agent` 多智能体 AI 副驾驶,用于分析四大黄金信号并生成结构化的 `IncidentReport`,其中包含诊断和修复建议。旨在降低待命工程师的 MTTD 和 MTTR。 **技术栈:** Python · FastAPI · Anthropic SDK · httpx #### 多智能体设计 | 角色 | 描述 | | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | | **编排器** | 通过 `asyncio.gather` 并行运行所有四个专家智能体,然后再次调用 Claude 将发现综合成最终报告 | | **延迟专家** | 调用 `GET /metrics/response-times` · 检测 P95 > 500 ms(警告)或 P99 > 1000 ms(严重) | | **错误专家** | 调用 `GET /metrics/overview` + `GET /metrics/status-codes` · 检测 5xx 错误率 > 5 %(警告)或 > 10 %(严重) | | **饱和度专家** | 调用 `GET /metrics/saturation` · 检测 Redis 内存 > 80 % 或拒绝连接数 > 0 | | **流量专家** | 调用 `GET /metrics/rps` + `GET /metrics/backends` · 检测 RPS 降至 0 或意外的流量激增 | 每个专家运行一个 **Claude 工具使用循环**(`claude-sonnet-4-6`):模型通过工具调用请求数据,接收指标 JSON,并返回一个结构化的 `SpecialistFinding`。 #### API | 方法 | 端点 | 描述 | | ------ | ---------- | ------------------------------------- | | `GET` | `/health` | 存活检查 | | `POST` | `/analyze` | 运行完整的多智能体分析周期 | #### `POST /analyze` 响应模式 ``` { "timestamp": "2026-05-09T23:00:00Z", "overall_severity": "ok | warning | critical", "title": "High 5xx Error Rate on api-backend", "diagnosis": "The error specialist detected a 5xx rate of 12%...", "recommendations": [ "Check api-backend application logs for stack traces", "Verify backend health check endpoints", "Consider rolling back the last deployment" ], "findings": [ { "specialist": "Latency", "severity": "ok", "summary": "Latency within normal bounds", "details": "P50=12ms, P95=45ms, P99=98ms — all below thresholds" }, ... ] } ``` #### 快速开始 **使用 Docker(推荐):** ``` # 1. 使用你的 Anthropic API key 创建 .env 文件 # (docker-compose 会自动加载它;该文件位于 .gitignore 中) echo "ANTHROPIC_API_KEY=sk-ant-..." > Incident-Response-Agent/.env # 2. 启动完整技术栈 (Redis + metrics service + agent) docker compose up --build # 3. 触发完整的 multi-agent 分析 curl -X POST http://localhost:8001/analyze | jq ``` **不使用 Docker:** ``` cd Incident-Response-Agent python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt # 复制并设置你的 API key cp .env.example .env # 编辑 .env:设置 ANTHROPIC_API_KEY 和 METRICS_API_URL=http://localhost:8000 uvicorn app.main:app --reload --port 8001 ``` #### 运行测试 ``` cd Incident-Response-Agent python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt pytest -v ``` #### 安全测试 **SAST — Bandit**(静态分析,无需运行服务): ``` cd Incident-Response-Agent pip install bandit bandit -r app ``` **DAST — OWASP ZAP**(动态分析,需要 Docker 和运行中的技术栈): ``` # 1. 启动技术栈 docker compose up --build -d # 2. 针对 agent 的 OpenAPI spec 运行 ZAP API 扫描 docker run --rm --network host \ -v /tmp/zap:/zap/wrk \ ghcr.io/zaproxy/zaproxy:stable \ zap-api-scan.py \ -t http://localhost:8001/openapi.json \ -f openapi \ -r /zap/wrk/zap-report-agent.html \ -J /zap/wrk/zap-report-agent.json \ -I # 3. 停止技术栈 docker compose down ``` HTML 和 JSON 报告保存在 `/tmp/zap/`。 #### 异常阈值(可通过环境变量配置) | 变量 | 默认值 | 触发条件 | | ------------------------------ | ------- | ---------------------------------------- | | `LATENCY_P95_THRESHOLD_MS` | `500` | 当 P95 超过此值时发出警告 | | `LATENCY_P99_THRESHOLD_MS` | `1000` | 当 P99 超过此值时发出严重警报 | | `ERROR_RATE_5XX_THRESHOLD_PCT` | `5.0` | 当 5xx 错误率超过此值时发出警告 | | `ERROR_RATE_4XX_THRESHOLD_PCT` | `20.0` | 当 4xx 错误率超过此值时发出警告 | | `MEMORY_USAGE_THRESHOLD_PCT` | `80.0` | 当 Redis 内存超过此百分比时发出警告 | ### `Log-Ingestion-and-Metrics` 摄取 HAProxy 日志并通过 Redis 暴露聚合指标的 FastAPI 服务。作为 Agentic AI 流水线使用的可观测性数据层。 **技术栈:** Python · FastAPI · redis-py (asyncio) · Pydantic v2 · OpenTelemetry · Prometheus #### API | 方法 | 端点 | 描述 | | ------ | ------------------------- | -------------------------------------------------------- | | `GET` | `/health` | 存活检查 (API + Redis) | | `POST` | `/logs` | 摄取一条 HAProxy 日志条目 | | `GET` | `/metrics/overview` | 总请求数、错误计数和错误率 (4xx/5xx %) | | `GET` | `/metrics/status-codes` | 按 HTTP 状态码统计的请求计数 | | `GET` | `/metrics/backends` | 按 HAProxy 后端统计的请求计数 (流量) | | `GET` | `/metrics/frontends` | 按 HAProxy 前端统计的请求计数 (流量) | | `GET` | `/metrics/response-times` | 延迟百分位数:P50, P95, P99 | | `GET` | `/metrics/rps` | 过去 N 分钟内每分钟的请求数 (流量) | | `GET` | `/metrics/saturation` | Redis 内存、已连接/已阻塞客户端数、拒绝连接数 | | `GET` | `/prometheus/metrics` | Prometheus 抓取端点 | #### 收集的指标 | 键模式 | 描述 | | -------------------------------- | -------------------------------------- | | `metrics:requests:total` | 摄取的总日志条目数 | | `metrics:status:{code}` | 按 HTTP 状态码统计的计数 | | `metrics:backend:{name}` | 按 HAProxy 后端统计的计数 | | `metrics:frontend:{name}` | 按 HAProxy 前端统计的计数 | | `metrics:errors:4xx` / `5xx` | 错误计数器 | | `metrics:response_times` | 用于计算 P50/P95/P99 的有序集合 | | `metrics:rps:{YYYY-MM-DDTHH:MM}` | 每分钟请求桶 (TTL 2h) | #### 快速开始 **使用 Docker(推荐):** ``` docker compose up --build ``` API 地址:`http://localhost:8000` · 文档地址:`http://localhost:8000/docs` **停止:** ``` # 停止容器(保留 Redis 数据卷) docker compose down # 停止并删除数据卷 docker compose down -v ``` **不使用 Docker:** ``` # 安装依赖 pip install -r Log-Ingestion-and-Metrics/requirements.txt # 启动 Redis (必需) redis-cli ping # 运行服务 uvicorn app.main:app --reload --port 8000 ``` #### 运行测试 ``` cd Log-Ingestion-and-Metrics # 创建并激活虚拟环境 python3 -m venv .venv source .venv/bin/activate # 安装依赖 pip install -r requirements.txt # 运行所有测试 pytest # 运行特定测试文件 pytest tests/test_ingest.py -v # 运行特定测试 pytest tests/test_ingest.py::test_ingest_returns_202 -v ``` #### 安全测试 **SAST — Bandit**(静态分析,无需运行服务): ``` cd Log-Ingestion-and-Metrics pip install bandit bandit -r app ``` **DAST — OWASP ZAP**(动态分析,需要 Docker 和运行中的服务): ``` # 1. 启动技术栈 docker compose up --build -d # 2. 针对 OpenAPI spec 运行 ZAP API 扫描 docker run --rm --network host \ -v /tmp/zap:/zap/wrk \ ghcr.io/zaproxy/zaproxy:stable \ zap-api-scan.py \ -t http://localhost:8000/openapi.json \ -f openapi \ -r /zap/wrk/zap-report-api.html \ -J /zap/wrk/zap-report-api.json \ -I # 3. 停止技术栈 docker compose down ``` HTML 和 JSON 报告保存在 `/tmp/zap/`。 #### 可观测性 该服务开箱即用地实现了三大可观测性支柱。 **日志 —— 结构化 JSON** 每个请求都以 JSON 格式记录到标准输出,包含以下字段: ``` { "timestamp": "2026-05-09T23:00:00.000Z", "level": "INFO", "logger": "app.access", "message": "http_request", "method": "POST", "path": "/logs", "status_code": 202, "duration_ms": 4.21, "request_id": "a1b2c3d4-..." } ``` 在请求头中传入 `X-Request-ID` 以在服务之间传播关联 ID。如果未提供,系统将自动生成一个并在响应中返回。 在本地开发中设置 `LOG_FORMAT=text` 以获取人类可读的输出。 **指标 —— Prometheus** Prometheus 指标通过 `GET /prometheus/metrics` 暴露。兼容任何标准抓取器(Prometheus, Grafana Agent, OpenTelemetry Collector)。 暴露的指标(黄金信号): | 指标 | 类型 | 描述 | | ------------------------------- | --------- | ------------------------------------- | | `http_requests_total` | 计数器 | 按方法、路径、状态统计的请求计数 | | `http_request_duration_seconds` | 直方图 | 延迟分布 (P50/P95/P99) | | `http_requests_inprogress` | 仪表盘 | 进行中的请求 (饱和度代理) | **追踪 —— OpenTelemetry** FastAPI 路由和 Redis 命令使用 OpenTelemetry span 自动插桩。 - **开发环境(默认):** 通过 `ConsoleSpanExporter` 将追踪打印到标准输出 - **生产环境:** 设置 `OTEL_EXPORTER_OTLP_ENDPOINT` 将追踪发送到任何兼容 OTLP 的后端(Jaeger, Tempo, Datadog 等) ``` # 示例:导出至本地 Jaeger 实例 OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4317 ``` #### 环境变量 | 变量 | 默认值 | 描述 | | ----------------------------- | ---------------------------- | ---------------------------------------- | | `REDIS_URL` | `redis://localhost:6379/0` | Redis 连接字符串 | | `RESPONSE_TIME_MAX_ENTRIES` | `100000` | 响应时间有序集合中的最大条目数 | | `LOG_LEVEL` | `info` | Uvicorn 日志级别 | | `LOG_FORMAT` | `json` | 日志输出格式:`json` 或 `text` | | `OTEL_SERVICE_NAME` | `log-ingestion-and-metrics` | 追踪中的服务名称 | | `OTEL_EXPORTER_OTLP_ENDPOINT` | _(空 — 控制台导出器)_ | 用于追踪导出的 OTLP gRPC 端点 | 复制 `.env.example` 到 `.env` 并根据需要进行调整。 ## 技术栈 项目中使用的所有技术、语言和库的完整列表。 ### 语言与运行时 | 技术 | 版本 | 用途 | | ------------------ | ------- | ---------------------------------- | | **Python** | 3.12 | 两个模块的主要开发语言 | | **Docker** | 24+ | 所有服务的容器运行时 | | **Docker Compose** | v2 | 多容器编排 | ### `Log-Ingestion-and-Metrics` —— 运行时依赖 | 库 | 版本 | 用途 | | ----------------------------------------- | ------- | ------------------------------------------------------------------------- | | **FastAPI** | ≥0.111 | 异步 Web 框架,生成 OpenAPI 文档 | | **Uvicorn** | ≥0.29 | ASGI 服务器(`[standard]` 附加组件:uvloop, websockets, watchfiles) | | **redis-py** (`redis[asyncio]`) | ≥5.0 | 异步 Redis 客户端(已弃用的 `aioredis` 包的继任者) | | **Pydantic** | ≥2.7 | 数据验证与序列化 (v2 API) | | **pydantic-settings** | ≥2.2 | 从环境变量 / `.env` 文件管理配置 | | **python-dotenv** | ≥1.0 | 被 pydantic-settings 使用的 `.env` 文件加载器 | | **python-json-logger** | ≥2.0.7 | 结构化 JSON 日志格式化器 (stdout) | | **prometheus-fastapi-instrumentator** | ≥6.1 | 在 `/prometheus/metrics` 自动为 FastAPI 配置 Prometheus 指标 | | **opentelemetry-sdk** | ≥1.20 | 用于分布式追踪的 OpenTelemetry 核心 SDK | | **opentelemetry-instrumentation-fastapi** | ≥0.41b0 | 使用 OTel span 自动为 FastAPI 路由插桩 | | **opentelemetry-instrumentation-redis** | ≥0.41b0 | 使用 OTel span 自动为 Redis 命令插桩 | ### `Log-Ingestion-and-Metrics` —— 开发与测试依赖 | 库 | 版本 | 用途 | | ------------------ | ------- | ------------------------------------------------------------------- | | **pytest** | ≥8.0 | 测试运行器 | | **pytest-asyncio** | ≥0.23 | 异步测试支持(`asyncio_mode = auto`) | | **httpx** | ≥0.27 | 测试套件通过 `ASGITransport` 使用的 HTTP 客户端 | | **fakeredis** | ≥2.23 | 内存中的 Redis 模拟;消除了测试中对真实 Redis 的需求 | ### `Incident-Response-Agent` —— 运行时依赖 | 库 | 版本 | 用途 | | --------------------- | ------- | ---------------------------------------------------------------------------- | | **FastAPI** | ≥0.111 | 异步 Web 框架,OpenAPI 文档 | | **Uvicorn** | ≥0.29 | ASGI 服务器 | | **anthropic** | ≥0.28 | 官方 Anthropic Python SDK — 异步客户端、工具使用循环、Claude API | | **httpx** | ≥0.27 | 用于调用 Log-Ingestion-and-Metrics API 的异步 HTTP 客户端 | | **Pydantic** | ≥2.7 | `IncidentReport` 和 `SpecialistFinding` 模型,请求/响应验证 | | **pydantic-settings** | ≥2.2.1 | 配置管理(阈值、模型名称、API 密钥) | ### `Incident-Response-Agent` —— 开发与测试依赖 | 库 | 版本 | 用途 | | ------------------ | ------- | ------------------------------------------ | | **pytest** | ≥8.0 | 测试运行器 | | **pytest-asyncio** | ≥0.23 | 异步测试支持(`asyncio_mode = auto`) | ### 安全工具 | 工具 | 类型 | 用途 | | ------------- | ---- | --------------------------------------------------------------------- | | **Bandit** | SAST | 针对潜在 Python 安全问题的静态分析(使用 `bandit -r app` 运行) | | **OWASP ZAP** | DAST | 针对实时 OpenAPI 规范的动态 API 扫描(`zap-api-scan.py`) | ### 基础设施与开发者工具 | 工具 | 用途 | | --------------------- | ---------------------------------------------------- | | **Redis 7 (Alpine)** | 用于存储所有摄取指标内存数据存储 | | **Git + GitHub** | 版本控制和远程仓库 | | **GitHub CLI (`gh`)** | 从终端创建和管理仓库 | ## 事件场景 —— 副驾驶在行动 经过验证的场景,展示了 Agentic AI 副驾驶如何被用于端到端地检测、诊断和解决事件。每个场景都遵循**感知 → 推理 → 行动 → 学习**的循环,并生成一份结构化的复盘报告。 | ID | 事件 | 黄金信号 | 根本原因 | 行动 | MTTD | 治理 | | :------ | :------------------------------- | :--------------- | :--------------------------------------- | :------------------------------- | :------- | :--------- | | INC-001 | P99 = 1.800ms + 5xx 激增 | 延迟 + 错误 | 部署回退 | 回滚 | ~1h | HITL | | INC-002 | Redis 内存达 90% | 饱和度 | 无限制计数器 + `noeviction` 策略 | `maxmemory-policy → allkeys-lru` | ~分钟 | HITL | | INC-003 | `/api/checkout` 上 25% 的 4xx 错误 | 错误 | Auth 服务部署破坏了 JWT 验证 | 回滚 | ~2h | HITL | | INC-004 | RPS = 0 持续 5 分钟 (全面中断) | 流量 | HAProxy 进程意外崩溃 | 重启 HAProxy | ~5分钟 | HITL | ### INC-001 —— P99 严重 + 5xx 激增(部署回退) **信号:** P99 延迟达到 1,800ms(阈值:1,000ms)+ 不断上升的 5xx 错误率。 **诊断:** 部署引发了性能回退。HAProxy 对后端请求的级联超时,产生了 503/504 错误。 **解决:** 回滚到之前的版本。检测后约 15 分钟内恢复。 **复盘:** [`docs/post-mortems/2026-05-10-p99-5xx-backend-deploy-regression.md`](docs/post-mortems/2026-05-10-p99-5xx-backend-deploy-regression.md) ### INC-002 —— Redis 饱和(90% 内存 + noeviction) **信号:** Redis 内存达 90%,饱和度警报触发。 **诊断:** 无 TTL 的指标计数器(`metrics:status:{code}`, `metrics:backend:{name}` 等)无限积累。`noeviction` 策略意味着下一批写入将触发 `OOM command not allowed`,从而停止所有日志摄取。 **解决:** 将 `maxmemory-policy` 从 `noeviction` 更改为 `allkeys-lru`。结构性修复(为计数器添加 TTL)被标记为后续跟进项。 **复盘:** [`docs/post-mortems/2026-05-10-redis-saturation-noeviction-oom.md`](docs/post-mortems/2026-05-10-redis-saturation-noeviction-oom.md) ### INC-003 —— `/api/checkout` 上的 401 未授权(Auth 服务回退) **信号:** `POST /api/checkout` 上的 4xx 错误率达到 25%(阈值:20%),主要为 401 状态码。 **诊断:** Auth 服务上的部署引入了 JWT 验证回退。有效的 token 被拒绝,阻塞了结账这一关键用户旅程约 2 小时才被检测到。 **解决:** 在确认没有涉及密钥轮换或数据库迁移后,回滚了 Auth 服务的部署。检测后约 15 分钟内恢复。 **复盘:** [`docs/post-mortems/2026-05-10-401-checkout-auth-service-regression.md`](docs/post-mortems/2026-05-10-401-checkout-auth-service-regression.md) ### INC-004 —— 全面中断(HAProxy 宕机,RPS = 0) **信号:** RPS 降至零超过 5 分钟,且没有正在进行的部署 —— 可能发生全面中断。 **诊断:** 对摄取 API 的健康检查响应正常,排除了应用程序崩溃的可能性,并指向了上游原因。HAProxy 进程已被确认停止。没有关于部署或人工干预的通报。 **解决:** 在收集崩溃证据(日志、dmesg)后重启 HAProxy。流量在 5 秒内恢复。崩溃的根本原因(OOM、外部信号或 bug)被标记为后续调查项。 **复盘:** [`docs/post-mortems/2026-05-10-rps-zero-haproxy-down-outage.md`](docs/post-mortems/2026-05-10-rps-zero-haproxy-down-outage.md) ## 研究背景 | | | | --------------- | ------------------------------------------------------------------ | | **机构** | Unisinos — Universidade do Vale do Rio dos Sinos | | **项目** | PPGCA — Pós-Graduação em Computação Aplicada | | **主题** | Agentic AI 作为事件响应中降低 MTTD/MTTR 的副驾驶 | | **领域** | SRE · AIOps · NOC · LLM · 多智能体系统 | ## 许可证 本项目仅供学术研究目的使用。
(porta 8000) participant DB as 🗄️ Redis
(Banco de Métricas) actor ENG as 👩💻 Engenheiro On-call participant ORC as 🎯 Orquestrador
(Agente IA) participant CL as 🧠 Claude
(LLM da Anthropic) rect rgb(220, 240, 255) Note over HA,DB: FASE 1 — Coleta contínua de dados (acontece o tempo todo) HA ->> API: Envia log de cada requisição HTTP recebida API ->> DB: Atualiza contadores de erros, latência e tráfego Note over DB: Métricas acumuladas em tempo real end rect rgb(220, 255, 220) Note over ENG,CL: FASE 2 — Análise com IA (disparada pelo engenheiro) ENG ->> ORC: POST /analyze — "Analise o estado do sistema agora" par 4 especialistas trabalham ao mesmo tempo ⚡ ORC ->>+ CL: Especialista de Latência consulta P50/P95/P99 DB -->> CL: dados de tempo de resposta CL -->>- ORC: "P99 = 1.500ms — CRÍTICO (limite: 1.000ms)" and ORC ->>+ CL: Especialista de Erros consulta taxas 4xx/5xx DB -->> CL: dados de erros HTTP CL -->>- ORC: "Taxa 5xx = 12% — CRÍTICO (limite: 5%)" and ORC ->>+ CL: Especialista de Saturação consulta uso de memória DB -->> CL: dados de memória e conexões Redis CL -->>- ORC: "Memória em 45%, sem conexões rejeitadas — OK" and ORC ->>+ CL: Especialista de Tráfego consulta requisições/minuto DB -->> CL: histórico de RPS dos últimos 10 minutos CL -->>- ORC: "RPS caiu a zero há 6 minutos — CRÍTICO (possível outage)" end ORC ->>+ CL: "3 de 4 especialistas reportaram CRÍTICO. Sintetize o diagnóstico." CL -->>- ORC: Título · Diagnóstico · Recomendações priorizadas ORC -->> ENG: 📋 Relatório de Incidente completo Note over ENG: Diagnóstico em ~10 segundos
em vez de minutos ou horas end ``` ## 架构 ### 系统概述 ``` flowchart LR HA["HAProxy\nLoad Balancer"] ENG(["Engenheiro\nOn-call"]) subgraph PLATFORM["Backend — AgenticAI · Incident Response"] subgraph INGESTION["Log Ingestion & Metrics · :8000"] LOGS["POST /logs"] MET["GET /metrics/*"] PROMED["GET /prometheus"] end REDIS[("Redis :6379\nP50·P95·P99\nRPS · errors")] subgraph OBS["Observability"] PROM["Prometheus"] GRAF["Grafana"] JAEG["Jaeger · Loki"] end subgraph AGENT["Incident Response Agent · :8001"] ORCH["Orchestrator\nasyncio.gather"] LAT["Latency\nP50/P95/P99"] ERR["Errors\n4xx / 5xx"] SAT["Saturation\nRedis memory"] TRF["Traffic\nRPS drops"] end CLAUDE["Claude API\nclaude-sonnet-4-6\nTool-use Loop"] REPORT[/"📋 IncidentReport"/] PM[["Post-mortems\nINC-001 · INC-002\nINC-003 · INC-004"]] end HA -->|"① POST /logs"| LOGS LOGS -->|"② persiste"| REDIS REDIS --> MET PROMED -.->|"③ scrape"| PROM PROM --> GRAF & JAEG ENG -->|"④ POST /analyze"| ORCH ORCH -->|"⑤ spawn parallel"| LAT & ERR & SAT & TRF LAT & ERR & SAT & TRF -->|"⑥ GET /metrics/*"| MET LAT & ERR & SAT & TRF <-->|"⑦ tool-use loop"| CLAUDE LAT & ERR & SAT & TRF -->|"⑧ findings"| ORCH ORCH -->|"⑨ síntese final"| REPORT REPORT --> ENG & PM ``` ### 内部架构 ``` flowchart TB subgraph sources["Log Sources"] HA["HAProxy / Load Balancer"] end subgraph compose["Docker Compose"] subgraph agent["Incident-Response-Agent · FastAPI :8001"] direction TB ORCH["Orchestrator\nasyncio.gather — runs specialists in parallel"] subgraph specialists["Specialist Agents (Claude claude-sonnet-4-6 + tool use)"] SLA["Latency\nP50 · P95 · P99"] SEA["Errors\n4xx / 5xx rates"] SSA["Saturation\nRedis resources"] STA["Traffic\nRPS / backends"] end ORCH -->|"spawn"| specialists specialists -->|"SpecialistFinding"| ORCH end subgraph service["Log-Ingestion-and-Metrics · FastAPI :8000"] direction TB subgraph middleware["Middleware"] RLM["RequestLoggingMiddleware\nX-Request-ID · JSON access log"] SHM["SecurityHeadersMiddleware\nX-Content-Type-Options · CORP"] end subgraph routers["Routers"] RI["POST /logs"] RM["GET /metrics/*\noverview · status-codes · backends\nfrontends · response-times · rps · saturation"] RH["GET /health"] RP["GET /prometheus/metrics"] end subgraph services["Services"] SI["ingestion.py\nprocess_log()"] SM["metrics.py\nget_overview() · get_saturation()\nget_response_time_percentiles()"] end subgraph observability["Observability"] OT["OpenTelemetry SDK\nFastAPI + Redis auto-instrumentation"] PI["prometheus-fastapi-instrumentator\nLatency · Traffic · Errors · Saturation"] JL["python-json-logger\nStructured JSON stdout"] end end REDIS[("Redis :6379\n─────────────────\nmetrics:requests:total\nmetrics:status:{code}\nmetrics:errors:4xx / 5xx\nmetrics:response_times ← P50/P95/P99\nmetrics:rps:{YYYY-MM-DDTHH:MM}\nmetrics:backend:{name}\nmetrics:frontend:{name}")] end subgraph obs_backends["Observability Backends (external / optional)"] PROM["Prometheus"] GRAFANA["Grafana"] COLLECTOR["OTel Collector"] JAEGER["Jaeger / Tempo"] LOKI["Loki / ELK / Splunk"] end %% Ingestion path HA -->|"POST /logs (JSON)"| RI RI --> SI SI -->|"pipeline: INCR · ZADD · EXPIRE"| REDIS %% Metrics query path RM --> SM SM -->|"MGET · ZRANGE · INFO"| REDIS %% Health check RH -->|"PING"| REDIS %% Agent queries metrics service specialists -->|"GET /metrics/*"| RM %% Observability outputs RP -->|"scrape"| PROM PROM --> GRAFANA OT -->|"OTLP gRPC"| COLLECTOR COLLECTOR --> JAEGER JL -->|"stdout JSON"| LOKI %% Middleware wraps all routes middleware -.->|"wraps"| routers ``` ### 四大黄金信号覆盖范围 | 信号 | 测量方式 | | -------------- | -------------------------------------------------------------------------------------------------------------------------- | | **延迟 (Latency)** | P50 / P95 / P99 通过 `GET /metrics/response-times` 获取 · 直方图通过 `GET /prometheus/metrics` 获取 | | **流量 (Traffic)** | 每分钟 RPS 通过 `GET /metrics/rps` 获取 · Prometheus 中的 `http_requests_total` 计数器 | | **错误 (Errors)** | 错误计数 + 错误率 (%) 通过 `GET /metrics/overview` 获取 · Prometheus 中的 `http_requests_total{status="5xx"}` | | **饱和度 (Saturation)** | Redis 内存、客户端数、拒绝连接数通过 `GET /metrics/saturation` 获取 · Prometheus 中的 `http_requests_inprogress` 仪表盘 | ## 模块 ### `Incident-Response-Agent` 多智能体 AI 副驾驶,用于分析四大黄金信号并生成结构化的 `IncidentReport`,其中包含诊断和修复建议。旨在降低待命工程师的 MTTD 和 MTTR。 **技术栈:** Python · FastAPI · Anthropic SDK · httpx #### 多智能体设计 | 角色 | 描述 | | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | | **编排器** | 通过 `asyncio.gather` 并行运行所有四个专家智能体,然后再次调用 Claude 将发现综合成最终报告 | | **延迟专家** | 调用 `GET /metrics/response-times` · 检测 P95 > 500 ms(警告)或 P99 > 1000 ms(严重) | | **错误专家** | 调用 `GET /metrics/overview` + `GET /metrics/status-codes` · 检测 5xx 错误率 > 5 %(警告)或 > 10 %(严重) | | **饱和度专家** | 调用 `GET /metrics/saturation` · 检测 Redis 内存 > 80 % 或拒绝连接数 > 0 | | **流量专家** | 调用 `GET /metrics/rps` + `GET /metrics/backends` · 检测 RPS 降至 0 或意外的流量激增 | 每个专家运行一个 **Claude 工具使用循环**(`claude-sonnet-4-6`):模型通过工具调用请求数据,接收指标 JSON,并返回一个结构化的 `SpecialistFinding`。 #### API | 方法 | 端点 | 描述 | | ------ | ---------- | ------------------------------------- | | `GET` | `/health` | 存活检查 | | `POST` | `/analyze` | 运行完整的多智能体分析周期 | #### `POST /analyze` 响应模式 ``` { "timestamp": "2026-05-09T23:00:00Z", "overall_severity": "ok | warning | critical", "title": "High 5xx Error Rate on api-backend", "diagnosis": "The error specialist detected a 5xx rate of 12%...", "recommendations": [ "Check api-backend application logs for stack traces", "Verify backend health check endpoints", "Consider rolling back the last deployment" ], "findings": [ { "specialist": "Latency", "severity": "ok", "summary": "Latency within normal bounds", "details": "P50=12ms, P95=45ms, P99=98ms — all below thresholds" }, ... ] } ``` #### 快速开始 **使用 Docker(推荐):** ``` # 1. 使用你的 Anthropic API key 创建 .env 文件 # (docker-compose 会自动加载它;该文件位于 .gitignore 中) echo "ANTHROPIC_API_KEY=sk-ant-..." > Incident-Response-Agent/.env # 2. 启动完整技术栈 (Redis + metrics service + agent) docker compose up --build # 3. 触发完整的 multi-agent 分析 curl -X POST http://localhost:8001/analyze | jq ``` **不使用 Docker:** ``` cd Incident-Response-Agent python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt # 复制并设置你的 API key cp .env.example .env # 编辑 .env:设置 ANTHROPIC_API_KEY 和 METRICS_API_URL=http://localhost:8000 uvicorn app.main:app --reload --port 8001 ``` #### 运行测试 ``` cd Incident-Response-Agent python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt pytest -v ``` #### 安全测试 **SAST — Bandit**(静态分析,无需运行服务): ``` cd Incident-Response-Agent pip install bandit bandit -r app ``` **DAST — OWASP ZAP**(动态分析,需要 Docker 和运行中的技术栈): ``` # 1. 启动技术栈 docker compose up --build -d # 2. 针对 agent 的 OpenAPI spec 运行 ZAP API 扫描 docker run --rm --network host \ -v /tmp/zap:/zap/wrk \ ghcr.io/zaproxy/zaproxy:stable \ zap-api-scan.py \ -t http://localhost:8001/openapi.json \ -f openapi \ -r /zap/wrk/zap-report-agent.html \ -J /zap/wrk/zap-report-agent.json \ -I # 3. 停止技术栈 docker compose down ``` HTML 和 JSON 报告保存在 `/tmp/zap/`。 #### 异常阈值(可通过环境变量配置) | 变量 | 默认值 | 触发条件 | | ------------------------------ | ------- | ---------------------------------------- | | `LATENCY_P95_THRESHOLD_MS` | `500` | 当 P95 超过此值时发出警告 | | `LATENCY_P99_THRESHOLD_MS` | `1000` | 当 P99 超过此值时发出严重警报 | | `ERROR_RATE_5XX_THRESHOLD_PCT` | `5.0` | 当 5xx 错误率超过此值时发出警告 | | `ERROR_RATE_4XX_THRESHOLD_PCT` | `20.0` | 当 4xx 错误率超过此值时发出警告 | | `MEMORY_USAGE_THRESHOLD_PCT` | `80.0` | 当 Redis 内存超过此百分比时发出警告 | ### `Log-Ingestion-and-Metrics` 摄取 HAProxy 日志并通过 Redis 暴露聚合指标的 FastAPI 服务。作为 Agentic AI 流水线使用的可观测性数据层。 **技术栈:** Python · FastAPI · redis-py (asyncio) · Pydantic v2 · OpenTelemetry · Prometheus #### API | 方法 | 端点 | 描述 | | ------ | ------------------------- | -------------------------------------------------------- | | `GET` | `/health` | 存活检查 (API + Redis) | | `POST` | `/logs` | 摄取一条 HAProxy 日志条目 | | `GET` | `/metrics/overview` | 总请求数、错误计数和错误率 (4xx/5xx %) | | `GET` | `/metrics/status-codes` | 按 HTTP 状态码统计的请求计数 | | `GET` | `/metrics/backends` | 按 HAProxy 后端统计的请求计数 (流量) | | `GET` | `/metrics/frontends` | 按 HAProxy 前端统计的请求计数 (流量) | | `GET` | `/metrics/response-times` | 延迟百分位数:P50, P95, P99 | | `GET` | `/metrics/rps` | 过去 N 分钟内每分钟的请求数 (流量) | | `GET` | `/metrics/saturation` | Redis 内存、已连接/已阻塞客户端数、拒绝连接数 | | `GET` | `/prometheus/metrics` | Prometheus 抓取端点 | #### 收集的指标 | 键模式 | 描述 | | -------------------------------- | -------------------------------------- | | `metrics:requests:total` | 摄取的总日志条目数 | | `metrics:status:{code}` | 按 HTTP 状态码统计的计数 | | `metrics:backend:{name}` | 按 HAProxy 后端统计的计数 | | `metrics:frontend:{name}` | 按 HAProxy 前端统计的计数 | | `metrics:errors:4xx` / `5xx` | 错误计数器 | | `metrics:response_times` | 用于计算 P50/P95/P99 的有序集合 | | `metrics:rps:{YYYY-MM-DDTHH:MM}` | 每分钟请求桶 (TTL 2h) | #### 快速开始 **使用 Docker(推荐):** ``` docker compose up --build ``` API 地址:`http://localhost:8000` · 文档地址:`http://localhost:8000/docs` **停止:** ``` # 停止容器(保留 Redis 数据卷) docker compose down # 停止并删除数据卷 docker compose down -v ``` **不使用 Docker:** ``` # 安装依赖 pip install -r Log-Ingestion-and-Metrics/requirements.txt # 启动 Redis (必需) redis-cli ping # 运行服务 uvicorn app.main:app --reload --port 8000 ``` #### 运行测试 ``` cd Log-Ingestion-and-Metrics # 创建并激活虚拟环境 python3 -m venv .venv source .venv/bin/activate # 安装依赖 pip install -r requirements.txt # 运行所有测试 pytest # 运行特定测试文件 pytest tests/test_ingest.py -v # 运行特定测试 pytest tests/test_ingest.py::test_ingest_returns_202 -v ``` #### 安全测试 **SAST — Bandit**(静态分析,无需运行服务): ``` cd Log-Ingestion-and-Metrics pip install bandit bandit -r app ``` **DAST — OWASP ZAP**(动态分析,需要 Docker 和运行中的服务): ``` # 1. 启动技术栈 docker compose up --build -d # 2. 针对 OpenAPI spec 运行 ZAP API 扫描 docker run --rm --network host \ -v /tmp/zap:/zap/wrk \ ghcr.io/zaproxy/zaproxy:stable \ zap-api-scan.py \ -t http://localhost:8000/openapi.json \ -f openapi \ -r /zap/wrk/zap-report-api.html \ -J /zap/wrk/zap-report-api.json \ -I # 3. 停止技术栈 docker compose down ``` HTML 和 JSON 报告保存在 `/tmp/zap/`。 #### 可观测性 该服务开箱即用地实现了三大可观测性支柱。 **日志 —— 结构化 JSON** 每个请求都以 JSON 格式记录到标准输出,包含以下字段: ``` { "timestamp": "2026-05-09T23:00:00.000Z", "level": "INFO", "logger": "app.access", "message": "http_request", "method": "POST", "path": "/logs", "status_code": 202, "duration_ms": 4.21, "request_id": "a1b2c3d4-..." } ``` 在请求头中传入 `X-Request-ID` 以在服务之间传播关联 ID。如果未提供,系统将自动生成一个并在响应中返回。 在本地开发中设置 `LOG_FORMAT=text` 以获取人类可读的输出。 **指标 —— Prometheus** Prometheus 指标通过 `GET /prometheus/metrics` 暴露。兼容任何标准抓取器(Prometheus, Grafana Agent, OpenTelemetry Collector)。 暴露的指标(黄金信号): | 指标 | 类型 | 描述 | | ------------------------------- | --------- | ------------------------------------- | | `http_requests_total` | 计数器 | 按方法、路径、状态统计的请求计数 | | `http_request_duration_seconds` | 直方图 | 延迟分布 (P50/P95/P99) | | `http_requests_inprogress` | 仪表盘 | 进行中的请求 (饱和度代理) | **追踪 —— OpenTelemetry** FastAPI 路由和 Redis 命令使用 OpenTelemetry span 自动插桩。 - **开发环境(默认):** 通过 `ConsoleSpanExporter` 将追踪打印到标准输出 - **生产环境:** 设置 `OTEL_EXPORTER_OTLP_ENDPOINT` 将追踪发送到任何兼容 OTLP 的后端(Jaeger, Tempo, Datadog 等) ``` # 示例:导出至本地 Jaeger 实例 OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4317 ``` #### 环境变量 | 变量 | 默认值 | 描述 | | ----------------------------- | ---------------------------- | ---------------------------------------- | | `REDIS_URL` | `redis://localhost:6379/0` | Redis 连接字符串 | | `RESPONSE_TIME_MAX_ENTRIES` | `100000` | 响应时间有序集合中的最大条目数 | | `LOG_LEVEL` | `info` | Uvicorn 日志级别 | | `LOG_FORMAT` | `json` | 日志输出格式:`json` 或 `text` | | `OTEL_SERVICE_NAME` | `log-ingestion-and-metrics` | 追踪中的服务名称 | | `OTEL_EXPORTER_OTLP_ENDPOINT` | _(空 — 控制台导出器)_ | 用于追踪导出的 OTLP gRPC 端点 | 复制 `.env.example` 到 `.env` 并根据需要进行调整。 ## 技术栈 项目中使用的所有技术、语言和库的完整列表。 ### 语言与运行时 | 技术 | 版本 | 用途 | | ------------------ | ------- | ---------------------------------- | | **Python** | 3.12 | 两个模块的主要开发语言 | | **Docker** | 24+ | 所有服务的容器运行时 | | **Docker Compose** | v2 | 多容器编排 | ### `Log-Ingestion-and-Metrics` —— 运行时依赖 | 库 | 版本 | 用途 | | ----------------------------------------- | ------- | ------------------------------------------------------------------------- | | **FastAPI** | ≥0.111 | 异步 Web 框架,生成 OpenAPI 文档 | | **Uvicorn** | ≥0.29 | ASGI 服务器(`[standard]` 附加组件:uvloop, websockets, watchfiles) | | **redis-py** (`redis[asyncio]`) | ≥5.0 | 异步 Redis 客户端(已弃用的 `aioredis` 包的继任者) | | **Pydantic** | ≥2.7 | 数据验证与序列化 (v2 API) | | **pydantic-settings** | ≥2.2 | 从环境变量 / `.env` 文件管理配置 | | **python-dotenv** | ≥1.0 | 被 pydantic-settings 使用的 `.env` 文件加载器 | | **python-json-logger** | ≥2.0.7 | 结构化 JSON 日志格式化器 (stdout) | | **prometheus-fastapi-instrumentator** | ≥6.1 | 在 `/prometheus/metrics` 自动为 FastAPI 配置 Prometheus 指标 | | **opentelemetry-sdk** | ≥1.20 | 用于分布式追踪的 OpenTelemetry 核心 SDK | | **opentelemetry-instrumentation-fastapi** | ≥0.41b0 | 使用 OTel span 自动为 FastAPI 路由插桩 | | **opentelemetry-instrumentation-redis** | ≥0.41b0 | 使用 OTel span 自动为 Redis 命令插桩 | ### `Log-Ingestion-and-Metrics` —— 开发与测试依赖 | 库 | 版本 | 用途 | | ------------------ | ------- | ------------------------------------------------------------------- | | **pytest** | ≥8.0 | 测试运行器 | | **pytest-asyncio** | ≥0.23 | 异步测试支持(`asyncio_mode = auto`) | | **httpx** | ≥0.27 | 测试套件通过 `ASGITransport` 使用的 HTTP 客户端 | | **fakeredis** | ≥2.23 | 内存中的 Redis 模拟;消除了测试中对真实 Redis 的需求 | ### `Incident-Response-Agent` —— 运行时依赖 | 库 | 版本 | 用途 | | --------------------- | ------- | ---------------------------------------------------------------------------- | | **FastAPI** | ≥0.111 | 异步 Web 框架,OpenAPI 文档 | | **Uvicorn** | ≥0.29 | ASGI 服务器 | | **anthropic** | ≥0.28 | 官方 Anthropic Python SDK — 异步客户端、工具使用循环、Claude API | | **httpx** | ≥0.27 | 用于调用 Log-Ingestion-and-Metrics API 的异步 HTTP 客户端 | | **Pydantic** | ≥2.7 | `IncidentReport` 和 `SpecialistFinding` 模型,请求/响应验证 | | **pydantic-settings** | ≥2.2.1 | 配置管理(阈值、模型名称、API 密钥) | ### `Incident-Response-Agent` —— 开发与测试依赖 | 库 | 版本 | 用途 | | ------------------ | ------- | ------------------------------------------ | | **pytest** | ≥8.0 | 测试运行器 | | **pytest-asyncio** | ≥0.23 | 异步测试支持(`asyncio_mode = auto`) | ### 安全工具 | 工具 | 类型 | 用途 | | ------------- | ---- | --------------------------------------------------------------------- | | **Bandit** | SAST | 针对潜在 Python 安全问题的静态分析(使用 `bandit -r app` 运行) | | **OWASP ZAP** | DAST | 针对实时 OpenAPI 规范的动态 API 扫描(`zap-api-scan.py`) | ### 基础设施与开发者工具 | 工具 | 用途 | | --------------------- | ---------------------------------------------------- | | **Redis 7 (Alpine)** | 用于存储所有摄取指标内存数据存储 | | **Git + GitHub** | 版本控制和远程仓库 | | **GitHub CLI (`gh`)** | 从终端创建和管理仓库 | ## 事件场景 —— 副驾驶在行动 经过验证的场景,展示了 Agentic AI 副驾驶如何被用于端到端地检测、诊断和解决事件。每个场景都遵循**感知 → 推理 → 行动 → 学习**的循环,并生成一份结构化的复盘报告。 | ID | 事件 | 黄金信号 | 根本原因 | 行动 | MTTD | 治理 | | :------ | :------------------------------- | :--------------- | :--------------------------------------- | :------------------------------- | :------- | :--------- | | INC-001 | P99 = 1.800ms + 5xx 激增 | 延迟 + 错误 | 部署回退 | 回滚 | ~1h | HITL | | INC-002 | Redis 内存达 90% | 饱和度 | 无限制计数器 + `noeviction` 策略 | `maxmemory-policy → allkeys-lru` | ~分钟 | HITL | | INC-003 | `/api/checkout` 上 25% 的 4xx 错误 | 错误 | Auth 服务部署破坏了 JWT 验证 | 回滚 | ~2h | HITL | | INC-004 | RPS = 0 持续 5 分钟 (全面中断) | 流量 | HAProxy 进程意外崩溃 | 重启 HAProxy | ~5分钟 | HITL | ### INC-001 —— P99 严重 + 5xx 激增(部署回退) **信号:** P99 延迟达到 1,800ms(阈值:1,000ms)+ 不断上升的 5xx 错误率。 **诊断:** 部署引发了性能回退。HAProxy 对后端请求的级联超时,产生了 503/504 错误。 **解决:** 回滚到之前的版本。检测后约 15 分钟内恢复。 **复盘:** [`docs/post-mortems/2026-05-10-p99-5xx-backend-deploy-regression.md`](docs/post-mortems/2026-05-10-p99-5xx-backend-deploy-regression.md) ### INC-002 —— Redis 饱和(90% 内存 + noeviction) **信号:** Redis 内存达 90%,饱和度警报触发。 **诊断:** 无 TTL 的指标计数器(`metrics:status:{code}`, `metrics:backend:{name}` 等)无限积累。`noeviction` 策略意味着下一批写入将触发 `OOM command not allowed`,从而停止所有日志摄取。 **解决:** 将 `maxmemory-policy` 从 `noeviction` 更改为 `allkeys-lru`。结构性修复(为计数器添加 TTL)被标记为后续跟进项。 **复盘:** [`docs/post-mortems/2026-05-10-redis-saturation-noeviction-oom.md`](docs/post-mortems/2026-05-10-redis-saturation-noeviction-oom.md) ### INC-003 —— `/api/checkout` 上的 401 未授权(Auth 服务回退) **信号:** `POST /api/checkout` 上的 4xx 错误率达到 25%(阈值:20%),主要为 401 状态码。 **诊断:** Auth 服务上的部署引入了 JWT 验证回退。有效的 token 被拒绝,阻塞了结账这一关键用户旅程约 2 小时才被检测到。 **解决:** 在确认没有涉及密钥轮换或数据库迁移后,回滚了 Auth 服务的部署。检测后约 15 分钟内恢复。 **复盘:** [`docs/post-mortems/2026-05-10-401-checkout-auth-service-regression.md`](docs/post-mortems/2026-05-10-401-checkout-auth-service-regression.md) ### INC-004 —— 全面中断(HAProxy 宕机,RPS = 0) **信号:** RPS 降至零超过 5 分钟,且没有正在进行的部署 —— 可能发生全面中断。 **诊断:** 对摄取 API 的健康检查响应正常,排除了应用程序崩溃的可能性,并指向了上游原因。HAProxy 进程已被确认停止。没有关于部署或人工干预的通报。 **解决:** 在收集崩溃证据(日志、dmesg)后重启 HAProxy。流量在 5 秒内恢复。崩溃的根本原因(OOM、外部信号或 bug)被标记为后续调查项。 **复盘:** [`docs/post-mortems/2026-05-10-rps-zero-haproxy-down-outage.md`](docs/post-mortems/2026-05-10-rps-zero-haproxy-down-outage.md) ## 研究背景 | | | | --------------- | ------------------------------------------------------------------ | | **机构** | Unisinos — Universidade do Vale do Rio dos Sinos | | **项目** | PPGCA — Pós-Graduação em Computação Aplicada | | **主题** | Agentic AI 作为事件响应中降低 MTTD/MTTR 的副驾驶 | | **领域** | SRE · AIOps · NOC · LLM · 多智能体系统 | ## 许可证 本项目仅供学术研究目的使用。
标签:AI Copilot, AIOps, Anthropic, CIS基准, Claude, CVE检测, DLL 劫持, HAProxy, HTTP错误率, IT事故响应, IT监控, IT运维, MTTD, MTTR, Redis, Socks5代理, 人工智能, 命令控制, 大语言模型, 学术研究, 实时指标, 平均恢复时间, 平均检测时间, 序列图, 搜索引擎查询, 数据采集, 用户代理, 用户模式Hook绕过, 硕士论文, 系统延迟, 系统架构, 自定义请求头, 请求拦截, 负载均衡, 运维大模型, 逆向工具