MAYANKKS13/Incident-Response-System

GitHub: MAYANKKS13/Incident-Response-System

这是一个利用AI和自动化工具实现事件响应自愈的演示系统。

Stars: 0 | Forks: 0

# Grab 自愈式基础设施 一套自愈式事件处理流程:**Prometheus** 检测**两个不同服务**(出行 + 外卖)的真实指标异常 → **Alertmanager** 发送 HMAC/Bearer 签名的 Webhook → **Node.js 后端**基于 **pgvector** 运行 RAG 驱动的推理 → **Angular UI** 自动流式展示推理日志 → 用户批准后,**Ansible playbook** 针对受影响的服务运行(使用警报的 `app` 标签选择正确的 URL)进行修复 → 已解决的事件会自动嵌入回知识库。 围绕此核心循环,UI 还支持:**服务/类别/领域事件过滤器**、**单个事件评论**、**带必填描述的手动解决**、**拒绝 AI 选择 → 资深 SRE 审核 → 拒绝反馈回知识库**、**与 Agent 多轮对话寻求替代修复方案**、**带图表的管理者可读 PDF 报告**,以及**基于 Elasticsearch 的用户搜索**(与 AI 的 pgvector 检索并存)。 无任何模拟。真实的 Prometheus 抓取两个真实的受害者服务,针对真实指标变化触发真实警报,后端确实调用 AWS Bedrock 进行检索和推理,Ansible playbook 确实执行并在正确服务上调用恢复端点。 ## 两个受害者服务 | 服务 | 端口 | 目录 | 领域 | 可见 UI | |---|---|---|---|---| | **rides-app** | 4000 | [victim-app/](victim-app/) | 网约车 — 司机、订单、动态定价 | 司机网格 · 动态定价仪表 · 请求流 | | **food-app** | 4001 | [food-app/](food-app/) | GrabFood 流程 — 餐厅、订单看板、送达时间预估 | 订单看板 · 队列深度条 · 餐厅磁贴 | 两者均在 `/metrics` 暴露带有 `app` 标签(`rides` 或 `food`)的 Prometheus 指标,在 `/admin/chaos/{...}/reset` 有相同的混沌测试路径,并在 `/` 有一个状态页面。 ## 架构 ``` ┌──────────────┐ ┌──────────────┐ alert fires ┌──────────────┐ │ rides-app │ ─┐ │ Prometheus │ ──────────────► │ Alertmanager │ │ (4000) │ │ scrape every 5s │ + rules.yml │ │ │ └──────────────┘ ├───────────────────►│ (by app:N) │ └──────────────┘ ┌──────────────┐ │ └──────────────┘ │ │ food-app │ ─┘ │ │ (4001) │ ▼ └──────────────┘ ┌──────────────────────────────────┐ ▲ │ Node.js backend │ │ ansible playbook hits the right URL │ /api/alerts → reasoning pipe │ │ based on alert's app label │ pgvector search → Bedrock │ ┌──────────────┐ POST /jobs/launch │ WS broadcast │ │ remediator │ ◄────── extraVars.victim_app_url ────────│ /api/solutions/apply │ │ (ansible-core)│ POST /callback ──────────────────────► │ (filters playbooks by app) │ └──────────────┘ └──────────────────────────────────┘ │ ▲ WebSocket │ │ HTTP ▼ │ ┌──────────────────────┐ │ Angular UI (4200) │ │ Service/Category/ │ │ Domain filters, │ │ reasoning, Apply │ └──────────────────────┘ ``` ## 前置条件 - **Docker Desktop** (Windows/Mac) 或 Docker Engine + Compose v2 (Linux) - **Node.js 20+** 和 npm - **AWS Bedrock 凭证** (可选 — 缺少时后端将在模拟模式下运行,使用模拟的推理日志) ## 快速启动 (3 个终端) ### 终端 A — Docker 栈 (postgres, rides-app, food-app, prometheus, alertmanager, grafana, remediator, elasticsearch) ``` cd path/to/grab docker compose up -d --build docker compose ps # confirm 8 containers running (rides-app + food-app + elasticsearch + 5 others) ``` ### 终端 B — 后端 (Node + WebSocket) ``` cd server npm install # first time only cp .env.example .env # first time only — then edit (see "Environment" below) node src/index.js ``` 你应该会看到: ``` [knowledge] pgvector backend ready: 12 docs, seeded=true (with AWS credentials) — or — [knowledge] DATABASE_URL set but AWS credentials missing — pgvector needs Bedrock embeddings, falling back to in-memory mock mode [server] listening on http://localhost:3000 [server] websocket on ws://localhost:3000/api/ws [server] LLM mode: LIVE (Bedrock: qwen.qwen3-235b-a22b-2507-v1:0) (or MOCK) ``` ### 终端 C — Angular 开发服务器 ``` cd Frontend npm install # first time only npm start ``` 等待 `✔ Compiled successfully`,然后打开 **http://localhost:4200**。 ## URL 参考 | URL | 显示内容 | |---|---| | http://localhost:4200/ai-monitor/live-alerts | **主 UI** — 按服务/类别/领域过滤的实时警报卡片、推理日志、应用/拒绝/聊天/标记解决 | | http://localhost:4200/ai-monitor/review-queue | **资深 SRE 审核队列** — 待处理的工程师拒绝项,批准后写入知识库 | | http://localhost:4200/ai-monitor/incident-report | **管理者可读 PDF 报告** — 基于图表的摘要(知识库、playbook、时间线)。打印 → 另存为 PDF。可通过已关闭事件中的“导出”访问。 | | http://localhost:4200/ai-monitor/closed-incidents | **历史事件** — 基于 Elasticsearch 的跨知识库搜索 | | http://localhost:3001/d/grab-self-healing | **Grafana 仪表盘** — 具有 `$app` 下拉菜单(全部 / rides / food);共享核心面板 + 每服务领域的行(登录:`admin` / `admin`) | | http://localhost:9090/alerts | **Prometheus 警报** — 核心和领域共 10 条规则,按 `app` 触发 | | http://localhost:9090/targets | Prometheus 目标 — 应显示 `rides-app`、`food-app` 和 `prometheus` 状态为 UP | | http://localhost:9093/#/alerts | **Alertmanager** — 正在路由的警报 | | http://localhost:9200/_cluster/health | **Elasticsearch** 集群健康状态(如果运行则为 green/yellow) | | http://localhost:4000/ | **出行受害者 UI** — 司机网格、动态定价仪表、请求流、混沌测试按钮 | | http://localhost:4001/ | **外卖受害者 UI** — 订单看板、队列深度条、餐厅磁贴、混沌测试按钮 | | http://localhost:4000/admin/status · http://localhost:4001/admin/status | 每个服务当前混沌测试开关状态 (JSON) | | http://localhost:4000/metrics · http://localhost:4001/metrics | 每个服务的原始 Prometheus 指标 | | http://localhost:3000/api/health | 后端健康状态(模式、知识库模式、WS 客户端数) | | http://localhost:3000/api/alerts | 后端已接收的警报列表 | | http://localhost:3000/api/search?q=cache | 真实的 ES 关键词搜索(跨知识库,如果 ES 禁用则返回 503) | | http://localhost:3000/api/review-queue?status=pending | 待处理的资深审核 | | http://localhost:5005/playbooks | 可用的 Ansible playbook | ## 触发事件 两个服务、十条警报规则、十一个 playbook。最简单的方法是使用 UI 内的按钮:打开实时警报页面,选择服务过滤器(全部 / 出行 / 外卖),然后点击 **触发 1 个事件** — 它将在所选应用上触发一个随机混沌测试场景。以下部分适用于手动 curl 触发,用于需要特定场景的情况。 混沌测试端点在两个应用中对于**共享**故障模式(延迟、错误率、数据库连接池耗尽、缓存未命中、内存泄漏)使用相同的名称。每个应用还额外具有**领域特定**的故障模式(出行应用的:司机供应 / 动态定价计算;外卖应用的:订单队列积压 / 餐厅超时 / 时间预估错误)。 ### 共享混沌测试 (适用于任一应用 — 替换端口) ``` # r-supply, category=domain) → restart-driver-supply.yml" – Here, "alert" is a command or term, "DriverSupplyEmpty" is a proper noun, class and category are technical. Keep them in English. Translate the arrows and the file name might be kept as is since it's a file. So: "→ 告警 DriverSupplyEmpty (class=driver-supply, category=domain) → restart-driver-supply.yml" curl -X POST http://localhost:4000/admin/chaos/db-pool-exhaust # rides curl -X POST http://localhost:4001/admin/chaos/db-pool-exhaust # food # 8. "Surge calc slowdown — /api/surge p95 > 1s" – "Surge calc" probably means surge calculation, so translate "slowdown" to "减速". Keep "/api/surge" as is. So: "Surge 计算减速 — /api/surge p95 > 1s" curl -X POST "http://localhost:4000/admin/chaos/latency?ms=1500" # rides curl -X POST "http://localhost:4001/admin/chaos/latency?ms=1500" # food # 9. "→ alert SurgeCalcSlow (class=surge-calc, category=domain) → fix-surge-calc.yml" – Similar to line 7: "→ 告警 SurgeCalcSlow (class=surge-calc, category=domain) → fix-surge-calc.yml" curl -X POST "http://localhost:4000/admin/chaos/error-rate?pct=40" # rides curl -X POST "http://localhost:4001/admin/chaos/error-rate?pct=40" # food # 10. "Order queue backlog — kitchen worker stalls, pending+cooking grows past 50" – Translate "backlog" to "积压", "stalls" to "停滞". So: "订单队列积压 — 厨房工作人员停滞,待处理+烹饪增长超过 50" curl -X POST http://localhost:4000/admin/chaos/cache-miss # rides curl -X POST http://localhost:4001/admin/chaos/cache-miss # food # 11. "→ alert OrderQueueBacklog (class=order-queue, category=domain) → restart-queue-worker.yml" – "→ 告警 OrderQueueBacklog (class=order-queue, category=domain) → restart-queue-worker.yml" curl -X POST http://localhost:4000/admin/chaos/memory-leak # rides curl -X POST http://localhost:4001/admin/chaos/memory-leak # food ``` 后台流量生成器在每个应用内运行,因此除非需要更快触发,否则不需要单独的请求循环。 ### 仅限出行应用的领域混沌测试 ``` # 12. "Restaurant upstream timeout — /api/restaurants returns 504s" – "上游超时", keep "/api/restaurants". So: "餐厅上游超时 — /api/restaurants 返回 504 错误" curl -X POST http://localhost:4000/admin/chaos/driver-supply # 13. "→ alert RestaurantUpstreamErrors (class=restaurant-upstream, category=domain) → failover-restaurant-upstream.yml" – "→ 告警 RestaurantUpstreamErrors (class=restaurant-upstream, category=domain) → failover-restaurant-upstream.yml" # 14. "Delivery ETA failures" – ETA is Estimated Time of Arrival, keep as is. So: "配送 ETA 失败" curl -X POST http://localhost:4000/admin/chaos/surge-calc # 15. "→ alert ETAServiceFailing (class=eta-service, category=domain) → restart-eta-service.yml" – "→ 告警 ETAServiceFailing (class=eta-service, category=domain) → restart-eta-service.yml" ``` ### 仅限外卖应用的领域混沌测试 ``` # 16. "or, via the backend (resets both in one call):" – Translate: "或者,通过后端(在一次调用中重置两者):" curl -X POST http://localhost:4001/admin/chaos/order-queue-backlog # Now, I need to ensure that I output exactly 16 lines, one per line, in the same order. So, I'll list them out. # Let me write the translations: curl -X POST http://localhost:4001/admin/chaos/restaurant-timeout # 1. DB 连接池耗尽 # 2. 高延迟 curl -X POST http://localhost:4001/admin/chaos/eta-errors # 3. 错误率飙升 ``` ### 重置 ``` curl -X POST http://localhost:4000/admin/chaos/reset # rides curl -X POST http://localhost:4001/admin/chaos/reset # food # 4. 缓存 miss 风暴 curl -X POST http://localhost:3000/api/demo/reset ``` ### 警报到 playbook 的映射 | 类 | 类别 | 应用 | Playbook | |---|---|---|---| | `latency` | 性能 | rides, food | `scale-latency.yml` (rides), `scale-latency-food.yml` (food) | | `errors` | 错误 | rides, food | `restart-service.yml` | | `database` | 基础设施 | rides, food | `restart-pool.yml` | | `cache` | 基础设施 | rides, food | `clear-cache.yml` (rides), `clear-cache-food.yml` (food) | | `memory` | 基础设施 | rides, food | `restart-service.yml` | | `driver-supply` | 领域 | rides | `restart-driver-supply.yml` | | `surge-calc` | 领域 | rides | `fix-surge-calc.yml` | | `order-queue` | 领域 | food | `restart-queue-worker.yml` | | `restaurant-upstream` | 领域 | food | `failover-restaurant-upstream.yml` | | `eta-service` | 领域 | food | `restart-eta-service.yml` | 后端根据警报的 `app` 标签过滤 playbook 候选项,因此 LLM 只能看到适用的 playbook。修复器会根据启动情况被告知正确的 `victim_app_url`。 ## 端到端演示流程(触发场景后) 在**实时警报 UI** 中,按以下顺序: 1. 大约 30-45 秒后,警报卡片出现(`CRITICAL · FIRING`)。 2. 推理日志在右侧面板中逐步流式传输。 3. **应用解决方案** 按钮激活。 4. 点击它 → 提示 “已启动 playbook X” → 修复面板显示 **状态:正在运行**。 5. 大约 5-10 秒后 → **状态:成功 (exit 0)**,原始 Ansible 标准输出显示在黑色框中。 6. 再过大约 30 秒后 → 当 Alertmanager 检测到恢复时,状态标签翻转为 **已解决**。 7. (设置了 AWS 凭证后)提示:“已从 X (id LEARNED-...) 更新知识库” — 已解决的事件已重新嵌入 pgvector 以供未来检索。 同时关注 Grafana — 异常指标(延迟、连接池、错误率等)在 playbook 运行后立即恢复到基线。 ## 环境 所有环境变量位于 `server/.env`。示例: ``` AWS_REGION=us-west-2 # Bedrock region AWS_ACCESS_KEY_ID=... # blank → mock mode AWS_SECRET_ACCESS_KEY=... AWS_SESSION_TOKEN=... # only for temporary STS creds (ASIA...) LLM_MODEL=qwen.qwen3-235b-a22b-2507-v1:0 # Bedrock chat model EMBEDDING_MODEL=amazon.titan-embed-text-v2:0 # Bedrock embedding model EMBEDDING_DIM=1024 # must match pgvector column PORT=3000 DATABASE_URL=postgresql://grab:grab@localhost:5432/grab # pgvector — needs AWS creds too REMEDIATOR_URL=http://localhost:5005 # remediator host port (5005, not 5000) ALERTMANAGER_BEARER_TOKEN=demo-secret-change-me # must match alertmanager/alertmanager.yml ELASTICSEARCH_URL=http://localhost:9200 # user-facing keyword search (optional) ``` | 变量 | 何时必需 | 缺失时的效果 | |---|---|---| | `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` | 实时 LLM + pgvector + 聊天 | 推理日志使用模拟存根;知识库使用内存中的 jaccard 相似度;聊天返回“设置 AWS 凭证以启用”的消息 | | `AWS_SESSION_TOKEN` | 仅用于临时 STS 凭证 | 永久 IAM 凭证 (AKIA...) 不需要此项 | | `LLM_MODEL` | — (有默认值) | 回退到 `qwen.qwen3-235b-a22b-2507-v1:0` | | `EMBEDDING_MODEL` / `EMBEDDING_DIM` | — (有默认值) | 回退到 Titan v2 @ 1024 维度 | | `DATABASE_URL` | pgvector 模式 + 持久化评论/审核队列 | 知识库回退到内存中的余弦相似度(有 AWS 凭证时)或 jaccard(无凭证时);评论 + 审核队列回退到仅内存 | | `REMEDIATOR_URL` | 应用解决方案按钮 | 从 `/api/solutions/apply` 返回 502 | | `ALERTMANAGER_BEARER_TOKEN` | Alertmanager → 后端 Webhook | 后端对传入的 Webhook 返回 401 | | `ELASTICSEARCH_URL` | 用户面向的关键词搜索 | `/api/search` 返回 503;已关闭事件中的搜索栏保持为空。后端在其他方面继续工作 — pgvector 独立处理 AI 检索。 | ## 项目结构 ``` grab/ ├── docker-compose.yml # postgres, rides-app, food-app, remediator, prometheus, alertmanager, grafana, elasticsearch ├── postgres/init.sql # CREATE EXTENSION vector ├── prometheus/ │ ├── prometheus.yml # scrapes rides-app:4000 + food-app:4001 │ └── alerts.yml # 10 alert rules: 5 core (grouped by app) + 2 rides domain + 3 food domain ├── alertmanager/alertmanager.yml # webhook receiver → backend /api/alerts ├── grafana/ │ ├── provisioning/ # auto-add Prometheus datasource + dashboard │ └── dashboards/victim-app.json # $app dropdown + core row + rides domain row + food domain row ├── victim-app/ # the RIDES service (label app=rides, port 4000) │ ├── src/ │ │ ├── index.js # Express bootstrap, serves /public + APIs │ │ ├── metrics.js # prom-client registry, request log buffer, domain gauges │ │ ├── chaos.js # shared toggles + driverSupplyEmpty + surgeCalcSlow │ │ ├── db.js # semaphore-backed pool of 10 │ │ ├── cache.js # in-memory cache + hit-ratio │ │ ├── backgroundTraffic.js # cyclic synthetic load │ │ └── routes/ │ │ ├── api.js # /api/rides, /api/drivers/:id, /api/bookings, /api/surge, /api/drivers-snapshot │ │ └── admin.js # /admin/chaos/{...,driver-supply,surge-calc,reset}, /admin/status, /admin/recent │ ├── public/index.html # driver grid + surge gauge + request feed UI │ └── Dockerfile ├── food-app/ # the FOOD service (label app=food, port 4001) │ ├── src/ │ │ ├── index.js # Express bootstrap, serves /public + APIs, starts order worker │ │ ├── metrics.js # prom-client registry, request log, queue/prep/upstream metrics │ │ ├── chaos.js # shared toggles + orderQueueBacklog + restaurantApiTimeout + etaServiceErrors │ │ ├── db.js # semaphore-backed pool of 10 │ │ ├── cache.js # in-memory cache + hit-ratio │ │ ├── orderQueue.js # in-memory order lifecycle (pending→cooking→ready→out→delivered) + kitchen worker │ │ ├── backgroundTraffic.js # cyclic synthetic load with order placements │ │ └── routes/ │ │ ├── api.js # /api/restaurants[/:id], /api/orders[/:id], /api/delivery/eta, /api/orders-snapshot │ │ └── admin.js # /admin/chaos/{...,order-queue-backlog,restaurant-timeout,eta-errors,reset} │ ├── public/index.html # order kanban + queue-depth bar + restaurant tiles UI │ └── Dockerfile ├── remediator/ # Ansible playbook runner (Node + ansible-core) │ ├── src/index.js # AWX-shaped /jobs/launch + callback (extraVars.victim_app_url overrides default) │ ├── playbooks/ # 11 playbooks │ │ ├── restart-pool.yml # → database (both apps) │ │ ├── restart-service.yml # → errors / memory / unknown (both apps) │ │ ├── clear-cache.yml # → rides cache (warms drivers) │ │ ├── scale-latency.yml # → rides latency (smoke-tests /api/rides) │ │ ├── restart-driver-supply.yml # → rides driver-supply │ │ ├── fix-surge-calc.yml # → rides surge-calc │ │ ├── clear-cache-food.yml # → food cache (warms restaurants) │ │ ├── scale-latency-food.yml # → food latency (smoke-tests /api/restaurants) │ │ ├── restart-queue-worker.yml # → food order-queue │ │ ├── failover-restaurant-upstream.yml # → food restaurant-upstream │ │ └── restart-eta-service.yml # → food eta-service │ └── Dockerfile ├── server/ # backend │ ├── src/ │ │ ├── index.js # Express + WebSocket bootstrap │ │ ├── llmService.js # generateReasoningLog + chatWithAgent (Bedrock Converse API) │ │ ├── embeddingService.js # Bedrock Titan embeddings (titan-embed-text-v2:0, 1024d) │ │ ├── knowledgeBase.js # auto-selects pgvector / in-memory cosine / jaccard, also seeds ES │ │ ├── pgvectorStore.js # kb_documents + playbook_runs + incident_comments + kb_review_queue │ │ ├── elasticsearchStore.js # ES client + index + bulkIndex + search (user-facing keyword) │ │ ├── reasoningPipeline.js # retrieve → generate → assemble │ │ ├── alertStore.js # in-memory store keyed by alertmanager fingerprint │ │ ├── commentsService.js # comments wrapper (pgvector or in-memory fallback) │ │ ├── reviewQueueService.js # senior-review queue wrapper │ │ ├── chatHistoryStore.js # in-memory per-fingerprint chat history (40-turn cap) │ │ ├── wsServer.js # WebSocket on /api/ws │ │ └── routes/ │ │ ├── alerts.js # POST /api/alerts (bearer) + GET list/detail │ │ │ # /:fp/comments (GET/POST) │ │ │ # /:fp/resolve (POST — manual resolve, mandatory comment) │ │ │ # /:fp/reject (POST — engineer rejects, queues for senior) │ │ │ # /:fp/chat (GET/POST/DELETE — multi-turn LLM chat) │ │ ├── solutions.js # POST /api/solutions/apply + /callback (rejects auto-resolved) │ │ ├── reviewQueue.js # /api/review-queue (list / approve / dismiss) │ │ ├── search.js # /api/search (Elasticsearch keyword search) │ │ ├── demo.js # /api/demo/trigger + 5-min reminder loop │ │ ├── reasoningLogs.js │ │ └── knowledge.js │ └── .env └── Frontend/ # Angular 15 ├── proxy.conf.json # /api → backend (with ws: true for WebSocket) └── src/app/ ├── services/ │ ├── websocket.service.ts # auto-reconnect WS client │ ├── live-alert.service.ts # HTTP + WS state, comments, resolve, reject, chat, review-queue │ └── elastic-search.service.ts # backed by /api/search (real ES, no longer mock) ├── shared/pipes/markdown.pipe.ts # safe markdown render for chat / comments / reasoning text ├── models/live-alert.model.ts # + IncidentComment, ReviewQueueEntry, ChatTurn types └── components/ ├── live-alerts/ # main demo component (standalone) ├── reasoning-log/ # streaming reveal of reasoning steps ├── incident-investigation-panel/ # Apply / Reject / Chat / Mark Resolved + comments └── ai-monitor/ ├── review-queue/ # senior SRE review page └── incident-report/ # ngx-echarts PDF report ``` ## 警报到动作的流程如何工作 1. **Prometheus** 每 5 秒抓取 `rides-app:4000/metrics` 和 `food-app:4001/metrics`。两个服务都发出带有 `app` 标签(`rides` 或 `food`)的指标。 2. 当某个规则的 PromQL 表达式在其 `for:` 窗口内为真(例如 `histogram_quantile(0.95, sum by (le, route, app) (...)) > 1`),它就会触发。核心规则按 `app` 分组,因此相同的警报可以为每个服务独立触发。 3. **Alertmanager** 接收它,按 `alertname` + `incident_class` + `app` 分组,并将 JSON POST 到 `http://host.docker.internal:3000/api/alerts`,并带有 `Authorization: Bearer demo-secret-change-me`。每个警报都携带 `app`、`category` 和 `incident_class` 标签。 4. **后端** 验证令牌,将 Alertmanager 载荷映射为一个事件(在 `LiveAlertRecord` 中保留 `app` + `category`),并异步运行推理管道(立即返回 202,以免阻塞 Alertmanager): - 从 pgvector 检索相似的历史事件和 SOP(基于 Titan 嵌入的余弦相似度) - 调用 Bedrock 聊天模型(默认为 Qwen3-235B),结合警报和检索到的上下文生成结构化的 ReasoningLog - 将所有内容以 Alertmanager 的稳定 `fingerprint` 为键存储。 5. **WebSocket 广播** 在每个里程碑发送:`alert.new`、`alert.reasoning-log`、`alert.resolved`、`remediation.launched`、`remediation.completed`、`kb.learned`。 6. **Angular UI** 接收广播并实时更新警报列表/推理日志面板。“打开的事件”选项卡提供服务/类别/领域类别芯片过滤器,以便用户可以按触发内容切片。 7. 用户点击 **应用解决方案** → 后端查找警报的 `app` 标签,将 playbook 目录过滤到 `applicableApps` 包含该应用的 playbook,选择 LLM 的建议(或该类别的目录默认值),并 POST 到 `remediator:/jobs/launch`,其中 `extraVars.victim_app_url` 设置为正确的服务 URL(`http://rides-app:4000` 或 `http://food-app:4001`)。 8. **修复器** 启动 `ansible-playbook`,后者通过 `ansible.builtin.uri` 模块调用正确服务的 `/admin/chaos/reset`。 9. 混沌测试清除,指标返回基线,Alertmanager 在 30 秒后发送 `status: resolved`。 10. **自动反馈循环**:如果修复成功且 pgvector 已启用,已解决的事件将作为 `LEARNED-` 行重新嵌入知识库以供未来检索。 ## 故障排除 | 症状 | 原因 | 修复方法 | |---|---|---| | 启动后端时出现 `EADDRINUSE :::3000` | 端口 3000 上有其他进程 | `taskkill /f /im node.exe` (Windows) 或使用 `netstat -ano \| findstr 3000` 查找占用者 | | 修复器出现 `port 5000 already allocated` | macOS 控制中心 / Windows IIS 使用 5000 | 已在 `docker-compose.yml` 中映射到 5005;确保 `.env` 中 `REMEDIATOR_URL=http://localhost:5005` | | `column "summary" of relation "kb_documents" does not exist` | 早期测试留下的陈旧模式 | `docker exec postgres psql -U grab -d grab -c "DROP TABLE IF EXISTS kb_documents CASCADE;"` 然后重启后端 | | `[HPM] proxying request /ws to undefined` | webpack-dev-server 使用 `/ws` 进行 HMR;冲突 | 已修复 — 后端 WS 在 `/api/ws` 并通过现有的 `/api` 桶代理 | | 后端显示 `mode=mock` 但 `.env` 中有 API 密钥 | dotenv 从 `process.cwd()` 加载;在 `server/` 外部运行 `node` 会错过它 | 已修复 — `index.js` 相对于其自身目录解析 `.env` | | Alertmanager 显示连接后端被拒绝 `connection refused` | 后端未运行 | 在终端 B 中启动后端;Alertmanager 将自动重试,使用指数退避 | | UI 显示 `WS disconnected` 🔴 | 后端关闭,或 `proxy.conf.json` 过时 | 检查后端是否启动;`proxy.conf.json` 中的 `/api` 代理条目必须有 `"ws": true` | | `docker compose ps` 后容器缺失 | Compose 状态被部分拆除 | 从仓库根目录运行 `docker compose up -d` 恢复所有内容 | ## 停止堆栈 ``` docker compose down # stops containers, keeps volumes (pgvector data preserved) docker compose down -v # also wipes postgres/grafana/prometheus volumes ``` 在各自的终端中使用 `Ctrl+C` 停止后端和 Angular。 ## 许可证 / 状态 用于演示/黑客马拉松的原型。未经生产环境加固。Alertmanager 和后端之间的 Bearer 认证是静态密钥 — 生产环境中可通过小型代理换成 HMAC 签名。
标签:Alertmanager, Angular, Ansible, AWS Bedrock, Elasticsearch, GNU通用公共许可证, Grype, MITM代理, Node.js, PDF报告, pgvector, RAG推理, SRE, webhook, 事件管理, 事件管道, 事件过滤, 偏差过滤, 基础设施监控, 外卖服务, 多轮对话, 异常检测, 服务监控, 模块化设计, 测试用例, 混沌工程, 用户搜索, 知识库管理, 系统提示词, 自动化修复, 自动化运维, 自定义脚本, 自定义请求头, 自我修复系统, 请求拦截, 骑行服务