kathirvelarun/air-dev-java
GitHub: kathirvelarun/air-dev-java
一个结合 AI agent 与规格驱动开发的运维事件响应平台,通过告警关联、自动调查和根本原因分析帮助 SRE 团队高效处置生产事件。
Stars: 0 | Forks: 0
# AIR — Agentic Incident Response
一个专为 SRE 工程师、事件指挥官和工程主管设计的 AI 驱动的事件调查与响应平台。AIR 同时也是**结合 AI 编程 agent 的规格驱动开发**的参考实现 —— `specs/` 目录下的每一个 spec 文件都是可以直接交给 agent 的 prompt。
## AIR 的功能
1. **接入**来自日志流、监控工具、API 和 Slack 的运维告警,并将它们**关联**成去重后的告警组
2. 根据关联的告警组或直接通过 UI **创建事件**
3. 使用专门的 AI agent 流水线(日志、指标、部署历史、依赖关系)对每个事件进行**调查**
4. **诊断**可能的根本原因 —— 提供排序后的假设,每个假设均附带置信度分数和引用的证据
5. **推荐**进行了风险分类的修复选项,其中首选选项会带有直链指向对应的 runbook
6. **保持人类在环** —— runbook 需要手动执行;AIR 绝不会自行更改生产环境状态
7. 在解决事件时**生成复盘报告** —— 包含时间线、影响范围、根本原因分析和待办事项
8. **丰富自身的知识库** —— 经过批准的复盘报告和 runbook 会被向量化,以供未来的调查使用
其核心理念是**受控的调查**:每一个事件都会积累从告警到解决的完整证据链,且每一个 AI 生成的结论都是可解释的,并可追溯到其来源。
## 架构
三个服务,两条通信通道:
```
Browser ──HTTP──▶ air-web (React SPA, :5173)
│
/api proxy
│
▼
air-backend (Spring Boot, :8080)
│
Internal REST API
│
▼
air-agent (FastAPI, :8000)
│
pgvector RAG
│
▼
PostgreSQL (:5432)
```
`air-web` 仅与 `air-backend` 通信。`air-backend` 调用 `air-agent` 进行 AI 相关工作。`air-agent` 通过 callback 返回结果,且绝不修改事件状态。
**实时更新:**调查进度通过 Server-Sent Events (SSE) 实时流式传输到浏览器。
| 服务 | 技术栈 |
|---------|-------|
| `air-web` | React 18, TypeScript, Vite, React Router v6, TanStack Query |
| `air-backend` | Java 21, Spring Boot 3.4.1, Spring Security 6, Spring Data JPA, Flyway, PostgreSQL |
| `air-agent` | Python 3.12+, FastAPI, LangChain, Ollama (self-hosted LLM), pgvector |
## 已构建的功能
### 阶段 1 — 项目脚手架 ✅
三个通过健康检查互联的可运行服务。
- **`air-backend`**: 采用 Gradle 多项目构建的 Spring Boot,`GET /api/health`(检查 DB + agent 可达性),已配置 Flyway
- **`air-web`**: Vite + React + TypeScript,带有占位路由的 React Router 外壳,TanStack Query provider,指向后端的 `/api` 代理
- **`air-agent`**: 带有 Pydantic 设置的 FastAPI,`GET /health` 端点
- **`docker-compose.yml`**: PostgreSQL (pgvector)、Ollama、air-backend、air-agent 及其健康检查依赖
- **Flyway V1**: `users` 表 — UUID 主键,邮箱 (唯一),BCrypt 密码哈希,角色检查约束
**冒烟测试:** `GET http://localhost:8080/api/health` → `{"status":"ok","db":"connected","agent":"reachable"}`
### 阶段 2 — 身份验证 ✅
实现具有基于角色的访问控制 (RBAC) 的、端到端的基于 JWT 的身份验证。
**后端:**
- `POST /api/auth/login` — 验证邮箱 + BCrypt 密码 + 角色匹配 → 签发 HS256 JWT (1小时过期)
- `GET /api/auth/me` — 从 `@AuthenticationPrincipal` 返回用户信息
- `POST /api/auth/logout` — 无状态返回 200
- `JwtAuthFilter` (`OncePerRequestFilter`) — 验证每次请求中的 Bearer token,设置以 `ROLE_` 为前缀的权限
- `SecurityConfig` — 无状态会话,针对 `localhost:5173` 的 CORS,为未来的 `@PreAuthorize` 启用 `@EnableMethodSecurity`
- `DataInitializer` — 初始化 `sre@air.dev` (SRE_ENGINEER) 和 `commander@air.dev` (INCIDENT_COMMANDER),密码均为 `password`
**前端:**
- 登录页 — 全屏 AmEx 深蓝色背景,白色卡片表单,角色选择器,预填的演示凭证
- `AuthProvider` / `useAuth()` — token + 用户信息持久化存储到 `localStorage`
- `ProtectedLayout` — 使用侧边栏包裹所有需验证的路由;遇到 401 时重定向至 `/login`
**演示凭证:**
| 邮箱 | 密码 | 角色 |
|-------|----------|------|
| `sre@air.dev` | `password` | SRE Engineer |
| `commander@air.dev` | `password` | Incident Commander |
### 阶段 3 — 告警接入与关联 ✅
告警流入,经过标准化,并去重关联为告警组。
**Flyway V2** — 两张新表:
```
alert_groups (id, dedup_key, service, first_seen, last_seen, occurrence_count, linked_incident_id)
alerts (id, source, source_id, summary, service, metric, error_signature,
severity_hint, dedup_key, alert_group_id, raw_payload, reported_at, created_at)
```
**后端端点:**
| 方法 | 路径 | 描述 |
|--------|------|-------------|
| `POST` | `/api/alerts` | 接入告警 → 标准化 → 计算 dedup key → 关联至告警组 → `201` |
| `GET` | `/api/alerts` | 列出告警,按 `source` / `service` 过滤,使用 `limit` / `offset` 分页 |
| `GET` | `/api/alert-groups/:id` | 包含所有成员告警的告警组详情 |
**关联逻辑:**
- Dedup key = `service + ":" + metric + ":" + errorSignature`
- 5分钟时间窗口:新告警会附加到具有相同 dedup key 的最近开启的告警组中,或开启一个新告警组
- 并发接入受组查找时的 `@Lock(PESSIMISTIC_WRITE)` (`SELECT ... FOR UPDATE`) 保护
- 幂等性:相同的 `source + source_id` 组合视为空操作 — 返回已有告警的关联状态
**限流:**
- 每个 `source` 在内存中的固定窗口计数器
- 可通过 `RATE_LIMIT_ALERTS_PER_MINUTE` 配置 (默认 60);超出限制时返回 `429`
**前端 — 告警页 (`/alerts`):**
- 过滤栏:source 下拉菜单 + service 文本过滤器
- 表格视图:严重程度徽标 (彩色圆点 + 标签)、service 标签、source、摘要、发生时间
- 可展开行:点击任意行查看告警组统计信息 (发生次数、首次/最后一次发现时间、dedup key) 以及所有同级告警
- 带有可直接复制的 `curl` 命令的空状态界面,方便快速测试
**新增共享组件 — `Layout.tsx`:**
- 深蓝色侧边栏 (`#00175a`),带有 AIR 品牌
- 角色感知导航:Incident Commander 可看到 Integrations + Settings
- 页脚包含用户名、角色标签和登出按钮
- 所有受保护路由现在均采用 `` → `` 模式
## 本地运行 (无需 Docker)
**前置条件:** Java 21, Node.js 20+, Python 3.12+, PostgreSQL 17
### 1. 数据库
```
# 创建数据库和用户(仅首次)
psql -c "CREATE USER air WITH PASSWORD 'air';"
psql -c "CREATE DATABASE air OWNER air;"
```
### 2. 后端
```
# 从 repo 根目录 — Flyway migrations 在启动时自动运行
./gradlew :air-backend:bootRun
# 监听于 http://localhost:8080
```
### 3. Agent
```
cd air-agent
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
.venv/bin/uvicorn main:app --reload --port 8000
# 监听于 http://localhost:8000
```
### 4. 前端
```
cd air-web
npm install
npm run dev
# 监听于 http://localhost:5173
```
打开 `http://localhost:5173` — 你将被重定向至登录页。
### 验证所有服务是否启动
```
curl http://localhost:8080/api/health
# {"status":"ok","db":"connected","agent":"reachable"}
```
### 接入测试告警
```
# 获取 token
TOKEN=$(curl -s -X POST http://localhost:8080/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"sre@air.dev","password":"password","role":"SRE_ENGINEER"}' \
| python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")
# 摄入 alert
curl -s -X POST http://localhost:8080/api/alerts \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"source":"ELF","summary":"DB connection pool exhausted","service":"checkout-service","severityHint":"P2","metric":"db.pool.size","errorSignature":"HikariPool-1"}' \
| python3 -m json.tool
```
## 环境变量
所有变量都有合理的本地默认值。在生产环境中请覆盖以下配置:
| 变量 | 默认值 | 描述 |
|----------|---------|-------------|
| `SPRING_DATASOURCE_URL` | `jdbc:postgresql://localhost:5432/air` | PostgreSQL JDBC URL |
| `SPRING_DATASOURCE_USERNAME` | `air` | 数据库用户名 |
| `SPRING_DATASOURCE_PASSWORD` | `air` | 数据库密码 |
| `JWT_SECRET` | `air-dev-jwt-secret-…` | HS256 签名密钥 (最少 32 字节) |
| `JWT_EXPIRY_MINUTES` | `60` | Token 有效期 |
| `AIR_AGENT_BASE_URL` | `http://localhost:8000` | air-agent 的基础 URL |
| `CORRELATION_WINDOW_MINUTES` | `5` | 告警关联窗口 |
| `RATE_LIMIT_ALERTS_PER_MINUTE` | `60` | 每个 source 每分钟允许的最大告警数 |
## 项目结构
```
air/
├── specs/
│ ├── mission.md # What AIR is, why it exists, core principles
│ ├── tech-stack.md # Architecture, service breakdown, design decisions
│ └── roadmap.md # 12 feature-sized phases with definitions of done
├── air-web/
│ └── src/
│ ├── components/
│ │ └── Layout.tsx # Sidebar navigation shell
│ ├── lib/
│ │ ├── api.ts # Typed fetch client with 401 handling
│ │ └── auth.tsx # AuthProvider + useAuth hook
│ └── pages/
│ ├── Login.tsx # Auth page
│ └── Alerts.tsx # Alert ingestion + correlated groups
├── air-backend/
│ └── src/main/
│ ├── java/com/amex/air/
│ │ ├── controller/ # HealthController, AuthController, AlertController
│ │ ├── domain/ # User, Alert, AlertGroup (JPA entities)
│ │ ├── dto/ # Request/response records
│ │ ├── repository/ # JPA repos (AlertGroupRepository has PESSIMISTIC_WRITE lock)
│ │ ├── security/ # JwtService, JwtAuthFilter, SecurityConfig
│ │ └── service/ # AlertService (correlation + rate limiting)
│ └── resources/
│ ├── application.yml
│ └── db/migration/
│ ├── V1__create_users.sql
│ └── V2__create_alerts.sql
└── air-agent/
├── main.py # FastAPI app
└── config.py # Pydantic settings
```
## 路线图
| 阶段 | 标题 | 状态 |
|-------|-------|--------|
| 1 | 项目脚手架 | ✅ 已完成 |
| 2 | 身份验证 | ✅ 已完成 |
| 3 | 告警接入与关联 | ✅ 已完成 |
| 4 | 事件创建 | 待办 |
| 5 | 调查 Agent 与 SSE | 待办 |
| 6 | RCA Agent | 待办 |
| 7 | Runbook Agent 与知识库 | 待办 |
| 8 | 通信 Agent 与 Slack 视图 | 待办 |
| 9 | 复盘 Agent 与回顾 | 待办 |
| 10 | 仪表盘与分析 | 待办 |
| 11 | 集成与设置 | 待办 |
| 12 | 强化与端到端测试 | 待办 |
请查看 `specs/roadmap.md` 获取每个阶段的完整完成标准。
## 设计原则
1. **证据优先。** 每个 AI 生成的结论都必须引用其来源。拒绝毫无根据的断言。
2. **人类在环。** AIR 负责提出建议;工程师负责决策和执行。
3. **可解释性高于魔法。** 置信度分数、引用的证据以及 `INSUFFICIENT_EVIDENCE` 状态,与答案本身一样重要。
4. **受控的知识库。** 只有经过人工批准的内容才能进入知识库 — 未经批准的 AI 输出绝不能反哺给自身。
标签:AIOps, AI智能体, AI风险缓解, RAG, SRE, 偏差过滤, 后端开发, 测试用例, 请求拦截, 运维, 逆向工具