# api-plane **Repository Path**: mengyinggitee/api-plane ## Basic Information - **Project Name**: api-plane - **Description**: api的接口成功率的可视化面板 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-07-27 - **Last Updated**: 2026-08-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # API Plane - API 请求成功率监控平台 一个轻量级的 API 请求成功率实时监控与告警系统,基于 Go + Gin 构建,提供可视化仪表板和灵活的告警触发器管理。 ## 目录 - [功能特性](#功能特性) - [系统架构](#系统架构) - [快速开始](#快速开始) - [本地运行](#本地运行) - [Docker 部署](#docker-部署) - [API 接口文档](#api-接口文档) - [上报请求数据](#上报请求数据) - [获取统计快照](#获取统计快照) - [配置统计窗口](#配置统计窗口) - [获取当前配置](#获取当前配置) - [获取项目列表](#获取项目列表) - [获取渠道列表](#获取渠道列表) - [获取项目下渠道成功率](#获取项目下渠道成功率) - [触发器管理](#触发器管理) - [健康检查](#健康检查) - [前端页面](#前端页面) - [内存优化设计](#内存优化设计) - [项目结构](#项目结构) - [技术栈](#技术栈) --- ## 功能特性 ### 实时监控仪表板 - **双窗口统计**:短窗口(默认 30 分钟)和长窗口(默认 24 小时)的成功率、请求量、趋势分析 - **耗时分位统计**:Avg / P50 / P95 / P99 / Max 五档分位耗时 - **峰值指标**:峰值 QPS(滑动窗口算法)和峰值并发数(扫描线算法) - **错误分布饼图**:按错误类型展示占比 - **耗时分布饼图**:按耗时区间(<500ms / 500-1000ms / 1-3s / 3-5s / >5s)展示 - **时序直方图**:按小时粒度展示成功/失败趋势,支持按错误类型堆叠 - **趋势分析**:对比前一窗口计算成功率变化趋势(如 `+2.3%` / `-1.5%`) - **多级筛选**:项目(Project)+ 渠道(Channel)两级下拉,按所选项目展示其下渠道数据,支持全部项目/全渠道汇总 - **项目成功率接口**:按项目返回其下各渠道最近半小时的成功率,可作为流量分配权重 ### 告警触发器 - **两种触发条件**: - 错误率高于阈值(如错误率 > 5%) - 出现特定错误类型(如 `timeout`、`5xx`) - **灵活配置**:可指定项目、渠道、统计窗口、通知 URL - **自动检测**:后台每 1 分钟自动检查所有启用的触发器 - **样本前置条件**:统计窗口内样本数必须大于 5 条才参与告警判定,样本不足时仅提示不告警 - **通知冷却**:同一触发器 5 分钟内不重复通知 - **通知方式**:GET 请求通知 URL(兼容各类 Webhook)或企业微信机器人(markdown) - **持久化存储**:触发器配置保存至 JSON 文件 ### 高性能内存引擎 - **异步写入**:带缓冲 Channel + Worker 池,写入不阻塞请求 - **数据聚类**:超过短窗口的旧记录自动聚合为小时级桶,大幅降低内存占用 - **结构体优化**:字段按大小降序排列,消除内存对齐填充浪费 --- ## 系统架构 ``` POST /api/request │ ▼ ┌───────────────────┐ │ Gin HTTP 路由 │ │ JSON 解析请求体 │ └───────┬───────────┘ │ ▼ ┌───────────────────┐ │ RequestStore │ │ Buffer Channel │ ← 异步队列 (默认 10000) │ (非阻塞入队) │ └───────┬───────────┘ │ ▼ ┌───────────────────┐ │ Worker Pool (4) │ │ 消费队列写入内存 │ └───────┬───────────┘ │ ┌─────────────┴─────────────┐ ▼ ▼ ┌──────────────────┐ ┌──────────────────┐ │ 原始记录 (短窗口) │ │ 小时聚合桶 (长窗口)│ │ RequestRecord[] │ │ HourlyAgg Map │ └────────┬─────────┘ └────────┬─────────┘ │ │ └──────────┬───────────────┘ ▼ ┌──────────────────┐ │ GET /api/stats │ │ 统计计算 + 趋势 │ └──────────────────┘ ┌──────────────────────────────────┐ │ TriggerStore (后台每1分钟) │ │ 检查触发条件 → 发送通知 │ └──────────────────────────────────┘ ``` --- ## 快速开始 ### 本地运行 ```bash # 确保 Go 版本 >= 1.25 go version # 下载依赖 go mod download # 运行 go run main.go ``` 服务启动后访问: - 仪表板:http://localhost:8081 - 触发器管理:http://localhost:8081/triggers ### Docker 部署 ```bash # 构建镜像 chmod +x build.sh ./build.sh # 或直接构建 docker build -t api-plane:latest . # 运行容器 docker run -d \ --name api-plane \ -p 8081:8081 \ -v $(pwd)/data:/app/data \ api-plane:latest ``` > 数据目录 `data/` 用于持久化触发器配置,建议挂载到宿主机。 --- ## API 接口文档 ### 上报请求数据 上报一条 API 请求记录到监控系统。 ``` POST /api/request Content-Type: application/json ``` **请求体:** | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | `project` | string | 否 | 项目标识,默认 `default` | | `channel` | string | 否 | 渠道标识,默认 `unknown` | | `success` | bool | 是 | 请求是否成功 | | `error_type` | string | 否 | 错误类型(失败时填写) | | `duration` | int32 | 是 | 请求耗时(毫秒) | **示例:** ```bash curl -X POST http://localhost:8081/api/request \ -H "Content-Type: application/json" \ -d '{ "project": "order-center", "channel": "order-service", "success": false, "error_type": "timeout", "duration": 3500 }' ``` **响应:** ```json // 成功 {"status": "accepted"} // 队列已满 // HTTP 503 {"status": "queue full, request dropped"} ``` > 请求采用异步写入,入队后立即返回,不阻塞调用方。队列容量默认 10000,满时丢弃。 --- ### 获取统计快照 获取当前统计快照,包含双窗口数据、饼图、直方图和趋势。 ``` GET /api/stats?project=all&channel=all ``` | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | `project` | string | 否 | 项目名,默认 `all`(全部项目) | | `channel` | string | 否 | 渠道名,默认 `all`(全渠道) | **响应示例:** ```json { "windowConfig": { "shortWindow": "30m", "longWindow": "24h", "histogramBin": "1h" }, "shortWindow": { "duration": "30m", "rate": 98.5, "success": 9850, "fail": 150, "total": 10000, "trend": "+1.2%", "trendValue": 1.2, "latency": { "avg": 120.5, "p50": 85.0, "p95": 450.0, "p99": 1200.0, "max": 5000.0 }, "peakQPS": 55.32, "peakConcurrency": 12 }, "longWindow": { ... }, "errorDistPie": { "labels": ["timeout", "5xx", "unknown"], "data": [80, 50, 20], "colors": ["#ef4444", "#f97316", "#eab308"], "total": 150, "description": "共 150 次错误" }, "timeDistPie": { ... }, "histogram": [ { "timeLabel": "14:00", "success": 1200, "fail": 15, "failByType": { "timeout": 10, "5xx": 5 } } ], "failTypeColors": { "timeout": "#ef4444", "5xx": "#f97316" }, "totalRequests": 10000, "currentProject": "all", "currentChannel": "all" } ``` --- ### 配置统计窗口 动态调整短窗口和长窗口的时间范围。 ``` POST /api/config Content-Type: application/json ``` | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | `shortWindow` | string | 否 | 短窗口时长,如 `"30m"`, `"1h"`, `"2h"` | | `longWindow` | string | 否 | 长窗口时长,如 `"24h"`, `"12h"`, `"6h"` | **示例:** ```bash curl -X POST http://localhost:8081/api/config \ -H "Content-Type: application/json" \ -d '{"shortWindow": "1h", "longWindow": "48h"}' ``` > 直方图桶大小固定为 1 小时,不可配置。 --- ### 获取当前配置 ``` GET /api/config ``` **响应:** ```json { "shortWindow": "30m", "longWindow": "24h", "histogramBin": "1h" } ``` --- ### 获取项目列表 获取所有已上报数据的项目名称(按字母排序)。 ``` GET /api/projects ``` **响应:** ```json { "projects": ["order-center", "payment-center"] } ``` --- ### 获取渠道列表 获取所有已上报数据的渠道名称(可按项目过滤)。 ``` GET /api/channels?project=all ``` | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | `project` | string | 否 | 项目名,默认 `all`(全部项目) | **响应:** ```json { "channels": ["order-service", "payment-service", "user-service"] } ``` --- ### 获取项目下渠道成功率 根据项目名称返回该项目下各渠道**最近半小时**的成功率,成功率可作为流量分配权重。 ``` GET /api/project/channels?project=order-center ``` | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | `project` | string | 是 | 项目名(不传则返回全部项目) | **响应:** ```json { "project": "order-center", "channels": [ { "channel": "order-service", "rate": 98.5 }, { "channel": "user-service", "rate": 95.2 } ] } ``` > `rate` 为最近半小时(短窗口)成功率百分比,保留两位小数。 --- ### 触发器管理 #### 创建触发器 ``` POST /api/triggers Content-Type: application/json ``` | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | `name` | string | 是 | 触发器名称 | | `notifyType` | string | 是 | 通知方式,多选一:`url`(HTTP GET 请求)或 `wechat`(企业微信机器人) | | `url` | string | 条件 | 通知 URL(GET 请求,`notifyType=url` 时必填) | | `webhookKey` | string | 条件 | 企业微信机器人 webhook key(`notifyType=wechat` 时必填,webhook 地址中 `?key=` 后的部分) | | `project` | string | 否 | 监控项目,默认 `all`(全部项目) | | `channel` | string | 否 | 监控渠道,默认 `all` | | `conditionType` | string | 是 | `error_rate` 或 `error_type` | | `errorType` | string | 条件 | 错误类型(`conditionType=error_type` 时必填) | | `errorRate` | float | 条件 | 错误率阈值 %(`conditionType=error_rate` 时必填,0-100) | | `window` | string | 否 | 统计窗口,默认 `"30m"` | **示例 - 错误率告警(HTTP GET 通知):** ```bash curl -X POST http://localhost:8081/api/triggers \ -H "Content-Type: application/json" \ -d '{ "name": "订单接口错误率告警", "notifyType": "url", "url": "https://hooks.example.com/notify", "project": "order-center", "channel": "order-service", "conditionType": "error_rate", "errorRate": 5.0, "window": "10m" }' ``` **示例 - 错误率告警(企业微信机器人 markdown 通知):** ```bash curl -X POST http://localhost:8081/api/triggers \ -H "Content-Type: application/json" \ -d '{ "name": "订单接口错误率告警", "notifyType": "wechat", "webhookKey": "1a2b3c4d-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "project": "order-center", "channel": "order-service", "conditionType": "error_rate", "errorRate": 5.0, "window": "10m" }' ``` 企业微信 markdown 消息包含**项目、渠道、触发时间、触发条件**等信息。 **示例 - 错误类型告警:** ```bash curl -X POST http://localhost:8081/api/triggers \ -H "Content-Type: application/json" \ -d '{ "name": "超时错误监控", "url": "https://hooks.example.com/notify", "channel": "all", "conditionType": "error_type", "errorType": "timeout", "window": "5m" }' ``` #### 获取所有触发器 ``` GET /api/triggers ``` #### 修改触发器 ``` PUT /api/triggers/:id ``` 请求体与创建触发器一致(`name`、`notifyType`、`url`/`webhookKey`、`project`、`channel`、`conditionType` 等),`id`、`createdAt`、`enabled` 保持不变。 #### 删除触发器 ``` DELETE /api/triggers/:id ``` #### 切换启用/禁用 ``` POST /api/triggers/:id/toggle ``` #### 获取检查结果 ``` GET /api/triggers/check ``` **响应示例:** ```json { "results": [ { "triggerId": "a1b2c3d4", "triggerName": "订单接口错误率告警", "triggered": true, "currentValue": 6.2, "threshold": 5.0, "message": "错误率 6.2% 已超过阈值 5.0%", "notifyUrl": "https://hooks.example.com/notify", "notifyStatus": "sent", "notifyError": "" } ] } ``` --- ### 健康检查 ``` GET /api/health ``` **响应:** ```json {"status": "ok"} ``` --- ## 前端页面 ### 仪表板 (`/`) 暗色主题的实时监控仪表板,基于 Chart.js 渲染图表: - **顶部概览**:成功率、总请求数、失败数、平均耗时、峰值 QPS 等核心指标卡片 - **趋势对比**:短窗口和长窗口的成功率趋势箭头 - **饼图区域**:错误类型分布 + 耗时区间分布 - **直方图**:按小时展示成功/失败请求量,支持按错误类型堆叠着色 - **多级筛选**:项目 + 渠道两级下拉,切换项目时自动刷新该项目的渠道列表与统计数据 - **自动刷新**:页面定时轮询 `/api/stats` 更新数据 ### 触发器管理 (`/triggers`) 白底简洁风格的触发器管理页面: - **新建表单**:填写名称、通知 URL、项目、渠道、触发条件等 - **项目筛选**:顶部项目下拉可按项目过滤触发器列表,并同步新建表单的项目选择 - **触发器列表**:展示所有触发器状态(正常/告警/禁用),支持启用/禁用切换和删除 - **实时检测**:显示最近一次检查结果和通知发送状态 - **响应式布局**:移动端自适应 --- ## 内存优化设计 系统对内存中的请求记录进行了两项核心优化: ### 1. 结构体字段优化 `RequestRecord` 字段按大小降序排列,消除 Go 内存对齐填充: | 字段 | 类型 | 大小 | |------|------|------| | Project | string | 16 bytes | | Channel | string | 16 bytes | | ErrorType | string | 16 bytes | | Timestamp | time.Time | 24 bytes | | Duration | int32 | 4 bytes | | Success | bool | 1 byte | **总计:72 bytes / 条**(含项目字段,无对齐填充浪费) ### 2. 长窗口数据聚类 超过短窗口的旧记录不再逐条保留,而是自动聚合为 `HourlyAgg` 小时桶: ``` 原始记录(短窗口内) → 逐条保留,精确统计 │ 超过短窗口后 ↓ 自动聚合 │ 小时聚合桶(长窗口) → 每小时每项目每渠道一条,近似统计 ``` **内存效果(以每秒 100 请求为例):** | 方案 | 24小时内存占用 | |------|--------------| | 优化前(全量原始记录) | ~760 MB | | 优化后(短窗口原始 + 长窗口聚合) | ~130 MB | 内存降低约 **83%**,同时保持长窗口统计的准确性。 --- ## 项目结构 ``` api-plane/ ├── main.go # 主程序(数据结构、存储引擎、统计计算、API路由、触发器) ├── go.mod # Go Modules 依赖定义 ├── go.sum # 依赖校验文件 ├── Dockerfile # 多阶段 Docker 构建 ├── build.sh # 构建脚本(拉取代码 + 构建镜像) ├── data/ │ └── triggers.json # 触发器持久化存储 └── templates/ ├── index.html # 监控仪表板页面(暗色主题 + Chart.js) └── triggers.html # 触发器管理页面 ``` --- ## 技术栈 | 组件 | 技术 | 说明 | |------|------|------| | 语言 | Go 1.25 | 高性能编译型语言 | | Web 框架 | Gin v1.12 | 轻量级 HTTP 框架 | | 跨域 | gin-cors v1.7 | CORS 中间件 | | 前端图表 | Chart.js v3.9 | 饼图 + 直方图渲染 | | 图标 | Font Awesome v6 | UI 图标 | | 容器化 | Docker 多阶段构建 | 构建镜像 golang:alpine → 运行镜像 alpine | | 时区 | Asia/Shanghai | 容器内配置东八区时区 |