1
0

feat: 重构为多类型 checker 通用框架,支持 HTTP 与命令检查

- 引入 typed target 判别联合,支持 http 与 command 两种 checker
- expect 重构为有序规则数组,按配置顺序快速失败并生成结构化 failure
- 新增 command runner,支持 exec + args 本地命令执行
- 引入全局并发限制 maxConcurrentChecks 和 size 解析 (KB/MB/GB)
- HTTP/command 各自独立 expect pipeline,应用领域默认成功语义
- SQLite schema、API、Dashboard 全链路调整为 checker 通用契约
- 补充完整测试覆盖(192 tests),更新 README 与示例配置
This commit is contained in:
2026-05-10 22:25:21 +08:00
parent 599d973cbd
commit b8810f1182
46 changed files with 3562 additions and 1062 deletions

160
README.md
View File

@@ -1,6 +1,6 @@
# Gateway Checker
基于 Bun + TypeScript 的 HTTP 拨测监控工具。通过 YAML 配置文件定义拨测目标,后端按配置定时并发拨测,结果持久化到本地 SQLite前端 Dashboard 展示各目标实时状态、可用率、延迟趋势等。
基于 Bun + TypeScript 的多类型拨测监控工具。通过 YAML 配置文件定义 HTTP 和命令行拨测目标,后端按配置定时并发拨测,结果持久化到本地 SQLite前端 Dashboard 展示各目标实时状态、可用率、耗时趋势等。
## 项目结构
@@ -12,11 +12,16 @@ src/
dev.ts 开发期启动入口
server.ts HTTP server 启动
checker/
types.ts 类型定义
types.ts 类型定义
config-loader.ts YAML 配置解析与校验
store.ts SQLite 数据存储
fetcher.ts HTTP 拨测执行
engine.ts 调度引擎(按 interval 分组、组内并发)
store.ts SQLite 数据存储
http-runner.ts HTTP 拨测执行
command-runner.ts 命令行拨测执行
http-expect.ts HTTP 响应断言
command-expect.ts 命令行输出断言
failure.ts 失败信息类型
size.ts 大小单位解析
engine.ts 调度引擎(按 interval 分组、组内并发)
shared/
api.ts 前后端共享 TypeScript 类型
web/ Vite + React 前端 Dashboard
@@ -52,48 +57,65 @@ bun run dev:web
server:
host: "127.0.0.1"
port: 3000
dataDir: "./data"
dataDir: "/tmp/probes_data"
runtime:
maxConcurrentChecks: 20
defaults:
interval: "30s"
interval: "5s"
timeout: "10s"
method: "GET"
http:
method: GET
maxBodyBytes: "100MB"
command:
maxOutputBytes: "100MB"
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}'
- name: "Baidu"
type: http
http:
url: "https://www.baidu.com"
expect:
status: [200]
maxLatencyMs: 5000
maxDurationMs: 10000
- name: "JSON API 监控"
url: "https://httpbin.org/json"
- name: "JSON API 示例"
type: http
http:
url: "https://httpbin.org/json"
expect:
status: [200]
headers:
Content-Type: application/json
Content-Type:
contains: "application/json"
body:
contains: "slideshow"
json:
$.slideshow.title: "Sample Slide Show"
- contains: "slideshow"
- json:
path: "$.slideshow.title"
equals: "Sample Slide Show"
- name: "HTML 页面监控"
url: "https://httpbin.org/html"
- name: "HTML 页面示例"
type: http
http:
url: "https://httpbin.org/html"
expect:
status: [200]
body:
css:
"h1": "Herman Melville - Moby-Dick"
xpath:
"/html/body/h1/text()": "Herman Melville - Moby-Dick"
- contains: "Moby-Dick"
- xpath:
path: "/html/body/h1/text()"
equals: "Herman Melville - Moby-Dick"
- name: "Nginx 进程检查"
type: command
command:
exec: "pgrep"
args: ["nginx"]
expect:
exitCode: [0]
stdout:
- match: "\\d+"
```
### 配置说明
@@ -102,39 +124,67 @@ targets:
- `host`: 监听地址,默认 `127.0.0.1`
- `port`: 监听端口,默认 `3000`
- `dataDir`: 数据目录,默认 `./data`
- **runtime**: 运行时配置
- `maxConcurrentChecks`: 最大并发拨测数,默认 `20`
- **defaults**: 全局默认值(均可省略)
- `interval`: 拨测间隔,默认 `30s`
- `timeout`: 请求超时,默认 `10s`
- `method`: HTTP 方法,默认 `GET`
- `headers`: 全局 headers
- `timeout`: 超时时间,默认 `10s`
- `http`: HTTP 类型默认值
- `method`: HTTP 方法,默认 `GET`
- `maxBodyBytes`: 响应体最大字节数,默认 `100MB`
- `command`: Command 类型默认值
- `maxOutputBytes`: 输出最大字节数,默认 `100MB`
- **targets**: 拨测目标列表(必填)
- `name`: 目标名称(必填,唯一)
- `url`: 目标 URL(必填)
- `method``headers``body`: 请求参数
- `type`: 目标类型,`http``command`(必填)
- `http`: HTTP 拨测配置type 为 http 时必填)
- `url`: 目标 URL
- `method``headers``body`: 请求参数
- `command`: 命令行拨测配置type 为 command 时必填)
- `exec`: 可执行文件名或路径
- `args`: 命令行参数列表
- `interval``timeout`: 覆盖全局默认值
- `expect`: 期望校验
- `status`: 可接受的状态码列表
- `headers`: 响应头校验(键值对,全部匹配
- `maxLatencyMs`: 最大延迟阈值(毫秒
- `body`: 响应体校验(可组合使用
- `status`: 可接受的状态码列表HTTP
- `exitCode`: 可接受的退出码列表Command
- `headers`: 响应头校验HTTP支持 `equals``contains` 等操作符
- `maxDurationMs`: 最大耗时阈值(毫秒
- `body`: HTTP 响应体校验(数组,可组合使用)
- `contains`: 响应体包含的文本
- `regex`: 响应体匹配的正则表达式
- `json`: JSONPath 提取值比较(路径 → 期望值
- `css`: CSS 选择器提取 HTML 元素比较(选择器 → 期望值,可选 `attr` 提取属性)
- `xpath`: XPath 提取 XML/HTML 节点比较(路径 → 期望值)
- body 比较支持操作符:`equals`(默认)、`contains``match`(正则)、`empty``exists``gte``lte``gt``lt`
- `match`: 响应体匹配的正则表达式
- `json`: JSONPath 提取值比较(`path` + 比较操作符
- `css`: CSS 选择器提取 HTML 元素比较
- `xpath`: XPath 提取 XML/HTML 节点比较
- `stdout` / `stderr`: Command 输出校验(数组,同 body 格式)
- 比较操作符:`equals`(默认)、`contains``match`(正则)、`empty``exists``gte``lte``gt``lt`
大小说明:`maxBodyBytes``maxOutputBytes` 支持单位 `KB``MB``GB`,也可直接使用数字(字节数)。
时长格式支持:`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` | 指定目标的按小时聚合趋势 |
| 端点 | 说明 |
| --------------------------------------- | ----------------------------------------------------- |
| `GET /health` | 健康检查 |
| `GET /api/summary` | 总览统计total/up/down/avgDurationMs/lastCheckTime |
| `GET /api/targets` | 目标列表及最新状态和统计摘要 |
| `GET /api/targets/:id/history?limit=20` | 指定目标的最近 N 条拨测记录 |
| `GET /api/targets/:id/trend?hours=24` | 指定目标的按小时聚合趋势 |
### 响应字段
**SummaryResponse**: `total``up``down``avgDurationMs``lastCheckTime`
**TargetStatus**: `id``name``type`http/command`target`URL 或命令摘要)、`interval``latestCheck``stats``sparkline`
**CheckResult**: `timestamp``success``matched``durationMs``statusDetail``failure`
**CheckFailure**: `kind`error/mismatch`phase``path``expected``actual``message`
**TargetStats**: `totalChecks``availability``avgDurationMs``p99DurationMs`
**TrendPoint**: `hour``avgDurationMs``availability``totalChecks`
## 代码质量
@@ -190,13 +240,13 @@ bun run verify
## 目标状态判定
两层判定模型:
两层判定模型,适用于 HTTP 和 Command 两种类型
- **success**: 请求是否成功完成(收到 HTTP 响应
- **success**: 拨测是否成功完成HTTP 收到响应 / Command 正常退出
- **matched**: 是否符合 expect 规则(无 expect 时默认为 true
- **UP** = success AND matched
- **DOWN** = NOT success OR NOT matched
## 已知限制
当前不做告警通知、数据自动清理、拨测目标动态增删、认证鉴权和分布式部署。
当前不做告警通知、数据自动清理、拨测目标动态增删、认证鉴权和分布式部署。Command 类型拨测不支持 Windows 环境。