Files
ai-ops/tech/INTERFACE.md
2026-05-12 17:48:22 +08:00

388 lines
13 KiB
Markdown
Raw Permalink 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.
# AI-Ops 核心接口设计
> 版本v1.0 | 状态:初稿
---
## 1. 内部模块间接口
### 1.1 MetricService
```go
type MetricService interface {
// 采集指标
Collect(ctx context.Context, source string, metrics []MetricPoint) error
// 查询时序数据
Query(ctx context.Context, req MetricQueryRequest) (*MetricQueryResult, error)
// 获取最新值
GetLatest(ctx context.Context, source, metricName string) (*MetricPoint, error)
// 存储保留期检查
PurgeExpired(ctx context.Context, before time.Time) (int64, error)
}
type MetricPoint struct {
Source string
Name string
Value float64
Tags map[string]string
Timestamp time.Time
}
type MetricQueryRequest struct {
Source string
Name string
StartTime time.Time
EndTime time.Time
Interval time.Duration // 聚合间隔
Tags map[string]string
}
type MetricQueryResult struct {
Points []MetricPoint
}
```
### 1.2 AlertService
```go
type AlertService interface {
// 规则 CRUD
CreateRule(ctx context.Context, rule AlertRule) (*AlertRule, error)
UpdateRule(ctx context.Context, rule AlertRule) (*AlertRule, error)
DeleteRule(ctx context.Context, ruleID string) error
GetRule(ctx context.Context, ruleID string) (*AlertRule, error)
ListRules(ctx context.Context, filter RuleFilter) ([]AlertRule, error)
// 告警事件管理
ListAlerts(ctx context.Context, filter AlertFilter) ([]AlertEvent, error)
Acknowledge(ctx context.Context, alertID, actorID string) error
Ignore(ctx context.Context, alertID, actorID string) error
Escalate(ctx context.Context, alertID, reason string) error
// 实时评估
Evaluate(ctx context.Context, ruleID string) (*AlertEvent, error)
}
type AlertRule struct {
ID string
Name string
MetricSource string
MetricName string
ThresholdType string // > < = regex
ThresholdValue string
DurationMin int
Level string // P0 P1 P2 P3
ChannelIDs []string
HealingAction *string
HealingConfig map[string]any
IsSandboxed bool
Enabled bool
Version int
}
type AlertEvent struct {
ID string
RuleID string
Level string
ResourceType string
ResourceID string
CurrentValue string
ThresholdValue string
Status string // triggered notified healing resolved escalated acknowledged
IsAggregated bool
AggregatedCount int
CreatedAt time.Time
UpdatedAt time.Time
}
```
### 1.3 HealingService
```go
type HealingService interface {
// 执行自愈动作
Execute(ctx context.Context, action HealingAction, target ResourceTarget) (*HealingResult, error)
// 获取可用动作列表
ListActions(ctx context.Context) []HealingActionMeta
// 回滚自愈动作
Rollback(ctx context.Context, executionID string) error
// 查询执行历史
ListExecutions(ctx context.Context, filter ExecutionFilter) ([]HealingExecution, error)
}
type HealingAction struct {
Type string // restart_instance switch_route throttle isolate_node invoke_script
Config map[string]any
}
type ResourceTarget struct {
Type string // service provider model
ID string
}
type HealingResult struct {
ExecutionID string
Success bool
BeforeState map[string]any
AfterState map[string]any
Error *string
ExecutedAt time.Time
}
```
### 1.4 AuditService
```go
type AuditService interface {
// 记录审计事件
Record(ctx context.Context, event AuditEvent) error
// 查询审计日志
Query(ctx context.Context, filter AuditFilter) ([]AuditEvent, error)
// 回滚操作
Rollback(ctx context.Context, eventID string, actorID string) (*AuditEvent, error)
// 影响面计算
CalculateImpact(ctx context.Context, objectType, objectID string, proposedState map[string]any) (*ImpactReport, error)
}
type AuditEvent struct {
EventID string
TenantID string
ObjectType string
ObjectID string
Action string // create update delete rollback
BeforeState map[string]any
AfterState map[string]any
RequestID string
ResultCode string
SourceIP string
ActorID string
CreatedAt time.Time
}
type ImpactReport struct {
RiskLevel string // low medium high
EstimatedRejectRate float64 // 预估拒绝率
AffectedResources []string
RequiresConfirm bool
}
```
### 1.5 CapacityService
```go
type CapacityService interface {
// 获取容量视图
GetDashboard(ctx context.Context, scope CapacityScope) (*CapacityDashboard, error)
// 增长率预测
PredictGrowth(ctx context.Context, metric string, horizon time.Duration) (*GrowthPrediction, error)
// 设置容量阈值
SetThreshold(ctx context.Context, metric string, threshold float64) error
}
type CapacityDashboard struct {
Metrics []CapacityMetric
Predictions []GrowthPrediction
LastUpdated time.Time
}
type CapacityMetric struct {
Name string
Current float64
Limit float64
Unit string
Utilization float64
}
type GrowthPrediction struct {
Metric string
DailyGrowth float64
DaysToLimit *int // nil 表示不会达到上限
}
```
### 1.6 IntegrationPlugin
`IntegrationPlugin` 是 AI-Ops 与立交桥主项目gateway/supply-api集成运行时的核心接口。主项目通过实现该接口将 AI-Ops 的能力挂载到自身进程中。
```go
// IntegrationPlugin 定义了 AI-Ops 模块在集成运行时必须实现的接口契约
// 注意:模块必须通过显式 import + init 注册到全局注册表,
// 且主程序必须通过配置显式 Enable 才能激活模块。
type IntegrationPlugin interface {
// Name 返回模块唯一标识,用于配置关联和日志区分
// 示例: "alert", "healing", "audit", "capacity"
Name() string
// Init 在模块被启用时执行一次初始化
// 负责: 连接数据库、初始化缓存、启动后台 worker 等
// 若初始化失败,整个模块不得启动,主程序应记录错误并继续启动其他模块
Init(ctx context.Context, cfg Config) error
// RegisterRoutes 将模块的 HTTP 接口注册到主程序的 ServeMux
// 路径必须以 /internal/ai-ops/{module}/ 为前缀
// 示例: /internal/ai-ops/alert/rules, /internal/ai-ops/healing/actions
RegisterRoutes(mux *http.ServeMux) error
// HealthChecks 返回模块的健康检查函数列表
// 主程序将聚合所有模块的健康检查到 /actuator/health 和 /actuator/health/ready
HealthChecks() []HealthCheckFunc
// Shutdown 在主程序退出时按 LIFO 顺序调用
// 负责: 关闭数据库连接、停止 worker、释放资源
// 超时上限 30 秒,超时后强制终止
Shutdown(ctx context.Context) error
}
// HealthCheckFunc 是健康检查函数签名
type HealthCheckFunc func(ctx context.Context) (name string, status string, detail string)
// PluginRegistry 是全局模块注册表(线程安全)
var registry = make(map[string]IntegrationPlugin)
var registryMu sync.RWMutex
// Register 在 init() 中调用,将模块注册到全局注册表
func Register(p IntegrationPlugin) {
registryMu.Lock()
defer registryMu.Unlock()
if _, exists := registry[p.Name()]; exists {
panic("duplicate plugin registration: " + p.Name())
}
registry[p.Name()] = p
}
// GetRegisteredPlugins 返回已注册的所有模块拷贝
func GetRegisteredPlugins() []IntegrationPlugin {
registryMu.RLock()
defer registryMu.RUnlock()
result := make([]IntegrationPlugin, 0, len(registry))
for _, p := range registry {
result = append(result, p)
}
return result
}
```
**注册与使用示例**
```go
package alert
import (
"context"
"net/http"
aiops "github.com/company/ai-ops"
)
func init() {
// 显式注册到全局注册表
aiops.Register(&AlertPlugin{})
}
type AlertPlugin struct{ /* ... */ }
func (p *AlertPlugin) Name() string { return "alert" }
func (p *AlertPlugin) Init(ctx context.Context, cfg aiops.Config) error { /* ... */ }
func (p *AlertPlugin) RegisterRoutes(mux *http.ServeMux) error { /* ... */ }
func (p *AlertPlugin) HealthChecks() []aiops.HealthCheckFunc { /* ... */ }
func (p *AlertPlugin) Shutdown(ctx context.Context) error { /* ... */ }
```
**关键约束**
1. **显式 Enable**:主程序配置文件中必须显式开启模块,默认关闭。示例:`ai_ops.alert.enabled: true`
2. **路由前缀统一**:所有注册的路由必须以 `/internal/ai-ops/` 为前缀,避免与主系统路径冲突。
3. **数据库前缀统一**:插件创建的表必须使用 `ai_ops_` 前缀,避免 schema 冲突。
4. **健康检查注入**:插件实现的 HealthChecks 必须被主程序聚合到 /actuator/health 和 /actuator/health/ready 。
5. **顺序关闭**主程序关闭时必须按后进先出LIFO顺序调用各插件的 Shutdown 。
---
## 2. 外部系统集成接口
### 2.1 与 Bridge Gateway 集成
| 方法 | 路径 | 请求 | 响应 | 说明 |
|------|------|------|------|------|
| 查询服务状态 | `GET /internal/gateway/health` | - | `{"status":"up","services":{}}` | 诊断时查询各服务健康状态 |
| 获取路由策略 | `GET /internal/gateway/routes` | - | `{"routes":[]}` | 读取当前路由配置,用于影响面分析 |
| 修改路由策略 | `POST /internal/gateway/routes` | `{"action":"switch_route","target":"","config":{}}` | `{"success":true}` | 自愈动作调用,需审计 |
|| 获取请求量统计 | `GET /internal/gateway/metrics` | `?metric=qps&duration=5m` | `{"value":1234.5}` | 采集指标数据 |
> **安全约束**`/internal/gateway/metrics` 端点仅限内网 IP 访问(如 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16或需要携带有效的服务间 API Key。公网直接访问应返回 403 Forbidden。
### 2.2 与 supply-api 集成
| 方法 | 路径 | 请求 | 响应 | 说明 |
|------|------|------|------|------|
| 查询供应商状态 | `GET /internal/supply/accounts/health` | - | `{"accounts":[]}` | 诊断供应商健康状态 |
| 获取审计日志格式 | `GET /internal/supply/audit/schema` | - | `{"schema":{}}` | 确保审计事件格式一致 |
### 2.3 与 platform-token-runtime 集成
| 方法 | 路径 | 请求 | 响应 | 说明 |
|------|------|------|------|------|
| 获取 Token 消耗 | `GET /internal/runtime/token-usage` | `?window=1h` | `{"total":12345,"by_model":{}}` | 采集 Token 消耗指标 |
| 获取容量使用率 | `GET /internal/runtime/capacity` | - | `{"utilization":0.75}` | 采集容量指标 |
---
## 3. API 接口规范
### 3.1 REST API 基础
- **基础路径**: `/api/v1/ai-ops/`
- **内部路径** (集成模式): `/internal/ai-ops/`
- **内容类型**: `application/json`
- **错误响应格式**:
```json
{
"error_code": "OPS_{CATEGORY}_{CODE}",
"message": "人类可读的错误信息",
"detail": {} // 可选,包含额外的调试信息
}
```
### 3.2 错误码
| 错误码 | HTTP 状态 | 说明 |
|---------|-----------|------|
| `OPS_GEN_4001` | 400 | 请求参数错误 |
| `OPS_GEN_4002` | 401 | 未授权 |
| `OPS_GEN_4003` | 403 | 权限不足 |
| `OPS_GEN_4004` | 404 | 资源不存在 |
| `OPS_GEN_4005` | 409 | 资源冲突(如名称已存在) |
| `OPS_GEN_4006` | 413 | 请求体过大(如日志查询时间范围过大) |
| `OPS_GEN_5001` | 500 | 内部服务错误 |
| `OPS_MET_4001` | 400 | 指标名称无效 |
| `OPS_MET_4002` | 400 | 时间范围不合法 |
| `OPS_ALT_4001` | 400 | 规则名称已存在 |
| `OPS_ALT_4002` | 400 | 规则参数验证失败 |
| `OPS_ALT_4003` | 409 | 规则被其他用户修改(版本冲突) |
| `OPS_HEAL_4001` | 400 | 自愈动作参数无效 |
| `OPS_HEAL_4002` | 409 | 自愈动作正在执行中 |
| `OPS_HEAL_4003` | 400 | 回滚目标执行不存在 |
| `OPS_AUD_4001` | 403 | 无权进行审计操作 |
| `OPS_AUD_4101` | 400 | 回滚目标资源不存在 |
| `OPS_AUD_4102` | 409 | 回滚目标已被后续修改覆盖 |
| `OPS_CAP_4001` | 400 | 容量指标不存在 |
### 3.3 分页
- `列表接口` 支持分页参数:`?page=1&page_size=20`
- 默认 `page_size=20`,最大 `page_size=100`
- 响应体包含:`{"items":[],"total":123,"page":1,"page_size":20}`
### 3.4 WebSocket 接口
**路径**: `/ws/v1/ai-ops/alerts`
**鉴权机制**:
- 连接建立时必须在查询参数中携带有效 JWT Token`?token=<jwt>`。
- 服务端在升级 WebSocket 连接前必须验证 token 有效性、过期时间和角色权限。
- token 无效或已过期时,立即返回 401 Unauthorized 并关闭连接。
- 订阅范围根据用户角色过滤,查看者只能接收 P1 及以下级别告警,管理员可接收所有级别。
**功能**:
- 客户端订阅后,实时推送新告警事件。
- 支持按级别过滤:`?levels=P0,P1`。
- 心跳间隔 30 秒。