Files
ez-api/docs/api.md
zenfun dab07caca2 docs(api): add apikey-stats time range and internal alerts report endpoints
Document two new API endpoints:
- GET /admin/apikey-stats/summary with optional since/until params
  for querying statistics within a specific time range
- POST /internal/alerts/report for Data Plane to report alerts
  with fingerprint-based deduplication mechanism
2025-12-31 14:25:55 +08:00

530 lines
18 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.
# EZ-API 控制平面 (Control Plane) 业务文档
> 本文档作为 Swagger 接口定义的补充,旨在详细说明 EZ-API 的业务逻辑、核心模型关系及配置含义,帮助前端开发与运维人员快速上手。
> **Swagger 入口**`GET /swagger/index.html`
---
## 1. 快速入门
### 1.1 服务地址 (Base URL)
默认地址:`http://{host}:8080`
### 1.2 鉴权体系
系统采用三级鉴权机制,分别对应不同的操作权限:
| 角色 | 鉴权方式 | 配置来源 | 说明 |
| :--- | :--- | :--- | :--- |
| **Admin** | `Authorization: Bearer <admin_token>` | 环境变量 `EZ_ADMIN_TOKEN` | 全局管理权限,可管理所有租户、供应商和模型。 |
| **Master** | `Authorization: Bearer <master_key>` | 创建 Master 时返回 | 租户级权限,仅能管理所属的子 Key、查看自身统计和日志。 |
| **Key** | `Authorization: Bearer <child_key>` | Master 或 Admin 签发 | 用于调用 AI API可通过 `/auth/whoami` 查询身份信息。 |
| **Internal** | `X-Internal-Token: <token>` | 环境变量 `EZ_INTERNAL_STATS_TOKEN` | 内部组件(如 Data Plane同步指标使用。 |
### 1.4 身份识别接口
使用 `GET /auth/whoami` 可根据 Authorization header 中的 Token 识别当前身份类型:
| Token 类型 | 返回 `type` | 说明 |
| :--- | :--- | :--- |
| Admin Token | `"admin"` | 进入管理员面板 |
| Master Key | `"master"` | 进入租户自服务面板 |
| Child Key | `"key"` | 显示 Key 信息页,包含 `issued_by` 字段标识签发者 |
**示例响应**
```json
// Admin Token
{"type": "admin", "role": "admin"}
// Master Key
{"type": "master", "id": 1, "name": "研发团队", "group": "default", ...}
// Child Key
{"type": "key", "id": 5, "master_id": 1, "issued_by": "master", ...}
```
### 1.3 通用约定
- **分页处理**
- 管理端列表 (`GET /admin/*`):使用 `page` (从 1 开始) 和 `limit` (默认 50最大 200)。
- 日志列表:使用 `limit``offset`
- **时间格式**
- 查询参数 (`since`/`until`):使用 **Unix 秒**(整数)。
- 日志清理 (`before`):使用 **RFC3339 字符串** (例如 `2025-01-01T00:00:00Z`)。
- **模糊搜索**`search` 参数通常匹配名称、描述或关键标识符。
---
## 2. 核心业务模型
EZ-API 的核心逻辑围绕“租户-令牌-路由-供应商”展开。
### 2.1 资源关系图
```mermaid
graph TD
Admin[Admin 管理员] -- 创建 --> Master[Master 租户]
Master -- 签发 --> Key[Key 子令牌]
Master -- 关联 --> Namespace[Namespace 命名空间]
Namespace -- 定义 --> Binding[Binding 路由规则]
Binding -- 映射 --> ProviderGroup[ProviderGroup 上游组]
ProviderGroup -- 包含 --> APIKey[APIKey 上游凭证]
Binding -. 关联 .-> Model[Model 能力表]
```
### 2.2 身份与权限模型
- **Master (租户)**:系统的顶级账户单位。
- `group`:路由分组,决定该租户默认使用哪一组供应商。
- `epoch`:版本号。当 Master 被删除或重置时Epoch 增加,所有旧的子 Key 将立即失效。
- `global_qps`:租户级总限流,`0` 表示不限流。
- **Key (子令牌)**:由 Master 签发给最终用户使用的 API Key。
- `scopes`:权限描述,仅用于业务标识。
- `quota_limit`总额度限制Token 数),`-1` 表示无限额。
- `quota_reset_type`:额度重置周期(如 `daily`, `monthly`)。
- `allow_ips`/`deny_ips`:支持 CIDR 格式的 IP 白名单/黑名单。
### 2.3 路由与供应商模型
- **ProviderGroup (上游组)**:一组同类型上游定义(如 OpenAI / Anthropic / Compatible
- `base_url``models` 在 Group 层统一声明。
- `name` 即路由的 `route_group`(内部使用)。
- **APIKey (上游凭证)**:具体可用的 key 池。
- `weight`:同组内负载均衡权重。
- `auto_ban` / `ban_until`:支持自动熔断与手动禁用。
- **Model (模型能力表)**:全局能力注册表(上下文长度、功能支持等)。
- **Namespace (命名空间)**:逻辑隔离单位,用于组织 Binding 规则。
- **Binding (路由规则)**:核心路由逻辑。
-`bindingKey = namespace.public_model` 映射到 `group_id`ProviderGroup
- 同一 `bindingKey` 可存在多条 Binding候选通过 `weight` 进行加权选择。
- `selector_type` + `selector_value` 用于从 Group 的 `models` 中解析上游 true_model。
- 能力校验以 `bindingKey` 为 keyCP 会将 true_model 能力汇总到 `bindingKey`)。
- 客户端请求若未携带 namespaceDP 会使用 key 的 `default_namespace` 生成 `bindingKey`
### 2.4 状态机约定
| 状态值 | 适用对象 | 含义 |
| :--- | :--- | :--- |
| `active` | 所有 | 正常可用。 |
| `suspended` | Master, Key, Namespace | 已停用,请求将被拦截。 |
| `auto_disabled` | APIKey | 因故障被系统自动熔断。 |
| `manual_disabled` | APIKey | 被管理员手动禁用。 |
---
## 3. 功能开关 (Feature Flags)
系统支持通过 API 动态调整运行时行为。
### 3.1 存储逻辑
- **常规开关**:存储在 Redis Hash `meta:features` 中。
- **日志策略**:由于涉及清理逻辑,存储在独立 Key 中。
### 3.2 常用配置项
| 配置项 | 类型 | 说明 | 默认值 |
| :--- | :--- | :--- | :--- |
| `dp_state_store_backend` | string | 状态存储后端:`memory` (单机) / `redis` (集群)。 | `memory` |
| `dp_claude_cross_upstream` | bool | 是否允许将 Claude 协议请求路由到 OpenAI 兼容与 Google-family 上游。 | `true` |
| `log_request_body_enabled` | bool | 是否在日志中记录请求体(注意隐私风险)。 | `true` |
| `log_retention_days` | int | 日志保留天数。写入 Redis `meta:log:retention_days`。 | `30` |
| `log_max_records` | int | 最大日志保留条数。写入 Redis `meta:log:max_records`。 | `1000000` |
> **注意**:更新 Feature 后Data Plane (DP) 会在下一个同步周期(通常为秒级)自动加载新配置。
---
## 4. API 模块概览
### 4.0 公开接口 - 无需鉴权
| 端点 | 说明 | 响应示例 |
|------|------|----------|
| `GET /health` | 健康检查(含依赖状态) | `{"status": "ok", "database": "up", "redis": "up", "uptime": "1h30m"}` |
| `GET /status` | 公开状态摘要 | `{"status": "ok", "uptime": "1h30m", "version": "v0.1.0"}` |
| `GET /about` | 系统信息 | `{"name": "EZ-API Gateway", "version": "v0.1.0", ...}` |
| `GET /auth/whoami` | 身份识别 | 根据 Token 返回身份类型和详细信息 |
| `GET /swagger/*` | API 文档 | Swagger UI |
### 4.1 管理端 (Admin API) - 需 Admin Token
- **租户管理**:创建 Master、签发子 Key、实时 QPS 监控、冻结/解冻。
- **上游管理**ProviderGroup + APIKey 的 CRUD 与批量操作。
- **模型注册表**:管理全局模型能力,支持从远程 `models.dev` 刷新和回滚。
- **日志审计**:全站请求日志查询、按条件批量删除日志、配置 Webhook 告警。
- **Dashboard 统计**:聚合指标摘要、系统级实时 QPS、按小时/分钟统计。
- **告警管理**:系统告警的查看、确认、解决和统计。
### 4.2 租户端 (Master API) - 需 Master Key
- **自服务**:查看租户信息、管理自己的子 Key。
- **数据分析**:查看所属租户的请求日志、用量统计、实时 QPS。
### 4.3 内部接口 (Internal API) - 需 Internal Token
- **指标回传**Data Plane 定期调用 `/internal/stats/flush` 同步 Token 消耗和请求数。
---
## 5. 典型操作示例
### 5.1 租户与令牌管理
1. **创建 Master 租户**
```bash
curl -X POST http://localhost:8080/admin/masters \
-H "Authorization: Bearer <admin_token>" \
-H "Content-Type: application/json" \
-d '{
"name": "研发团队",
"group": "default",
"max_child_keys": 10,
"global_qps": 50
}'
```
2. **为 Master 签发子 Key**(注意:`key_secret` 仅在此处返回一次):
```bash
curl -X POST http://localhost:8080/admin/masters/{master_id}/keys \
-H "Authorization: Bearer <admin_token>" \
-H "Content-Type: application/json" \
-d '{
"scopes": "chat,embedding",
"quota_limit": 5000000,
"quota_reset_type": "monthly",
"model_limits_enabled": true,
"model_limits": "gpt-4,claude-3-opus"
}'
```
### 5.2 供应商与路由配置
1. **创建 ProviderGroup**
```bash
curl -X POST http://localhost:8080/admin/provider-groups \
-H "Authorization: Bearer <admin_token>" \
-H "Content-Type: application/json" \
-d '{
"name": "openai-default",
"type": "openai",
"base_url": "https://api.openai.com/v1",
"models": ["gpt-4o", "gpt-4o-mini"]
}'
```
2. **创建 APIKey**
```bash
curl -X POST http://localhost:8080/admin/api-keys \
-H "Authorization: Bearer <admin_token>" \
-H "Content-Type: application/json" \
-d '{
"group_id": 1,
"api_key": "sk-...",
"weight": 10
}'
```
3. **创建模型路由 (Binding)**
```bash
curl -X POST http://localhost:8080/admin/bindings \
-H "Authorization: Bearer <admin_token>" \
-H "Content-Type: application/json" \
-d '{
"namespace": "default",
"public_model": "gpt-4o",
"group_id": 1,
"selector_type": "exact",
"selector_value": "gpt-4o",
"weight": 1
}'
```
### 5.3 系统运维与监控
1. **调整全局日志保留策略**
```bash
curl -X PUT http://localhost:8080/admin/features \
-H "Authorization: Bearer <admin_token>" \
-H "Content-Type: application/json" \
-d '{
"log_retention_days": 15,
"log_max_records": 2000000
}'
```
2. **查询特定 Key 的请求日志**
```bash
curl "http://localhost:8080/admin/logs?key_id=123&limit=20&status_code=200" \
-H "Authorization: Bearer <admin_token>"
```
3. **查看租户实时统计**
```bash
curl http://localhost:8080/admin/masters/{id}/realtime \
-H "Authorization: Bearer <admin_token>"
```
### 5.4 租户自服务 (Master API)
1. **租户签发子 Key**
```bash
curl -X POST http://localhost:8080/v1/tokens \
-H "Authorization: Bearer <master_key>" \
-H "Content-Type: application/json" \
-d '{
"scopes": "app-1",
"quota_limit": 100000
}'
```
2. **租户查看自身用量统计**
```bash
curl "http://localhost:8080/v1/stats?period=today" \
-H "Authorization: Bearer <master_key>"
```
### 5.5 内部与高级操作
1. **手动刷新模型注册表**
```bash
curl -X POST http://localhost:8080/admin/model-registry/refresh \
-H "Authorization: Bearer <admin_token>" \
-H "Content-Type: application/json" \
-d '{"ref": "main"}'
```
2. **内部指标回传 (Internal)**
```bash
curl -X POST http://localhost:8080/internal/stats/flush \
-H "X-Internal-Token: <internal_token>" \
-H "Content-Type: application/json" \
-d '{
"keys": [
{
"token_hash": "...",
"requests": 100,
"tokens": 5000,
"last_accessed_at": 1734849600
}
]
}'
```
---
## 6. Dashboard 与告警 API
### 6.1 Dashboard 统计端点
#### 获取 Dashboard 摘要
`GET /admin/dashboard/summary`
**查询参数**
| 参数 | 类型 | 说明 | 默认值 |
| :--- | :--- | :--- | :--- |
| `period` | string | 预设周期:`today`, `week`, `month` | `today` |
| `since` | int | 自定义起始时间 (Unix 秒) | - |
| `until` | int | 自定义结束时间 (Unix 秒) | - |
**响应示例**
```json
{
"period": "today",
"requests": {"total": 123456, "success": 120000, "failed": 3456, "error_rate": 0.028},
"tokens": {"total": 9876543, "input": 4000000, "output": 5876543},
"latency": {"avg_ms": 234.5},
"masters": {"total": 10, "active": 8},
"keys": {"total": 150, "active": 120},
"provider_keys": {"total": 20, "active": 15, "suspended": 3, "auto_disabled": 2},
"top_models": [{"model": "gpt-4o", "requests": 50000, "tokens": 2000000}],
"updated_at": 1704153600
}
```
#### 获取系统级实时统计
`GET /admin/realtime`
**响应示例**
```json
{
"qps": 125,
"rpm": 7500,
"rate_limited_count": 2,
"by_master": [{"master_id": 1, "qps": 50, "rate_limited": false}],
"updated_at": 1704153600
}
```
#### 日志统计按时间聚合
`GET /admin/logs/stats?group_by=hour|minute`
**新增 `group_by` 选项**
| 值 | 说明 | 时间范围限制 |
| :--- | :--- | :--- |
| `hour` | 按小时聚合,返回 `hour` 字段 (ISO 8601) | 无限制 |
| `minute` | 按分钟聚合,返回 `minute` 字段 (ISO 8601) | **必须提供 `since` 和 `until`,最大跨度 6 小时** |
**示例请求**
```bash
# 按小时统计 (24小时趋势)
curl "http://localhost:8080/admin/logs/stats?group_by=hour&since=1704067200&until=1704153600" \
-H "Authorization: Bearer <admin_token>"
# 按分钟统计 (精细时序最大6小时)
curl "http://localhost:8080/admin/logs/stats?group_by=minute&since=1704150000&until=1704153600" \
-H "Authorization: Bearer <admin_token>"
```
**响应示例 (hour)**
```json
{
"items": [
{"hour": "2025-01-01T10:00:00Z", "count": 1234, "tokens_in": 50000, "tokens_out": 80000, "avg_latency_ms": 234.5}
]
}
```
**响应示例 (minute)**
```json
{
"items": [
{"minute": "2025-01-01T10:30:00Z", "count": 45, "tokens_in": 2000, "tokens_out": 3500, "avg_latency_ms": 180.2}
]
}
```
### 6.2 API Key 状态筛选
`GET /admin/api-keys?status=active|suspended|auto_disabled|manual_disabled`
**新增 `status` 参数**:按上游凭证状态过滤,可与 `group_id` 组合使用。
```bash
# 获取所有激活的上游凭证
curl "http://localhost:8080/admin/api-keys?status=active" \
-H "Authorization: Bearer <admin_token>"
# 获取指定组内已暂停的凭证
curl "http://localhost:8080/admin/api-keys?group_id=1&status=suspended" \
-H "Authorization: Bearer <admin_token>"
```
### 6.3 告警管理端点
#### 告警类型与严重性
| 类型 (`type`) | 说明 |
| :--- | :--- |
| `rate_limit` | 速率限制触发 |
| `error_spike` | 错误率飙升 |
| `quota_exceeded` | 配额超限 |
| `key_disabled` | Key 被禁用 |
| `key_expired` | Key 已过期 |
| `provider_down` | 上游服务不可用 |
| 严重性 (`severity`) | 说明 |
| :--- | :--- |
| `info` | 信息通知 |
| `warning` | 警告 |
| `critical` | 严重告警 |
| 状态 (`status`) | 说明 |
| :--- | :--- |
| `active` | 活动告警 |
| `acknowledged` | 已确认 |
| `resolved` | 已解决 |
| `dismissed` | 已忽略 |
#### 告警端点列表
| 端点 | 方法 | 说明 |
| :--- | :--- | :--- |
| `/admin/alerts` | GET | 列出告警,支持 `status`、`severity`、`type` 筛选 |
| `/admin/alerts` | POST | 创建告警 |
| `/admin/alerts/:id` | GET | 获取单个告警详情 |
| `/admin/alerts/:id/ack` | POST | 确认告警 |
| `/admin/alerts/:id/resolve` | POST | 解决告警 |
| `/admin/alerts/:id` | DELETE | 忽略告警 (软删除) |
| `/admin/alerts/stats` | GET | 获取告警统计 |
#### 创建告警
```bash
curl -X POST http://localhost:8080/admin/alerts \
-H "Authorization: Bearer <admin_token>" \
-H "Content-Type: application/json" \
-d '{
"type": "rate_limit",
"severity": "warning",
"title": "速率限制触发",
"message": "Master research-team 在过去5分钟内触发了100次速率限制",
"related_id": 5,
"related_type": "master",
"related_name": "research-team"
}'
```
#### 获取告警统计
```bash
curl http://localhost:8080/admin/alerts/stats \
-H "Authorization: Bearer <admin_token>"
```
**响应示例**
```json
{
"total": 100,
"active": 5,
"acknowledged": 10,
"resolved": 85,
"critical": 2,
"warning": 3,
"info": 0
}
```
### 6.4 APIKey 成功率统计时间范围
`GET /admin/apikey-stats/summary?since=<unix>&until=<unix>`
**新增时间范围参数**:可选的 `since` 和 `until` 参数,用于获取特定时间段内的上游凭证统计。
```bash
# 获取今天的统计
curl "http://localhost:8080/admin/apikey-stats/summary?since=1704067200&until=1704153600" \
-H "Authorization: Bearer <admin_token>"
# 获取全量统计(不传时间参数)
curl "http://localhost:8080/admin/apikey-stats/summary" \
-H "Authorization: Bearer <admin_token>"
```
**响应示例**
```json
{
"total_requests": 50000,
"success_requests": 48000,
"failure_requests": 2000,
"success_rate": 0.96,
"failure_rate": 0.04
}
```
### 6.5 DP 告警上报 (内部接口)
`POST /internal/alerts/report`
**内部端点**:供 Data Plane 上报异常事件给 Control Plane需要 `X-Internal-Token` 认证。
**去重机制**
- 每个告警可携带 `fingerprint` 字段(如 `rate_limit:master:5`
- 若 5 分钟内存在相同 fingerprint 的活跃告警,新告警将被去重
```bash
curl -X POST http://localhost:8080/internal/alerts/report \
-H "X-Internal-Token: <internal_token>" \
-H "Content-Type: application/json" \
-d '{
"alerts": [
{
"type": "rate_limit",
"severity": "warning",
"title": "速率限制触发",
"message": "Master production 在1分钟内触发50次限流",
"related_id": 5,
"related_type": "master",
"related_name": "production",
"fingerprint": "rate_limit:master:5"
}
]
}'
```
**响应示例**
```json
{
"accepted": 1,
"deduplicated": 0,
"errors": []
}
```
---
## 7. 备注
- **数据一致性**:控制平面 (CP) 修改配置后,数据平面 (DP) 通过 Redis Pub/Sub 或定期轮询实现最终一致性。
- **安全性**:请务必妥善保管 `EZ_ADMIN_TOKEN`。Master Key 和子 Key Secret 在数据库中均以哈希形式存储,丢失无法找回,只能重置。