mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-09-29 05:56:38 +08:00
f783a1e6fa
Tabs for analysis/config, dual-axis RPS chart with overview filters and average RPS rankings from access-log overview.
218 lines
7.5 KiB
Markdown
218 lines
7.5 KiB
Markdown
# 限流页请求压力分析设计
|
||
|
||
日期:2026-07-19
|
||
状态:已评审待实现
|
||
方案:Tabs(分析 / 配置)+ 专用 ECharts 双轴压力图(方案 A)
|
||
|
||
## 背景
|
||
|
||
`/rate-limits` 当前仅为管理员配置全局 OpenResty 默认限流(`limit_conn_*` / `limit_rate`),无请求压力可视化。
|
||
|
||
访问日志概览已提供:
|
||
|
||
- 过滤:时间预设 `24h | 7d | 15d | 30d` + 域名多选 `hosts[]`
|
||
- 数据:`GET /api/v1/d/access-logs/overview` → 小时桶 `trends.requests` / `trends.visits`,以及 `top_hosts` / `top_ips`(窗口总请求数)
|
||
- 图表:共享 `TrendChart` 为**单 Y 轴**;仓库内无 ECharts `dataZoom`、无双轴指标图
|
||
|
||
需求:在限流页展示当前请求压力(RPS),默认 24 小时,图表样式对齐「双轴时序面积折线 + 底部缩放条」描述,过滤复用访问日志概览组件,并增加域名/IP 平均 RPS 排行。
|
||
|
||
## 目标
|
||
|
||
1. `/rate-limits` 改为 Tabs:**分析**(默认)/ **配置**。
|
||
2. 分析 Tab:概览式过滤 + RPS/访客双轴主图 + 域名/IP 平均 RPS 排行。
|
||
3. 配置 Tab:迁入现有全局默认限流表单,行为不变。
|
||
4. 数据复用 `AccessLogService.getOverview`,不新增后端 API。
|
||
5. 主图为**专用** ECharts 组件,不扩展共享 `TrendChart`。
|
||
|
||
## 非目标
|
||
|
||
- 新 RPS 时序 API 或峰值桶 RPS 排行接口
|
||
- 给通用 `TrendChart` 增加双轴 / dataZoom
|
||
- 配置 Tab 限流语义变更
|
||
- 分析过滤支持 node_id / IP / path(概览亦无)
|
||
- 英文文档
|
||
|
||
## 页面信息架构
|
||
|
||
**路由:** `/rate-limits`(导航「安全性 → 限流」不变)
|
||
|
||
| Tab | 内容 |
|
||
|-----|------|
|
||
| **分析**(默认) | 过滤条 → `RatePressureChart` → 双排行榜 |
|
||
| **配置** | 现有三项全局默认限流表单 + 保存 + 链到版本发布 |
|
||
|
||
可选:`?tab=config` 直达配置;默认 `analysis`。
|
||
|
||
**权限:** 仅管理员(与现页一致)。
|
||
|
||
**分析 Tab 自上而下:**
|
||
|
||
1. **过滤条**(与访问日志概览一致)
|
||
- 时间:`24 | 168 | 360 | 720` 小时,默认 **24**
|
||
- 域名:Zone 树多选 → `hosts[]`
|
||
2. **主图卡片** `RatePressureChart`
|
||
3. **排行榜**(并排)
|
||
- 平均 RPS 最高域名
|
||
- 平均 RPS 最高 IP
|
||
|
||
## 数据与状态
|
||
|
||
### 查询
|
||
|
||
```ts
|
||
AccessLogService.getOverview({
|
||
hours: overviewHours,
|
||
hosts: overviewHosts.length > 0 ? overviewHosts : undefined,
|
||
})
|
||
// queryKey: ['openflare', 'rate-limits', 'overview', hours, hosts]
|
||
```
|
||
|
||
- 过滤变更 → 重新请求 overview
|
||
- 图表 `dataZoom` **仅**前端缩放已加载序列,**不**改 `hours`、**不**触发 refetch
|
||
|
||
### 指标定义
|
||
|
||
| 序列 | 源字段 | 换算 | 轴 |
|
||
|------|--------|------|-----|
|
||
| 请求速率 (RPS) | `trends.requests[].value` | `value / 3600`(概览固定 1h 桶) | 左 Y |
|
||
| 独立访客 | `trends.visits[].value` | 桶内 UV,不换算 | 右 Y |
|
||
|
||
- 时间点:`bucket_started_at`
|
||
- Tooltip:时间 + RPS(如 `12.3 req/s`)+ 访客数
|
||
- 空数据 / 加载 / 错误:对齐访问日志概览空态与 `ErrorInline` / loading
|
||
|
||
### 排行口径
|
||
|
||
窗口**平均** RPS(与 dashboard `estimated_qps` 一致):
|
||
|
||
```
|
||
avgRps = total_requests / (hours * 3600)
|
||
```
|
||
|
||
- 域名:`top_hosts[]` 的 `value` 为窗口总请求数 → 换算后展示
|
||
- IP:`top_ips[]` 同理
|
||
- 标题:「平均 RPS 最高域名」「平均 RPS 最高 IP」
|
||
- 副文案标明窗口(如「近 24 小时平均」)
|
||
- UI 组件:现有 `RankCard` / `RankChart`
|
||
|
||
**不是**峰值小时桶 RPS;避免新 API。
|
||
|
||
## 主图组件 `RatePressureChart`
|
||
|
||
### 布局(对齐产品描述)
|
||
|
||
1. **外部卡片**:圆角、边框/轻阴影,扁平矩形
|
||
2. **顶部控制栏**
|
||
- 左:主标题「请求压力」(字号加粗)
|
||
- 右:时钟图标 + 当前查询窗口起止(由 `hours` 与「现在」推算本地时间,`YYYY-MM-DD HH:mm:ss`)
|
||
3. **图例与轴标识**
|
||
- 左上:左轴属性「RPS」
|
||
- 右上:图例圆点 +「请求速率」「独立访客」
|
||
- 最右:右轴单位「访客 / 桶」
|
||
4. **主绘制区**
|
||
- 双 Y 轴:左 RPS 从 0 递增;右访客从 0 递增
|
||
- X 轴:时间,标签两行(月-日 / 时:分),可复用 `formatOverviewTrendLabel` 思路
|
||
- 水平等距虚线网格
|
||
- 面积 + 折线,半透明填充,两序列可重叠
|
||
5. **底部 dataZoom slider**
|
||
- ECharts `dataZoom: [{ type: 'slider', ... }]`
|
||
- 宽度对齐绘图区;左右手柄;内嵌缩略波动线
|
||
- 仅影响可见区间
|
||
|
||
### 实现约束
|
||
|
||
- 新建专用组件,**不要**给 `TrendChart` 加 dualY/dataZoom
|
||
- 库:`echarts` + `echarts-for-react`(与看板一致)
|
||
- 颜色使用主题/CSS 变量或与访问日志趋势相近的语义色,避免硬编码与 shadcn 变体冲突时可参考现有 `TrendChart` 系列色
|
||
|
||
## 过滤组件复用
|
||
|
||
优先从 `frontend/app/(main)/access-logs/components/overview-tab.tsx` **抽出**:
|
||
|
||
- `OverviewToolbar`(或等价)
|
||
- `OverviewHostFilter`
|
||
- 依赖的 `OVERVIEW_RANGE_OPTIONS` / `OverviewRangeHours` 已在 `access-log-utils.ts`
|
||
|
||
落点建议:
|
||
|
||
- 仍放在 `access-logs/components/` 并 export,限流分析 import;或
|
||
- 若跨模块更清晰,迁到 `frontend/components/common/`(仅当确实跨页面复用且避免循环依赖时)
|
||
|
||
**验收:** 访问日志概览过滤行为与抽出前一致。
|
||
|
||
## 文件结构
|
||
|
||
```
|
||
frontend/app/(main)/rate-limits/
|
||
page.tsx # Tabs、权限、分析/配置挂载
|
||
components/
|
||
analysis-tab.tsx # 过滤 + 图 + 排行 + overview query
|
||
rate-pressure-chart.tsx # 双轴 + dataZoom
|
||
config-tab.tsx # 现有 Option 表单逻辑迁入
|
||
```
|
||
|
||
可选抽出:
|
||
|
||
```
|
||
frontend/app/(main)/access-logs/components/
|
||
overview-toolbar.tsx # 从 overview-tab 抽出
|
||
overview-host-filter.tsx
|
||
```
|
||
|
||
后端:无变更。
|
||
|
||
## 边界与兼容
|
||
|
||
| 场景 | 行为 |
|
||
|------|------|
|
||
| 无日志 / ClickHouse 空 | 图与排行空态 |
|
||
| 仅选域名 | overview 带 `hosts[]` |
|
||
| dataZoom 拖动 | 不请求后端 |
|
||
| 非管理员 | 空态「权限不足」 |
|
||
| 书签 `/rate-limits` | 默认分析 Tab |
|
||
| 配置保存 | 仍 invalidate options / config-preview / config-versions |
|
||
|
||
## 测试与验收
|
||
|
||
### 自动化(按项目习惯)
|
||
|
||
- 若有 vitest:过滤 props 透传、`avgRps` 换算纯函数单测
|
||
- 图表以手工/视觉验收为主(ECharts 难做快照)
|
||
|
||
### 验收标准
|
||
|
||
1. 默认进入分析 Tab,24h,主图展示 RPS + 访客
|
||
2. 切换 7d / 域名后图与排行刷新
|
||
3. dataZoom 仅改变可见时间范围
|
||
4. 排行展示平均 RPS,不是原始请求总数(文案明确「平均」)
|
||
5. 配置 Tab 可读写三项默认限流并保存
|
||
6. 访问日志概览过滤不回归
|
||
7. `make prettier`;相关 typecheck/lint 通过
|
||
|
||
## 文档
|
||
|
||
- 本设计:`docs/superpowers/specs/2026-07-19-rate-limit-analytics-design.md`
|
||
- 实现时:`docs/changelog/index.md` `[Unreleased]` 补充用户可见条目
|
||
- 纯 UI/分析展示,无新 system config 键
|
||
|
||
## 实现落点索引
|
||
|
||
| 区域 | 路径 |
|
||
|------|------|
|
||
| 限流页 | `frontend/app/(main)/rate-limits/` |
|
||
| 概览过滤复用 | `access-logs/components/overview-tab.tsx` 等 |
|
||
| Overview API | `AccessLogService.getOverview` |
|
||
| 排行 UI | `components/data/rank-card.tsx` |
|
||
| 趋势参考 | `components/data/trend-chart.tsx`(只参考样式,不扩展) |
|
||
|
||
## 决策摘要
|
||
|
||
| 决策 | 选择 |
|
||
|------|------|
|
||
| 页面结构 | Tabs:分析 / 配置 |
|
||
| 双轴 | 左 RPS,右 独立访客/桶 |
|
||
| 过滤 | 概览过滤 + 默认 24h 预设 |
|
||
| 排行 | 窗口平均 RPS = 总请求 / 窗口秒数 |
|
||
| 图表实现 | 专用 ECharts 组件(方案 A) |
|
||
| 后端 | 无新 API |
|