1
0

feat: 将 demo 项目转化为 HTTP 拨测监控工具

新增 YAML 配置解析(Bun 内置 YAML)、SQLite 数据存储(bun:sqlite)、按 interval 分组并发拨测引擎、REST API(/api/summary、/api/targets、/api/targets/:id/history、/api/targets/:id/trend)、React 前端 Dashboard(统计卡片、目标表格、可展开详情面板、recharts 趋势图)。CLI 简化为仅接受配置文件路径。移除 /api/demo 路由和相关 demo 代码。保留 /health、静态资源服务和 SPA fallback。
This commit is contained in:
2026-05-09 17:04:25 +08:00
parent 9267f6585c
commit 57d3a5cfb4
43 changed files with 2910 additions and 525 deletions

168
README.md
View File

@@ -1,53 +1,113 @@
# Gateway Checker
基于 Bun + TypeScript 的前后端一体化 demo。开发期使用 Vite + React 提供前端 HMR后端由 Bun 提供 API生产期先构建前端静态资源再将前端资源和 Bun 后端打包为单个 executable
基于 Bun + TypeScript 的 HTTP 拨测监控工具。通过 YAML 配置文件定义拨测目标,后端按配置定时并发拨测,结果持久化到本地 SQLite前端 Dashboard 展示各目标实时状态、可用率、延迟趋势等
## 项目结构
```text
src/
server/ Bun 后端运行时、API、静态资源 fallback
shared/ 前后端共享 TypeScript 类型
web/ Vite + React 前端 demo
scripts/ 开发、构建和 smoke test 脚本
tests/ Bun test 测试
openspec/ OpenSpec 变更与规格文档
server/
app.ts Bun HTTP 路由API + 静态资源 + SPA fallback
config.ts CLI 参数解析
dev.ts 开发期启动入口
server.ts HTTP server 启动
checker/
types.ts 类型定义
config-loader.ts YAML 配置解析与校验
store.ts SQLite 数据存储
fetcher.ts HTTP 拨测执行
engine.ts 调度引擎(按 interval 分组、组内并发)
shared/
api.ts 前后端共享 TypeScript 类型
web/ Vite + React 前端 Dashboard
components/ UI 组件
hooks/ 数据轮询 hooks
scripts/ 开发、构建和 smoke test 脚本
tests/ Bun test 测试
openspec/ OpenSpec 变更与规格文档
```
## 开发命令
## 快速开始
```bash
bun install
bun run dev
cp probes.example.yaml probes.yaml
bun run dev probes.yaml
```
`bun run dev` 会同时启动
- Bun 后端:默认 `http://127.0.0.1:3000`
- Vite 前端:默认 `http://127.0.0.1:5173`
开发期请打开 Vite 前端地址。前端通过相对路径 `/api/demo` 调用后端Vite 会把 `/api/*` 代理到 Bun 后端,因此浏览器不需要 CORS 配置。
全栈开发命令使用 `PORT` 作为后端端口覆盖来源,并将同一端口传给 Vite proxy
```bash
PORT=4000 bun run dev
```
`bun run dev` 会同时启动 Bun 后端和 Vite 前端。开发期请打开 Vite 前端地址 `http://127.0.0.1:5173`
也可以分别运行:
```bash
bun run dev:server
bun run dev:server probes.yaml
bun run dev:web
```
分别运行时,若后端不是默认 `3000` 端口,需要为 Vite 指定同一个后端端口:
## 配置文件
```bash
PORT=4000 bun run dev:server
BACKEND_PORT=4000 bun run dev:web
程序通过 YAML 配置文件定义所有运行参数:
```yaml
server:
host: "127.0.0.1"
port: 3000
dataDir: "./data"
defaults:
interval: "30s"
timeout: "10s"
method: "GET"
targets:
- name: "示例服务"
url: "https://httpbin.org/get"
interval: "60s"
- name: "POST 检查"
url: "https://httpbin.org/post"
method: "POST"
headers:
Content-Type: "application/json"
body: '{"ping": true}'
expect:
status: [200]
maxLatencyMs: 5000
```
### 配置说明
- **server**: 服务配置(均可省略,使用默认值)
- `host`: 监听地址,默认 `127.0.0.1`
- `port`: 监听端口,默认 `3000`
- `dataDir`: 数据目录,默认 `./data`
- **defaults**: 全局默认值(均可省略)
- `interval`: 拨测间隔,默认 `30s`
- `timeout`: 请求超时,默认 `10s`
- `method`: HTTP 方法,默认 `GET`
- `headers`: 全局 headers
- **targets**: 拨测目标列表(必填)
- `name`: 目标名称(必填,唯一)
- `url`: 目标 URL必填
- `method``headers``body`: 请求参数
- `interval``timeout`: 覆盖全局默认值
- `expect`: 期望校验
- `status`: 可接受的状态码列表
- `bodyContains`: 响应体包含的文本
- `maxLatencyMs`: 最大延迟阈值(毫秒)
时长格式支持:`30s``5m``500ms`
## API 端点
| 端点 | 说明 |
|------|------|
| `GET /health` | 健康检查 |
| `GET /api/summary` | 总览统计total/up/down/avgLatencyMs/lastCheckTime |
| `GET /api/targets` | 目标列表及最新状态和统计摘要 |
| `GET /api/targets/:id/history?limit=20` | 指定目标的最近 N 条拨测记录 |
| `GET /api/targets/:id/trend?hours=24` | 指定目标的按小时聚合趋势 |
## 代码质量
```bash
@@ -57,23 +117,7 @@ bun run format
bun run check
```
- `lint` 使用 ESLint 检查 TypeScript、React Hooks 和前后端边界
- `format:check` 使用 Prettier 检查代码格式。
- `format` 使用 Prettier 重写受管理文件格式。
- `check` 依次运行 `typecheck``lint``format:check` 和单元测试,适合日常开发期间快速验证。
Prettier 不格式化 `openspec/``dist/``.build/``node_modules/``bun.lock` 和临时构建产物。
## Demo 验证
开发期打开 `http://127.0.0.1:5173`,页面应显示 `/api/demo` 返回的后端 message、Bun 版本、平台和响应时间。
直接验证 API
```bash
curl http://127.0.0.1:3000/api/demo
curl http://127.0.0.1:3000/health
```
- `check` 依次运行 `typecheck``lint``format:check` 和单元测试
## 构建 executable
@@ -83,31 +127,23 @@ bun run build
构建流程:
- 运行 `vite build`,输出前端资源到 `dist/web`
- 生成临时 `.build/static-assets.ts`用 Bun file import 嵌入 Vite 产物
- 生成临时 `.build/server-entry.ts`,作为生产 executable 的 server 入口
- 运行 `Bun.build({ compile })`,输出 `dist/gateway-checker`
1. 运行 `vite build`,输出前端资源到 `dist/web`
2. 生成临时 `.build/static-assets.ts`,嵌入 Vite 产物
3. 生成临时 `.build/server-entry.ts`,作为生产入口
4. 运行 `Bun.build({ compile })`,输出 `dist/gateway-checker`
运行 executable
```bash
./dist/gateway-checker
./dist/gateway-checker probes.yaml
```
生产期默认访问 `http://127.0.0.1:3000`。同一个 executable 会服务 `/api/demo``/health``/assets/*` 和前端 SPA fallback。
## 运行参数
默认配置:
- `HOST=127.0.0.1`
- `PORT=3000`
可以通过环境变量或 CLI 参数覆盖:
CLI 只接受一个参数YAML 配置文件路径。
```bash
PORT=4000 ./dist/gateway-checker
./dist/gateway-checker --host 0.0.0.0 --port 4000
./dist/gateway-checker ./probes.yaml
```
## 测试
@@ -118,15 +154,21 @@ bun run verify
```
- `check` 适合日常开发包含类型检查、lint、格式检查和单元测试。
- `verify` 适合提交前或发布前,先运行 `check`,再重新构建生产 executable 并运行 smoke test。
- `test:smoke` 会启动生成的 executable并检查 `/api/demo``/health`、前端根路径、静态资源、未知 API、未知静态资源、生产模式、缓存响应头、低风险安全响应头和 SPA fallback。
- `verify` 先运行 `check`,再重新构建生产 executable 并运行 smoke test。
## 前后端边界
前端只通过 HTTP 调用后端,默认 API 路径为相对 `/api/*`。共享类型放在 `src/shared`,前端不得 import `src/server` 的运行时实现。
前端只通过 HTTP 调用后端API 路径为 `/api/*`。共享类型放在 `src/shared`,前端不得 import `src/server` 的运行时实现。
这保证了当前可以单文件部署,也保留未来将前端拆到 CDN 或独立静态站点的路径。
## 目标状态判定
两层判定模型:
- **success**: 请求是否成功完成(收到 HTTP 响应)
- **matched**: 是否符合 expect 规则(无 expect 时默认为 true
- **UP** = success AND matched
- **DOWN** = NOT success OR NOT matched
## 已知限制
当前 demo 不包含数据库、认证、SSR、React Router 或 UI 组件库。单 executable 是按目标平台构建的产物,不是一个文件同时覆盖 macOS、Linux 和 Windows
当前不做告警通知、数据自动清理、拨测目标动态增删、认证鉴权和分布式部署