docs: 重构文档体系
This commit is contained in:
714
README.md
714
README.md
@@ -12,29 +12,14 @@
|
||||
|
||||
DiAL 是一个自托管的拨测监控工具,支持 **HTTP**、**命令行**、**数据库**、**TCP**、**UDP**、**DNS**、**ICMP** 和 **LLM** 多种拨测类型。通过 YAML 配置文件定义拨测目标,后端定时并发执行拨测并将结果持久化到本地 SQLite,前端 Dashboard 展示各目标的实时状态、可用率和耗时趋势。
|
||||
|
||||
**功能亮点:**
|
||||
## 功能亮点
|
||||
|
||||
- 多种拨测类型:HTTP(GET/POST/PUT 等)、Cmd(命令行执行)、DB(PostgreSQL/MySQL/SQLite)、TCP(端口可达性 + Banner 探测)、UDP(自定义 payload 请求-响应)、DNS(本机解析检查 + DNS server 深度拨测)、ICMP(存活检测、延迟、丢包率)、LLM(大模型服务应用层健康检查)
|
||||
- 丰富的校验规则:状态码、响应头、JSONPath、CSS 选择器、XPath、正则匹配、数值比较等
|
||||
- 结构化观测数据:检查结果保留按需读取的 HTTP body 预览、TCP/UDP 响应摘要、ICMP 丢包率、CMD 输出预览、LLM token 用量等 observation,便于排障和后续分析
|
||||
- 响应式 Dashboard:实时状态、可用率统计、动态粒度趋势图(avg/P95 + 状态条)、手动/自动刷新、版本号展示
|
||||
- 多类型拨测:HTTP、Cmd、DB、TCP、UDP、DNS、ICMP、LLM
|
||||
- 丰富校验规则:状态码、响应头、JSONPath、CSS 选择器、XPath、正则匹配、数值比较等
|
||||
- 结构化观测数据:HTTP body 预览、TCP/UDP 响应摘要、ICMP 丢包率、CMD 输出、LLM token 用量等
|
||||
- 内置 Dashboard:实时状态、可用率统计、趋势图、最近状态条、手动/自动刷新、版本号展示
|
||||
- 多主题支持:系统、明亮、黑暗三种主题模式
|
||||
- 零外部依赖:数据存储使用 SQLite,无需额外数据库服务
|
||||
|
||||
## 版本管理
|
||||
|
||||
DiAL 使用 `package.json.version` 作为唯一版本源,Dashboard Header 展示当前运行实例版本号(如 `v0.1.0`)。
|
||||
|
||||
**版本升迁命令:**
|
||||
|
||||
```bash
|
||||
bun run version:patch # 升迁 patch 版本(0.1.0 -> 0.1.1)
|
||||
bun run version:minor # 升迁 minor 版本(0.1.0 -> 0.2.0)
|
||||
bun run version:major # 升迁 major 版本(0.1.0 -> 1.0.0)
|
||||
bun run version:set 0.2.0 # 显式设置版本
|
||||
```
|
||||
|
||||
版本升迁仅更新 `package.json`,不自动创建 git commit、tag 或 changelog。
|
||||
- 自托管部署:本地 SQLite 存储,无需额外数据库服务
|
||||
|
||||
## 应用截图
|
||||
|
||||
@@ -50,693 +35,54 @@ bun run version:set 0.2.0 # 显式设置版本
|
||||
ICMP checker 依赖系统 `ping` 命令。精简容器镜像需额外安装,例如 Alpine 可安装 `iputils-ping`。
|
||||
|
||||
```bash
|
||||
# 克隆仓库
|
||||
git clone https://github.com/your-org/DiAL.git
|
||||
cd DiAL
|
||||
|
||||
# 安装依赖
|
||||
bun install
|
||||
|
||||
# 复制示例配置并按需修改
|
||||
cp probes.example.yaml probes.yaml
|
||||
|
||||
# 启动开发服务器
|
||||
bun run dev probes.yaml
|
||||
```
|
||||
|
||||
`bun run dev` 会同时启动 Vite 开发服务器(`http://127.0.0.1:5173`)和 API 服务器(`http://127.0.0.1:3000`),访问前端地址即可使用 Dashboard。
|
||||
|
||||
## 生产部署
|
||||
|
||||
```bash
|
||||
# 构建
|
||||
bun run build
|
||||
|
||||
# 运行
|
||||
./dist/dial-server ./probes.yaml
|
||||
```
|
||||
|
||||
构建产物为独立可执行文件,只需一个 YAML 配置文件即可运行。
|
||||
|
||||
### Docker 部署
|
||||
|
||||
DiAL 提供基于 Alpine 的多阶段镜像。构建阶段使用 Bun 生成 musl 目标单可执行文件,运行阶段只包含 `dial-server`、基础证书、`ping`、musl executable 必需运行库、时区数据和容器运行所需目录。
|
||||
|
||||
```bash
|
||||
# 构建当前架构镜像
|
||||
docker build -t dial:alpine .
|
||||
|
||||
# 运行容器,使用内置容器配置示例
|
||||
docker run --rm -p 3000:3000 -v dial-data:/data/dial dial:alpine
|
||||
|
||||
# 使用自定义配置文件
|
||||
docker run --rm -p 3000:3000 \
|
||||
-v "$PWD/docker/probes.yaml:/etc/dial/probes.yaml:ro" \
|
||||
-v dial-data:/data/dial \
|
||||
dial:alpine
|
||||
```
|
||||
|
||||
容器默认读取 `/etc/dial/probes.yaml`,推荐将数据卷挂载到 `/data/dial`。容器专用示例配置位于 [`docker/probes.yaml`](docker/probes.yaml),默认监听 `0.0.0.0:3000`,并将 SQLite 数据和日志写入 `/data/dial`。
|
||||
|
||||
多架构镜像可通过 Docker Buildx 构建:
|
||||
|
||||
```bash
|
||||
docker buildx build --platform linux/amd64,linux/arm64 -t dial:alpine .
|
||||
```
|
||||
|
||||
如需在容器中运行 ICMP checker,除镜像内置的 `iputils-ping` 外,还需要授予 `NET_RAW` capability:
|
||||
|
||||
```bash
|
||||
docker run --rm --cap-add=NET_RAW -p 3000:3000 -v dial-data:/data/dial dial:alpine
|
||||
```
|
||||
|
||||
官方镜像不内置 `bun`、`node`、`curl`、`dig`、`psql`、`mysql`、`redis-cli` 等 CMD checker 可能需要的额外命令。需要这些命令时请使用派生镜像自行安装:
|
||||
|
||||
```dockerfile
|
||||
FROM dial:alpine
|
||||
|
||||
USER root
|
||||
RUN apk add --no-cache curl bind-tools postgresql-client
|
||||
USER dial
|
||||
```
|
||||
|
||||
### 跨平台发布打包
|
||||
|
||||
```bash
|
||||
# 编译全部 7 个目标平台
|
||||
bun run release
|
||||
|
||||
# 编译指定平台
|
||||
bun run release --target linux-x64
|
||||
bun run release --target linux-x64,windows-x64,darwin-arm64
|
||||
```
|
||||
|
||||
支持的目标平台:`linux-x64`、`linux-arm64`、`linux-x64-musl`、`linux-arm64-musl`、`windows-x64`、`darwin-x64`、`darwin-arm64`
|
||||
|
||||
**产出物结构:**
|
||||
|
||||
```
|
||||
dist/release/
|
||||
├── binaries/ ← 裸二进制(带版本号和平台标识)
|
||||
│ ├── dial-server-0.1.0-linux-x64
|
||||
│ ├── dial-server-0.1.0-windows-x64.exe
|
||||
│ └── ...
|
||||
└── packages/ ← tar.gz 压缩包 + SHA256 校验和
|
||||
├── dial-server_0.1.0_linux_x64.tar.gz
|
||||
├── dial-server_0.1.0_linux_x64.tar.gz.sha256
|
||||
└── ...
|
||||
```
|
||||
|
||||
压缩包内含可执行文件、`probes.example.yaml` 和 `LICENSE`,解压后可直接使用。
|
||||
|
||||
## 配置文件
|
||||
|
||||
程序通过 YAML 配置文件定义所有运行参数,完整示例参见 [`probes.example.yaml`](probes.example.yaml)。
|
||||
|
||||
### 配置文件结构
|
||||
## 最小配置示例
|
||||
|
||||
```yaml
|
||||
# yaml-language-server: $schema=./probe-config.schema.json
|
||||
|
||||
server: # 服务配置(均可省略)
|
||||
listen:
|
||||
host: "127.0.0.1"
|
||||
port: "${server_port}"
|
||||
storage:
|
||||
dataDir: "/tmp/probes_data"
|
||||
retention: "${retention}"
|
||||
logging:
|
||||
level: "${log_level|info}"
|
||||
file:
|
||||
path: "<dataDir>/logs/dial.log"
|
||||
|
||||
probes: # 拨测运行时配置(可省略)
|
||||
execution:
|
||||
maxConcurrentChecks: "${max_checks}"
|
||||
|
||||
variables: # 配置变量(可省略)
|
||||
env_name: "生产"
|
||||
base_url: "https://api.example.com"
|
||||
server_port: 3000
|
||||
retention: "7d"
|
||||
max_checks: 20
|
||||
default_interval: "30s" # 通过变量在多个 target 间共享常用值
|
||||
default_timeout: "10s"
|
||||
|
||||
targets: # 拨测目标列表(必填)
|
||||
targets:
|
||||
- id: "baidu-home"
|
||||
name: "Baidu"
|
||||
type: http
|
||||
http:
|
||||
url: "https://www.baidu.com"
|
||||
expect:
|
||||
# ...
|
||||
- id: "my-cmd"
|
||||
name: "脚本检查"
|
||||
type: cmd
|
||||
cmd:
|
||||
# ...
|
||||
expect:
|
||||
# ...
|
||||
# ... 更多 targets
|
||||
status: [200]
|
||||
durationMs:
|
||||
lte: 5000
|
||||
```
|
||||
|
||||
### server.listen — 监听配置
|
||||
完整配置、checker 和 expect 规则参见 [配置文件](docs/user/configuration.md)、[Checker 参考](docs/user/checkers/README.md) 和 [校验规则](docs/user/expectations.md)。
|
||||
|
||||
| 字段 | 说明 | 必填 | 默认值 |
|
||||
| ------ | -------- | ---- | ----------- |
|
||||
| `host` | 监听地址 | 否 | `127.0.0.1` |
|
||||
| `port` | 监听端口 | 否 | `3000` |
|
||||
## 生产运行
|
||||
|
||||
### server.storage — 存储配置
|
||||
|
||||
| 字段 | 说明 | 必填 | 默认值 |
|
||||
| ----------- | ------------------------------------------------ | ---- | -------- |
|
||||
| `dataDir` | 数据目录,相对路径基于配置文件所在目录解析 | 否 | `./data` |
|
||||
| `retention` | 历史数据保留时长,支持 `ms`/`s`/`m`/`h`/`d` 单位 | 否 | `7d` |
|
||||
|
||||
### probes.execution — 拨测运行时配置
|
||||
|
||||
| 字段 | 说明 | 必填 | 默认值 |
|
||||
| --------------------- | -------------- | ---- | ------ |
|
||||
| `maxConcurrentChecks` | 最大并发拨测数 | 否 | `20` |
|
||||
|
||||
### server.logging — 日志配置
|
||||
|
||||
| 字段 | 说明 | 必填 | 默认值 |
|
||||
| ---------------------------------------- | ---------------------------------------------- | ---- | ------------------------- |
|
||||
| `server.logging.level` | 全局日志等级,console 和 file 未指定时继承此值 | 否 | `info` |
|
||||
| `server.logging.console.level` | 控制台日志等级 | 否 | 继承 `level` |
|
||||
| `server.logging.file.level` | 文件日志等级 | 否 | 继承 `level` |
|
||||
| `server.logging.file.path` | 日志文件路径,相对路径基于配置文件目录解析 | 否 | `<dataDir>/logs/dial.log` |
|
||||
| `server.logging.file.rotation.size` | 按大小滚动,支持 `KB`/`MB`/`GB` 单位 | 否 | `50MB` |
|
||||
| `server.logging.file.rotation.frequency` | 按时间滚动:`hourly`、`daily`、`weekly` | 否 | `daily` |
|
||||
| `server.logging.file.rotation.maxFiles` | 保留的归档文件数量(不含活跃日志) | 否 | `14` |
|
||||
|
||||
日志等级支持:`trace`、`debug`、`info`、`warn`、`error`、`fatal`。
|
||||
|
||||
控制台始终输出(pretty 格式),文件始终输出 JSONL 格式并支持滚动。`rotation.size` 和 `rotation.frequency` 任一条件触发即滚动。
|
||||
|
||||
### 内置默认值
|
||||
|
||||
未显式配置时,系统使用以下内置默认值:
|
||||
|
||||
- `interval`:`30s`(拨测间隔)
|
||||
- `timeout`:`10s`(超时时间)
|
||||
- 各 checker 专属默认值见对应章节
|
||||
|
||||
如需在配置文件中共享相同的配置值,可使用 `variables` 定义变量,然后在 `server`、`probes` 和 `targets` 中通过 `${var}` 引用。例如在 `variables` 中定义 `default_interval: "30s"`,在多个 target 的 `interval` 字段写 `${default_interval}`。
|
||||
|
||||
### variables — 配置变量
|
||||
|
||||
`variables` 是顶层动态键值表,key 必须符合 `[a-zA-Z_][a-zA-Z0-9_]*`,value 仅支持 string、number、boolean。`server`、`probes` 和 `targets` 中的字符串值可引用变量:
|
||||
|
||||
- `${key}`:引用 variables 或环境变量
|
||||
- `${key|default}`:变量和环境变量都不存在时使用默认值,第一个 `|` 后的内容为默认值
|
||||
- `${key|}`:变量和环境变量都不存在时使用空字符串作为默认值
|
||||
- `$${key}`:转义输出字面量 `${key}`
|
||||
|
||||
解析优先级为 `variables -> process.env -> 默认值`,三者均不存在时配置校验失败。字段值完整等于单个变量引用时会保留 number/boolean/string 类型,环境变量和默认值会做类型推断,但空字符串保持为字符串;部分拼接时统一转为字符串。变量替换作用于 `server`、`probes` 和 `targets`,不作用于 `variables` 段自身,且不会替换 `targets[].id` 和 `targets[].type` 字段;对象 key 不参与替换。
|
||||
|
||||
配置加载内部区分三层形态:用户 YAML 属于 Authoring Config,允许变量引用和 expect 简写;`normalizeAuthoringConfig()` 会在启动时完成变量替换、expect primitive/keyed/content 简写展开并移除 `variables` 段,生成 Normalized Config;checker 的 `resolve()` 只在 ResolvedConfig 阶段补默认值并解析 duration、size、路径和运行期环境。根目录 `probe-config.schema.json` 面向 Authoring Config,因此 VSCode 校验会接受 `server.listen.port: "${server_port|3000}"`、`http.maxRedirects: "${MAX|5}"` 和 `expect.durationMs: 5000` 这类写法。
|
||||
|
||||
### targets — 拨测目标列表(必填)
|
||||
|
||||
每个 target 的通用字段:
|
||||
|
||||
| 字段 | 说明 | 必填 | 默认值 |
|
||||
| ------------- | ------------------------------------------------------------------------------------ | ---- | --------- |
|
||||
| `id` | 目标唯一标识,最长 30 字符,支持字母数字、下划线、连字符,不参与变量替换 | 是 | |
|
||||
| `name` | 展示名称,最长 30 字符,支持变量替换,可省略或显式 null;前端展示时 null 回退到 `id` | 否 | |
|
||||
| `description` | 目标描述,最长 500 字符,支持变量替换,可省略或显式 null,允许空字符串 | 否 | |
|
||||
| `type` | 目标类型:`http`、`cmd`、`db`、`tcp`、`udp`、`dns`、`icmp`、`llm` | 是 | |
|
||||
| `group` | 分组名称 | 否 | `default` |
|
||||
| `interval` | 拨测间隔,未配置时使用内置默认值 `30s` | 否 | `30s` |
|
||||
| `timeout` | 超时时间,未配置时使用内置默认值 `10s` | 否 | `10s` |
|
||||
|
||||
---
|
||||
|
||||
### HTTP Checker(`type: http`)
|
||||
|
||||
**配置项**
|
||||
|
||||
| 字段 | 说明 | 必填 | 默认值 |
|
||||
| ------------------- | ------------------- | ---- | ------- |
|
||||
| `http.url` | 目标 URL | 是 | |
|
||||
| `http.method` | HTTP 方法 | 否 | `GET` |
|
||||
| `http.headers` | 请求头 | 否 | |
|
||||
| `http.body` | 请求体 | 否 | |
|
||||
| `http.ignoreSSL` | 忽略 HTTPS 证书校验 | 否 | `false` |
|
||||
| `http.maxRedirects` | 最大重定向跟随次数 | 否 | `0` |
|
||||
|
||||
**expect 校验项**
|
||||
|
||||
| 字段 | 说明 | 必填 | 默认值 |
|
||||
| ------------ | -------------------------------------------------- | ---- | ------- |
|
||||
| `status` | 可接受的状态码列表,支持精确码和范围(如 `"2xx"`) | 否 | `[200]` |
|
||||
| `headers` | 响应头校验,使用动态键名和 `KeyedExpectations` | 否 | |
|
||||
| `body` | 响应体校验,使用 `ContentExpectations` 数组 | 否 | |
|
||||
| `durationMs` | 完整执行耗时校验,使用 `ValueMatcher` | 否 | |
|
||||
|
||||
**配置示例**
|
||||
|
||||
```yaml
|
||||
- id: "json-api"
|
||||
name: "JSON API 示例"
|
||||
type: http
|
||||
http:
|
||||
url: "https://httpbin.org/json"
|
||||
headers:
|
||||
Authorization: "Bearer token"
|
||||
expect:
|
||||
status: [200]
|
||||
headers:
|
||||
Content-Type:
|
||||
contains: "application/json"
|
||||
body:
|
||||
- json:
|
||||
path: "$.slideshow.title"
|
||||
equals: "Sample Slide Show"
|
||||
durationMs:
|
||||
lte: 10000
|
||||
```bash
|
||||
bun run build
|
||||
./dist/dial-server ./probes.yaml
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Cmd Checker(`type: cmd`)
|
||||
|
||||
**配置项**
|
||||
|
||||
| 字段 | 说明 | 必填 | 默认值 |
|
||||
| ---------- | -------------------------------------- | ---- | ------ |
|
||||
| `cmd.exec` | 可执行文件名或路径 | 是 | |
|
||||
| `cmd.args` | 命令行参数列表 | 否 | `[]` |
|
||||
| `cmd.env` | 环境变量覆盖(继承进程环境变量并合并) | 否 | |
|
||||
| `cmd.cwd` | 工作目录(相对于配置文件所在目录) | 否 | |
|
||||
|
||||
**expect 校验项**
|
||||
|
||||
| 字段 | 说明 | 必填 | 默认值 |
|
||||
| ------------ | --------------------------------------------- | ---- | ------ |
|
||||
| `exitCode` | 可接受的退出码列表 | 否 | `[0]` |
|
||||
| `stdout` | 标准输出校验,使用 `ContentExpectations` 数组 | 否 | |
|
||||
| `stderr` | 标准错误校验,使用 `ContentExpectations` 数组 | 否 | |
|
||||
| `durationMs` | 完整执行耗时校验,使用 `ValueMatcher` | 否 | |
|
||||
|
||||
**配置示例**
|
||||
|
||||
```yaml
|
||||
- id: "bun-script"
|
||||
name: "Bun 脚本检查"
|
||||
type: cmd
|
||||
cmd:
|
||||
exec: "bun"
|
||||
args: ["-e", "console.log('ok')"]
|
||||
expect:
|
||||
exitCode: [0]
|
||||
stdout:
|
||||
- contains: "ok"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### DB Checker(`type: db`)
|
||||
|
||||
**配置项**
|
||||
|
||||
| 字段 | 说明 | 必填 | 默认值 |
|
||||
| ---------- | ------------------------------------------------------------- | ---- | ------ |
|
||||
| `db.url` | 数据库连接字符串,支持 `postgres://`、`mysql://`、`sqlite://` | 是 | |
|
||||
| `db.query` | SQL 查询语句,不配置时仅测试连接 | 否 | |
|
||||
|
||||
**expect 校验项**
|
||||
|
||||
| 字段 | 说明 | 必填 | 默认值 |
|
||||
| ------------ | ----------------------------------------------------------------------- | ---- | ------ |
|
||||
| `rowCount` | 查询返回行数校验,使用 `ValueMatcher` | 否 | |
|
||||
| `rows` | 查询结果逐行校验,数组内每行为列名到 `KeyedExpectations` 的映射 | 否 | |
|
||||
| `result` | 完整查询结果 `{ rows, rowCount }` 校验,使用 `ContentExpectations` 数组 | 否 | |
|
||||
| `durationMs` | 完整执行耗时校验,使用 `ValueMatcher` | 否 | |
|
||||
|
||||
**配置示例**
|
||||
|
||||
```yaml
|
||||
- id: "sqlite-query"
|
||||
name: "SQLite 数据库检查"
|
||||
type: db
|
||||
db:
|
||||
url: "sqlite:///path/to/db.sqlite"
|
||||
query: "SELECT COUNT(*) as cnt FROM users WHERE status = 'active'"
|
||||
expect:
|
||||
durationMs:
|
||||
lte: 5000
|
||||
rowCount: { gte: 1 }
|
||||
rows:
|
||||
- cnt: { gte: 0 }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### TCP Checker(`type: tcp`)
|
||||
|
||||
**配置项**
|
||||
|
||||
| 字段 | 说明 | 必填 | 默认值 |
|
||||
| ----------------------- | ------------------------------------------- | ---- | ------- |
|
||||
| `tcp.host` | 目标主机地址 | 是 | |
|
||||
| `tcp.port` | 目标端口(1-65535) | 是 | |
|
||||
| `tcp.readBanner` | 是否读取服务端 banner | 否 | `false` |
|
||||
| `tcp.bannerReadTimeout` | banner 读取超时(毫秒) | 否 | `2000` |
|
||||
| `tcp.maxBannerBytes` | banner 最大字节数,支持 `KB`/`MB`/`GB` 单位 | 否 | `4KB` |
|
||||
|
||||
**expect 校验项**
|
||||
|
||||
| 字段 | 说明 | 必填 | 默认值 |
|
||||
| ------------ | ------------------------------------------------------------------------- | ---- | ------ |
|
||||
| `connected` | 期望连接结果,`true` 可达或 `false` 期望不可达 | 否 | `true` |
|
||||
| `banner` | Banner 内容校验,使用 `ContentExpectations` 数组,需开启 `tcp.readBanner` | 否 | |
|
||||
| `durationMs` | 完整执行耗时校验,使用 `ValueMatcher` | 否 | |
|
||||
|
||||
**配置示例**
|
||||
|
||||
```yaml
|
||||
- id: "redis-port"
|
||||
name: "Redis 端口可达"
|
||||
type: tcp
|
||||
tcp:
|
||||
host: "127.0.0.1"
|
||||
port: 6379
|
||||
expect:
|
||||
durationMs:
|
||||
lte: 3000
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### UDP Checker(`type: udp`)
|
||||
|
||||
**配置项**
|
||||
|
||||
| 字段 | 说明 | 必填 | 默认值 |
|
||||
| ---------------------- | ---------------------------------------- | ---- | ------ |
|
||||
| `udp.host` | 目标主机地址 | 是 | |
|
||||
| `udp.port` | 目标端口(1-65535) | 是 | |
|
||||
| `udp.payload` | 发送数据 | 否 | `""` |
|
||||
| `udp.encoding` | payload 编码:`text`、`hex`、`base64` | 否 | `text` |
|
||||
| `udp.responseEncoding` | 响应解码:`text`、`hex`、`base64` | 否 | `text` |
|
||||
| `udp.maxResponseBytes` | 响应最大字节数,支持 `KB`/`MB`/`GB` 单位 | 否 | `4KB` |
|
||||
|
||||
**expect 校验项**
|
||||
|
||||
| 字段 | 说明 | 必填 | 默认值 |
|
||||
| -------------- | --------------------------------------------- | ---- | ------ |
|
||||
| `responded` | 期望是否收到响应 | 否 | `true` |
|
||||
| `response` | 响应内容校验,使用 `ContentExpectations` 数组 | 否 | |
|
||||
| `responseSize` | 响应字节数校验,使用 `ValueMatcher` | 否 | |
|
||||
| `sourceHost` | 响应来源地址校验,使用 `ValueMatcher` | 否 | |
|
||||
| `sourcePort` | 响应来源端口校验,使用 `ValueMatcher` | 否 | |
|
||||
| `durationMs` | 完整执行耗时校验,使用 `ValueMatcher` | 否 | |
|
||||
|
||||
**配置示例**
|
||||
|
||||
```yaml
|
||||
- id: "udp-heartbeat"
|
||||
name: "UDP 心跳检测"
|
||||
type: udp
|
||||
udp:
|
||||
host: "127.0.0.1"
|
||||
port: 9000
|
||||
payload: "PING"
|
||||
expect:
|
||||
responded: true
|
||||
response:
|
||||
- contains: "PONG"
|
||||
durationMs:
|
||||
lte: 100
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### ICMP Checker(`type: icmp`)
|
||||
|
||||
**配置项**
|
||||
|
||||
| 字段 | 说明 | 必填 | 默认值 |
|
||||
| ----------------- | ------------------------- | ---- | ------ |
|
||||
| `icmp.host` | 目标主机地址 | 是 | |
|
||||
| `icmp.count` | ICMP 包数量,范围 `1-100` | 否 | `3` |
|
||||
| `icmp.packetSize` | ICMP 包大小(bytes) | 否 | `56` |
|
||||
|
||||
ICMP checker 通过系统 `ping` 命令执行 ICMP 探测,支持 Linux、macOS 和 Windows 输出解析。
|
||||
|
||||
**expect 校验项**
|
||||
|
||||
| 字段 | 说明 | 必填 | 默认值 |
|
||||
| ------------------- | --------------------------------------------------- | ---- | ------ |
|
||||
| `alive` | 期望主机可达性 | 否 | `true` |
|
||||
| `packetLossPercent` | 丢包率百分比校验,范围 `0-100`,使用 `ValueMatcher` | 否 | |
|
||||
| `avgLatencyMs` | 平均延迟校验,使用 `ValueMatcher` | 否 | |
|
||||
| `maxLatencyMs` | 最大单次延迟校验,使用 `ValueMatcher` | 否 | |
|
||||
| `durationMs` | 完整执行耗时校验,使用 `ValueMatcher` | 否 | |
|
||||
|
||||
**配置示例**
|
||||
|
||||
```yaml
|
||||
- id: "gateway-icmp"
|
||||
name: "网关 ICMP 可达"
|
||||
type: icmp
|
||||
icmp:
|
||||
host: "10.0.0.1"
|
||||
count: 3
|
||||
packetSize: 56
|
||||
expect:
|
||||
alive: true
|
||||
packetLossPercent:
|
||||
lte: 10
|
||||
avgLatencyMs:
|
||||
lte: 100
|
||||
maxLatencyMs:
|
||||
lte: 300
|
||||
durationMs:
|
||||
lte: 5000
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### DNS Checker(`type: dns`)
|
||||
|
||||
DNS Checker 支持两种解析模式,通过 `dns.resolver` 字段区分:
|
||||
|
||||
- **`system` 模式**:使用本机 DNS 解析器检查域名是否能解析到预期地址,输出有限 observation。
|
||||
- **`server` 模式**:直接向指定 DNS server 发起 UDP/TCP 深度拨测,检查 DNS 协议级响应(RCODE、TTL、flags、记录值等)。
|
||||
|
||||
#### `dns.resolver: system` 配置项
|
||||
|
||||
| 字段 | 说明 | 必填 | 默认值 |
|
||||
| -------------- | ---------- | ---- | -------- |
|
||||
| `dns.resolver` | 解析模式 | 是 | `system` |
|
||||
| `dns.name` | 待解析域名 | 是 | |
|
||||
| `dns.family` | 地址族 | 否 | `any` |
|
||||
|
||||
`family` 可选值:`any`(返回 IPv4 和 IPv6)、`ipv4`(仅 IPv4)、`ipv6`(仅 IPv6)。
|
||||
|
||||
**system 模式 expect 校验项**
|
||||
|
||||
| 字段 | 说明 | 断言模型 |
|
||||
| ------------ | -------------------- | --------------------------------- |
|
||||
| `values` | 解析结果地址集合断言 | DNS 集合(include/exclude/exact) |
|
||||
| `valueCount` | 解析结果数量 | ValueMatcher |
|
||||
| `durationMs` | 解析耗时 | ValueMatcher |
|
||||
|
||||
**示例**:
|
||||
|
||||
```yaml
|
||||
- id: "dns-system-api"
|
||||
name: "本机 DNS 解析"
|
||||
type: dns
|
||||
dns:
|
||||
resolver: system
|
||||
name: "api.example.com"
|
||||
family: any
|
||||
expect:
|
||||
values:
|
||||
exact:
|
||||
- "203.0.113.10"
|
||||
durationMs:
|
||||
lte: 500
|
||||
```
|
||||
|
||||
#### `dns.resolver: server` 配置项
|
||||
|
||||
| 字段 | 说明 | 必填 | 默认值 |
|
||||
| ---------------------- | --------------------------------- | ---- | -------- |
|
||||
| `dns.resolver` | 解析模式 | 是 | `server` |
|
||||
| `dns.server` | DNS server 地址 | 是 | |
|
||||
| `dns.name` | 查询域名 | 是 | |
|
||||
| `dns.port` | DNS server 端口 | 否 | `53` |
|
||||
| `dns.protocol` | 传输协议:`udp` / `tcp` | 否 | `udp` |
|
||||
| `dns.recordType` | DNS 记录类型 | 否 | `A` |
|
||||
| `dns.recursionDesired` | 是否设置 RD flag | 否 | `true` |
|
||||
| `dns.tcpFallback` | UDP 响应 TC=1 时是否 TCP fallback | 否 | `true` |
|
||||
| `dns.maxResponseBytes` | 响应最大字节数 | 否 | `4KB` |
|
||||
|
||||
`recordType` 可选值:`A`、`AAAA`、`CNAME`、`NS`、`MX`、`TXT`、`SOA`、`SRV`、`CAA`、`PTR`。
|
||||
|
||||
**server 模式 expect 校验项**
|
||||
|
||||
| 字段 | 说明 | 断言模型 |
|
||||
| -------------------- | ---------------------------------- | --------------------------------- |
|
||||
| `responded` | 是否收到 DNS response | boolean |
|
||||
| `rcode` | 期望 RCODE 列表(如 `NOERROR`) | string[] |
|
||||
| `values` | 目标类型记录值集合断言 | DNS 集合(include/exclude/exact) |
|
||||
| `valueCount` | 目标类型记录数量 | ValueMatcher |
|
||||
| `answerCount` | answer section 总记录数 | ValueMatcher |
|
||||
| `ttlMin` | answer 中最小 TTL | ValueMatcher |
|
||||
| `ttlMax` | answer 中最大 TTL | ValueMatcher |
|
||||
| `authoritative` | AA flag | boolean |
|
||||
| `recursionAvailable` | RA flag | boolean |
|
||||
| `truncated` | TC flag | boolean |
|
||||
| `authenticatedData` | AD flag | boolean |
|
||||
| `result` | 完整结构化响应的 JSONPath 兜底断言 | ContentExpectations |
|
||||
| `durationMs` | 完整查询耗时 | ValueMatcher |
|
||||
|
||||
**示例**:
|
||||
|
||||
```yaml
|
||||
- id: "dns-server-api"
|
||||
name: "Cloudflare DNS A 记录"
|
||||
type: dns
|
||||
dns:
|
||||
resolver: server
|
||||
server: "1.1.1.1"
|
||||
port: 53
|
||||
protocol: udp
|
||||
name: "api.example.com"
|
||||
recordType: A
|
||||
expect:
|
||||
rcode: ["NOERROR"]
|
||||
values:
|
||||
include:
|
||||
- "203.0.113.10"
|
||||
ttlMin:
|
||||
gte: 60
|
||||
durationMs:
|
||||
lte: 200
|
||||
|
||||
- id: "dns-nxdomain-check"
|
||||
name: "负向 DNS 检查"
|
||||
type: dns
|
||||
dns:
|
||||
resolver: server
|
||||
server: "1.1.1.1"
|
||||
name: "nxdomain.example.com"
|
||||
recordType: A
|
||||
expect:
|
||||
rcode: ["NXDOMAIN"]
|
||||
```
|
||||
|
||||
**Notes**:
|
||||
|
||||
- 未配置 expect 时,`system` 模式默认要求解析成功且 `valueCount > 0`,`server` 模式默认要求 `NOERROR + valueCount > 0`。
|
||||
- 显式配置非 `NOERROR` rcode(如 `NXDOMAIN`)时,不自动要求 `valueCount > 0`。
|
||||
- `values.exact` 忽略返回顺序(集合匹配);对 A/AAAA 查询,CNAME 链不计入 `values`,单独放入 `cnameChain`
|
||||
- `values` 按记录类型规范化为字符串,格式:MX=`"10 mail.example.com"`、SOA=空格分隔字段、SRV=`"10 60 443 server.example.com"`、CAA=`"0 issue letsencrypt.org"` 等。
|
||||
|
||||
---
|
||||
|
||||
### LLM Checker(`type: llm`)
|
||||
|
||||
**配置项**
|
||||
|
||||
| 字段 | 说明 | 必填 | 默认值 |
|
||||
| --------------------- | ------------------------------------------------------ | ---- | ------- |
|
||||
| `llm.provider` | 模型提供方:`openai`、`openai-responses`、`anthropic` | 是 | |
|
||||
| `llm.url` | API base URL | 是 | |
|
||||
| `llm.model` | 模型名称 | 是 | |
|
||||
| `llm.prompt` | 单轮 prompt | 是 | |
|
||||
| `llm.mode` | 调用模式:`http`(非流式)或 `stream`(流式) | 否 | `http` |
|
||||
| `llm.key` | API key,支持 `${VAR}` 变量替换 | 否 | `""` |
|
||||
| `llm.authToken` | Bearer token(仅 `anthropic` provider,与 `key` 互斥) | 否 | |
|
||||
| `llm.headers` | 附加请求头 | 否 | |
|
||||
| `llm.ignoreSSL` | 忽略 HTTPS 证书校验 | 否 | `false` |
|
||||
| `llm.options` | 生成选项 | 否 | |
|
||||
| `llm.providerOptions` | Provider 专属选项 | 否 | |
|
||||
|
||||
`llm.options` 支持 `maxOutputTokens`(默认 `16`)、`temperature`(默认 `0`)、`topP`、`topK`、`presencePenalty`、`frequencyPenalty`、`stopSequences`、`seed`。
|
||||
|
||||
**expect 校验项**
|
||||
|
||||
| 字段 | 说明 | 必填 | 默认值 |
|
||||
| ----------------- | ---------------------------------------------------------------------- | ---- | ------- |
|
||||
| `status` | 可接受的状态码列表,支持精确码和范围(如 `"2xx"`) | 否 | `[200]` |
|
||||
| `headers` | 响应头校验,使用动态键名和 `KeyedExpectations` | 否 | |
|
||||
| `output` | 模型输出校验,使用 `ContentExpectations` 数组 | 否 | |
|
||||
| `finishReason` | finish reason 校验,使用 `ValueMatcher` | 否 | |
|
||||
| `rawFinishReason` | 原始 finish reason 校验,使用 `ValueMatcher` | 否 | |
|
||||
| `usage` | Token usage 校验(`inputTokens`/`outputTokens`/`totalTokens` matcher) | 否 | |
|
||||
| `stream` | 流式断言(`completed`、`firstTokenMs` matcher,仅 `mode: stream`) | 否 | |
|
||||
| `durationMs` | 完整执行耗时校验,使用 `ValueMatcher` | 否 | |
|
||||
|
||||
**配置示例**
|
||||
|
||||
```yaml
|
||||
- id: "llm-openai-probe"
|
||||
name: "OpenAI 健康检查"
|
||||
type: llm
|
||||
llm:
|
||||
provider: openai
|
||||
url: "https://api.openai.com/v1"
|
||||
model: "gpt-4o-mini"
|
||||
prompt: "Say OK"
|
||||
key: "${OPENAI_API_KEY}"
|
||||
expect:
|
||||
status: [200]
|
||||
finishReason: "stop"
|
||||
output:
|
||||
- contains: "OK"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 通用校验规则
|
||||
|
||||
#### ContentExpectations 校验项
|
||||
|
||||
`body`、`stdout`、`stderr`、`banner`、`response`、`output`、`result` 均使用数组:
|
||||
|
||||
- `contains` — 响应体包含指定文本
|
||||
- `regex` — 正则匹配(启动期会拒绝存在 ReDoS 风险的模式)
|
||||
- `json` — JSONPath 提取值比较(`path` 必填,如 `$.slideshow.title`)
|
||||
- `css` — CSS 选择器提取 HTML 元素(`selector` 必填,`attr` 可选提取属性)
|
||||
- `xpath` — XPath 提取 XML/HTML 节点(`path` 必填,如 `/html/body/h1/text()`)
|
||||
|
||||
#### ValueMatcher
|
||||
|
||||
`equals`、`contains`、`regex`、`empty`、`exists`、`gte`、`lte`、`gt`、`lt`。`equals` 支持 JSON 深度相等;`regex` 固定使用无 flags 正则;提取器未配置 matcher 时等价于 `exists: true`。ValueMatcher expect 字段也可直接写 string、number、boolean 或 null,等价于 `{ equals: value }`;数组和对象必须显式写成 `{ equals: ... }`。
|
||||
|
||||
#### KeyedExpectations
|
||||
|
||||
`headers`、`rows` 中每行使用的校验结构,支持 ValueMatcher 的全部字段。
|
||||
|
||||
### 补充说明
|
||||
|
||||
- **大小说明**:`maxBodyBytes`、`maxOutputBytes`、`maxResponseBytes`、`maxBannerBytes` 支持 `KB`、`MB`、`GB` 单位,也可直接使用数字
|
||||
- **时长格式**:`500ms`、`30s`、`5m`、`2h`、`7d`
|
||||
- **JSON Schema**:仓库根目录导出 `probe-config.schema.json`,在 YAML 文件顶部添加 `# yaml-language-server: $schema=./probe-config.schema.json` 即可在编辑器中获得提示和校验
|
||||
- **旧字段移除**:`maxDurationMs`、`maxPacketLoss`、`maxAvgLatencyMs`、`maxMaxLatencyMs` 和旧正则字段 `match` 已移除,请分别改用 `durationMs`、ICMP matcher 字段和 `regex`
|
||||
|
||||
> **注意:** 配置校验在启动时执行,非法配置会阻止启动并输出错误信息。除动态键值表(`headers`、`env`、`variables`)外,未知字段会导致启动失败,请使用 YAML 注释。
|
||||
|
||||
## 目标状态判定
|
||||
|
||||
采用单层判定模型:
|
||||
|
||||
- **UP** = 拨测结果符合 expect 规则
|
||||
- **DOWN** = 拨测结果不符合 expect 规则
|
||||
|
||||
执行失败(网络错误、超时、进程崩溃)和 expect 不匹配都统一为 DOWN,通过 `failure.kind` 区分原因(`"error"` vs `"mismatch"`)。
|
||||
|
||||
API 返回的检查结果包含 `detail` 和 `observation`:`detail` 是后端按 checker 类型从结构化 observation 动态生成的人可读摘要,`observation` 保存该次检查的结构化观测数据。`detail` 不写入 SQLite,存储层仅持久化 `observation` JSON、`failure` JSON、匹配状态、耗时和时间戳。
|
||||
Docker、跨平台发布包和运行时注意事项参见 [部署文档](docs/user/deployment.md)。
|
||||
|
||||
## 文档导航
|
||||
|
||||
| 入口 | 内容 |
|
||||
| -------------------------------------------- | ---------------------------------------------------- |
|
||||
| [文档总览](docs/README.md) | 全部文档入口和文档归属矩阵 |
|
||||
| [配置文件](docs/user/configuration.md) | YAML 结构、变量、server、targets 通用字段 |
|
||||
| [Checker 参考](docs/user/checkers/README.md) | 所有 checker 的配置、expect 和示例 |
|
||||
| [校验规则](docs/user/expectations.md) | ValueMatcher、ContentExpectations、KeyedExpectations |
|
||||
| [部署文档](docs/user/deployment.md) | 构建、Docker、发布包和容器运行边界 |
|
||||
| [状态模型](docs/user/status-model.md) | UP/DOWN、failure、observation、detail |
|
||||
| [故障排查](docs/user/troubleshooting.md) | 常见运行问题和排查入口 |
|
||||
|
||||
## 开发
|
||||
|
||||
@@ -745,7 +91,7 @@ bun run check # schema:check + typecheck + lint + test
|
||||
bun run verify # check + build
|
||||
```
|
||||
|
||||
开发相关文档(项目结构、构建、测试、代码规范等)请参阅 [DEVELOPMENT.md](DEVELOPMENT.md)。
|
||||
开发入口参见 [DEVELOPMENT.md](DEVELOPMENT.md)。新增或修改 checker 前请先阅读 [CONTRIBUTING.md](CONTRIBUTING.md)。
|
||||
|
||||
## License
|
||||
|
||||
|
||||
Reference in New Issue
Block a user