diff --git a/README.md b/README.md index e75e3cc..c597163 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# DiAL +

DiAL

轻量级多类型拨测监控工具 @@ -21,6 +21,13 @@ DiAL 是一个自托管的拨测监控工具,支持 **HTTP**、**命令行** - 多主题支持:系统、明亮、黑暗三种主题模式 - 零外部依赖:数据存储使用 SQLite,无需额外数据库服务 +## 应用截图 + +| | 亮色 | 暗色 | +| ------ | --------------------------------------------------- | ------------------------------------------------- | +| 主页 | ![index-light](assets/screenshot/light_index.png) | ![index-dark](assets/screenshot/dark_index.png) | +| 详情页 | ![detail-light](assets/screenshot/light_detail.png) | ![detail-dark](assets/screenshot/dark_detail.png) | + ## 快速开始 **前置条件:** [Bun](https://bun.sh/) >= 1.0 @@ -60,155 +67,74 @@ bun run build 程序通过 YAML 配置文件定义所有运行参数,完整示例参见 [`probes.example.yaml`](probes.example.yaml)。 +### 配置文件结构 + ```yaml # yaml-language-server: $schema=./probe-config.schema.json -server: +server: # 服务配置(均可省略) host: "127.0.0.1" port: 3000 dataDir: "/tmp/probes_data" -runtime: +runtime: # 运行时配置 maxConcurrentChecks: 20 retention: "7d" -variables: +variables: # 配置变量(可省略) env_name: "生产" base_url: "https://api.example.com" - api_token: "Bearer demo-token" - sqlite_url: "sqlite:///path/to/db.sqlite" -defaults: +defaults: # 全局默认值(均可省略) interval: "30s" timeout: "10s" - http: - maxBodyBytes: "10MB" - cmd: - maxOutputBytes: "1MB" + # http: ... + # cmd: ... + # llm: ... -targets: +targets: # 拨测目标列表(必填) - id: "baidu-home" name: "Baidu" type: http http: url: "https://www.baidu.com" expect: - status: [200] - durationMs: - lte: 10000 - - - id: "json-api" - name: "${env_name} JSON API 示例" - type: http - http: - url: "${base_url}/json" - headers: - Authorization: "${api_token|Bearer fallback-token}" - expect: - status: [200] - headers: - Content-Type: - contains: "application/json" - body: - - json: - path: "$.slideshow.title" - equals: "Sample Slide Show" - - - id: "bun-script" - name: "Bun 脚本检查" + # ... + - id: "my-cmd" + name: "脚本检查" type: cmd cmd: - exec: "bun" - args: ["-e", "console.log('ok')"] + # ... expect: - exitCode: [0] - stdout: - - contains: "ok" - - - id: "sqlite-active-users" - name: "SQLite 数据库检查" - type: db - db: - url: "${sqlite_url}" - query: "SELECT COUNT(*) as cnt FROM users WHERE status = 'active'" - expect: - durationMs: - lte: 5000 - rowCount: { gte: 1 } - rows: - - cnt: { gte: 0 } - - - id: "redis-port" - name: "Redis 端口可达" - type: tcp - tcp: - host: "127.0.0.1" - port: 6379 - expect: - durationMs: - lte: 3000 - - - id: "udp-heartbeat" - name: "UDP 心跳检测" - type: udp - udp: - host: "127.0.0.1" - port: 9000 - payload: "PING" - expect: - response: - - contains: "PONG" - durationMs: - lte: 100 - - - 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 + # ... + # ... 更多 targets ``` -### 配置说明 +### server — 服务配置 -#### server — 服务配置(均可省略,使用默认值) +| 字段 | 说明 | 必填 | 默认值 | +| --------- | ------------------------------------------ | ---- | ----------- | +| `host` | 监听地址 | 否 | `127.0.0.1` | +| `port` | 监听端口 | 否 | `3000` | +| `dataDir` | 数据目录,相对路径基于配置文件所在目录解析 | 否 | `./data` | -| 字段 | 说明 | 默认值 | -| --------- | ------------------------------------------ | ----------- | -| `host` | 监听地址 | `127.0.0.1` | -| `port` | 监听端口 | `3000` | -| `dataDir` | 数据目录,相对路径基于配置文件所在目录解析 | `./data` | +### runtime — 运行时配置 -#### runtime — 运行时配置 +| 字段 | 说明 | 必填 | 默认值 | +| --------------------- | ------------------------------------------------ | ---- | ------ | +| `maxConcurrentChecks` | 最大并发拨测数 | 否 | `20` | +| `retention` | 历史数据保留时长,支持 `ms`/`s`/`m`/`h`/`d` 单位 | 否 | `7d` | -| 字段 | 说明 | 默认值 | -| --------------------- | ------------------------------------------------ | ------ | -| `maxConcurrentChecks` | 最大并发拨测数 | `20` | -| `retention` | 历史数据保留时长,支持 `ms`/`s`/`m`/`h`/`d` 单位 | `7d` | +### defaults — 全局默认值 -#### defaults — 全局默认值(均可省略) +| 字段 | 说明 | 必填 | 默认值 | +| ---------- | -------- | ---- | ------ | +| `interval` | 拨测间隔 | 否 | `30s` | +| `timeout` | 超时时间 | 否 | `10s` | -| 字段 | 说明 | 默认值 | -| -------------------- | -------------------------------------------------- | ------- | -| `interval` | 拨测间隔 | `30s` | -| `timeout` | 超时时间 | `10s` | -| `http.maxBodyBytes` | 响应体最大字节数 | `100MB` | -| `http.headers` | 默认请求头(target 中的 headers 会合并覆盖同名头) | — | -| `cmd.maxOutputBytes` | 输出最大字节数 | `100MB` | -| `cmd.cwd` | 默认工作目录(相对于配置文件所在目录) | `.` | +各 checker 专属的默认配置见对应章节。 -#### variables — 配置变量(可省略) +### variables — 配置变量 `variables` 是顶层动态键值表,key 必须符合 `[a-zA-Z_][a-zA-Z0-9_]*`,value 仅支持 string、number、boolean。target 中的字符串值可引用变量: @@ -218,118 +144,362 @@ targets: 解析优先级为 `variables -> process.env -> 默认值`。字段值完整等于单个变量引用时会保留 number/boolean/string 类型;部分拼接时统一转为字符串。变量替换仅作用于 `targets`,且不会替换 `id` 和 `type` 字段。 -#### targets — 拨测目标列表(必填) +### targets — 拨测目标列表(必填) 每个 target 的通用字段: -| 字段 | 说明 | 必填 | -| ------------- | ------------------------------------------------------------------------------------ | -------------------- | -| `id` | 目标唯一标识,最长 30 字符,支持字母数字、下划线、连字符,不参与变量替换 | 是 | -| `name` | 展示名称,最长 30 字符,支持变量替换,可省略或显式 null;前端展示时 null 回退到 `id` | 否 | -| `description` | 目标描述,最长 500 字符,支持变量替换,可省略或显式 null,允许空字符串 | 否 | -| `type` | 目标类型:`http`、`cmd`、`db`、`tcp`、`udp`、`icmp`、`llm` | 是 | -| `group` | 分组名称 | 否,默认 `"default"` | -| `interval` | 覆盖全局拨测间隔 | 否 | -| `timeout` | 覆盖全局超时时间 | 否 | +| 字段 | 说明 | 必填 | 默认值 | +| ------------- | ------------------------------------------------------------------------------------ | ---- | --------- | +| `id` | 目标唯一标识,最长 30 字符,支持字母数字、下划线、连字符,不参与变量替换 | 是 | | +| `name` | 展示名称,最长 30 字符,支持变量替换,可省略或显式 null;前端展示时 null 回退到 `id` | 否 | | +| `description` | 目标描述,最长 500 字符,支持变量替换,可省略或显式 null,允许空字符串 | 否 | | +| `type` | 目标类型:`http`、`cmd`、`db`、`tcp`、`udp`、`icmp`、`llm` | 是 | | +| `group` | 分组名称 | 否 | `default` | +| `interval` | 覆盖全局拨测间隔 | 否 | | +| `timeout` | 覆盖全局超时时间 | 否 | | -**HTTP 类型** (`type: http`) +--- -| 字段 | 说明 | -| ------------------- | --------------------------------------- | -| `http.url` | 目标 URL | -| `http.method` | HTTP 方法(覆盖 defaults) | -| `http.headers` | 请求头(与 defaults.http.headers 合并) | -| `http.body` | 请求体 | -| `http.ignoreSSL` | 忽略 HTTPS 证书校验,默认 `false` | -| `http.maxRedirects` | 最大重定向跟随次数,默认 `0`(不跟随) | +### HTTP Checker(`type: http`) -**Cmd 类型** (`type: cmd`) +**全局默认值(`defaults.http`)** -| 字段 | 说明 | -| ---------- | -------------------------------------- | -| `cmd.exec` | 可执行文件名或路径 | -| `cmd.args` | 命令行参数列表 | -| `cmd.env` | 环境变量覆盖(继承进程环境变量并合并) | -| `cmd.cwd` | 工作目录(相对于配置文件所在目录) | +| 字段 | 说明 | 必填 | 默认值 | +| -------------- | -------------------------------------------------- | ---- | ------- | +| `maxBodyBytes` | 响应体最大字节数 | 否 | `100MB` | +| `headers` | 默认请求头(target 中的 headers 会合并覆盖同名头) | 否 | | -**DB 类型** (`type: db`) +**配置项** -| 字段 | 说明 | -| ---------- | ------------------------------------------------------------- | -| `db.url` | 数据库连接字符串,支持 `postgres://`、`mysql://`、`sqlite://` | -| `db.query` | SQL 查询语句(不配置时仅测试连接) | +| 字段 | 说明 | 必填 | 默认值 | +| ------------------- | --------------------------------------- | ---- | ------- | +| `http.url` | 目标 URL | 是 | | +| `http.method` | HTTP 方法 | 否 | `GET` | +| `http.headers` | 请求头(与 defaults.http.headers 合并) | 否 | | +| `http.body` | 请求体 | 否 | | +| `http.ignoreSSL` | 忽略 HTTPS 证书校验 | 否 | `false` | +| `http.maxRedirects` | 最大重定向跟随次数 | 否 | `0` | -**TCP 类型** (`type: tcp`) +**expect 校验项** -| 字段 | 说明 | -| ----------------------- | ------------------------------------------------------- | -| `tcp.host` | 目标主机地址 | -| `tcp.port` | 目标端口(1-65535) | -| `tcp.readBanner` | 是否读取服务端 banner,默认 `false` | -| `tcp.bannerReadTimeout` | banner 读取超时(毫秒),默认 `2000` | -| `tcp.maxBannerBytes` | banner 最大字节数,支持 `KB`/`MB`/`GB` 单位,默认 `4KB` | +| 字段 | 说明 | 必填 | 默认值 | +| ------------ | -------------------------------------------------- | ---- | ------- | +| `status` | 可接受的状态码列表,支持精确码和范围(如 `"2xx"`) | 否 | `[200]` | +| `headers` | 响应头校验,使用动态键名和 `KeyValueExpect` | 否 | | +| `body` | 响应体校验,使用 `ContentRules` 数组 | 否 | | +| `durationMs` | 完整执行耗时校验,使用 `ValueMatcher` | 否 | | -**ICMP 类型** (`type: icmp`) +**配置示例** -| 字段 | 说明 | -| ----------------- | ----------------------------------- | -| `icmp.host` | 目标主机地址 | -| `icmp.count` | ICMP 包数量,默认 `3`,范围 `1-100` | -| `icmp.packetSize` | ICMP 包大小(bytes),默认 `56` | +```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 +``` + +--- + +### Cmd Checker(`type: cmd`) + +**全局默认值(`defaults.cmd`)** + +| 字段 | 说明 | 必填 | 默认值 | +| ---------------- | -------------------------------------- | ---- | ------- | +| `maxOutputBytes` | 输出最大字节数 | 否 | `100MB` | +| `cwd` | 默认工作目录(相对于配置文件所在目录) | 否 | `.` | + +**配置项** + +| 字段 | 说明 | 必填 | 默认值 | +| ---------- | -------------------------------------- | ---- | ------ | +| `cmd.exec` | 可执行文件名或路径 | 是 | | +| `cmd.args` | 命令行参数列表 | 否 | `[]` | +| `cmd.env` | 环境变量覆盖(继承进程环境变量并合并) | 否 | | +| `cmd.cwd` | 工作目录(相对于配置文件所在目录) | 否 | | + +**expect 校验项** + +| 字段 | 说明 | 必填 | 默认值 | +| ------------ | -------------------------------------- | ---- | ------ | +| `exitCode` | 可接受的退出码列表 | 否 | `[0]` | +| `stdout` | 标准输出校验,使用 `ContentRules` 数组 | 否 | | +| `stderr` | 标准错误校验,使用 `ContentRules` 数组 | 否 | | +| `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` | 查询结果逐行校验,数组内每行为列名到 `KeyValueExpect` 的映射 | 否 | | +| `result` | 完整查询结果 `{ rows, rowCount }` 校验,使用 `ContentRules` 数组 | 否 | | +| `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 内容校验,使用 `ContentRules` 数组,需开启 `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`) + +**全局默认值(`defaults.udp`)** + +| 字段 | 说明 | 必填 | 默认值 | +| ------------------ | ---------------------------------------- | ---- | ------ | +| `encoding` | payload 编码 | 否 | `text` | +| `responseEncoding` | 响应解码 | 否 | `text` | +| `maxResponseBytes` | 响应最大字节数,支持 `KB`/`MB`/`GB` 单位 | 否 | `4KB` | + +**配置项** + +| 字段 | 说明 | 必填 | 默认值 | +| ---------------------- | ---------------------------------------- | ---- | ------ | +| `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` | 响应内容校验,使用 `ContentRules` 数组 | 否 | | +| `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 输出解析。 -**LLM 类型** (`type: llm`) +**expect 校验项** -| 字段 | 说明 | -| --------------------- | ----------------------------------------------------------- | -| `llm.provider` | 模型提供方:`openai`、`openai-responses`、`anthropic` | -| `llm.url` | API base URL | -| `llm.model` | 模型名称 | -| `llm.prompt` | 单轮 prompt | -| `llm.mode` | 调用模式:`http`(默认,非流式)或 `stream`(流式) | -| `llm.key` | API key(默认空字符串,支持 `${VAR}` 变量替换) | -| `llm.authToken` | Bearer token(仅 `anthropic` provider,与 `key` 互斥) | -| `llm.headers` | 附加请求头(与 `defaults.llm.headers` 合并) | -| `llm.ignoreSSL` | 忽略 HTTPS 证书校验,默认 `false` | -| `llm.options` | 生成选项(与 `defaults.llm.options` 合并) | -| `llm.providerOptions` | Provider 专属选项(与 `defaults.llm.providerOptions` 合并) | +| 字段 | 说明 | 必填 | 默认值 | +| ------------------- | --------------------------------------------------- | ---- | ------ | +| `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 +``` + +--- + +### LLM Checker(`type: llm`) + +**全局默认值(`defaults.llm`)** + +| 字段 | 说明 | 必填 | 默认值 | +| ----------------- | ------------------- | ---- | ------- | +| `mode` | 调用模式 | 否 | | +| `headers` | 默认请求头 | 否 | | +| `ignoreSSL` | 忽略 HTTPS 证书校验 | 否 | `false` | +| `options` | 生成选项 | 否 | | +| `providerOptions` | Provider 专属选项 | 否 | | + +不支持 `provider`、`url`、`model`、`key`、`authToken`、`prompt`。 + +**配置项** + +| 字段 | 说明 | 必填 | 默认值 | +| --------------------- | ----------------------------------------------------------- | ---- | ------- | +| `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` | 附加请求头(与 `defaults.llm.headers` 合并) | 否 | | +| `llm.ignoreSSL` | 忽略 HTTPS 证书校验 | 否 | `false` | +| `llm.options` | 生成选项(与 `defaults.llm.options` 合并) | 否 | | +| `llm.providerOptions` | Provider 专属选项(与 `defaults.llm.providerOptions` 合并) | 否 | | `llm.options` 支持 `maxOutputTokens`(默认 `16`)、`temperature`(默认 `0`)、`topP`、`topK`、`presencePenalty`、`frequencyPenalty`、`stopSequences`、`seed`。 -`defaults.llm` 支持 `mode`、`headers`、`ignoreSSL`、`options`、`providerOptions`,不支持 `provider`、`url`、`model`、`key`、`authToken`、`prompt`。 +**expect 校验项** -#### expect — 期望校验 +| 字段 | 说明 | 必填 | 默认值 | +| ----------------- | ---------------------------------------------------------------------- | ---- | ------- | +| `status` | 可接受的状态码列表,支持精确码和范围(如 `"2xx"`) | 否 | `[200]` | +| `headers` | 响应头校验,使用动态键名和 `KeyValueExpect` | 否 | | +| `output` | 模型输出校验,使用 `ContentRules` 数组 | 否 | | +| `finishReason` | finish reason 校验,使用 `ValueMatcher` | 否 | | +| `rawFinishReason` | 原始 finish reason 校验,使用 `ValueMatcher` | 否 | | +| `usage` | Token usage 校验(`inputTokens`/`outputTokens`/`totalTokens` matcher) | 否 | | +| `stream` | 流式断言(`completed`、`firstTokenMs` matcher,仅 `mode: stream`) | 否 | | +| `durationMs` | 完整执行耗时校验,使用 `ValueMatcher` | 否 | | -| 字段 | 适用类型 | 说明 | -| ------------------- | -------- | ---------------------------------------------------------------------- | -| `status` | HTTP/LLM | 可接受的状态码列表,支持精确码和范围(如 `"2xx"`);默认 `[200]` | -| `exitCode` | Cmd | 可接受的退出码列表;未指定时默认 `[0]` | -| `headers` | HTTP/LLM | 响应头校验,使用动态键名和 `KeyValueExpect` | -| `durationMs` | 全部 | 完整执行耗时校验,使用 `ValueMatcher`,如 `{ lte: 1000 }` | -| `output` | LLM | 模型输出校验,使用 `ContentRules` 数组 | -| `finishReason` | LLM | finish reason 校验,使用 `ValueMatcher` | -| `rawFinishReason` | LLM | 原始 finish reason 校验,使用 `ValueMatcher` | -| `usage` | LLM | Token usage 校验(`inputTokens`/`outputTokens`/`totalTokens` matcher) | -| `stream` | LLM | 流式断言(`completed`、`firstTokenMs` matcher,仅 `mode: stream`) | -| `body` | HTTP | 响应体校验,使用 `ContentRules` 数组 | -| `stdout` / `stderr` | Cmd | 输出校验,使用 `ContentRules` 数组 | -| `rowCount` | DB | 查询返回行数校验,使用 `ValueMatcher` | -| `rows` | DB | 查询结果逐行校验,数组内每行为列名到 `KeyValueExpect` 的映射 | -| `result` | DB | 完整查询结果 `{ rows, rowCount }` 校验,使用 `ContentRules` 数组 | -| `connected` | TCP | 期望连接结果,`true`(默认)可达或 `false` 期望不可达 | -| `banner` | TCP | Banner 内容校验,使用 `ContentRules` 数组,需开启 `tcp.readBanner` | -| `responded` | UDP | 期望是否收到响应,默认 `true` | -| `response` | UDP | 响应内容校验,使用 `ContentRules` 数组 | -| `responseSize` | UDP | 响应字节数校验,使用 `ValueMatcher` | -| `sourceHost` | UDP | 响应来源地址校验,使用 `ValueMatcher` | -| `sourcePort` | UDP | 响应来源端口校验,使用 `ValueMatcher` | -| `alive` | ICMP | 期望主机可达性,默认 `true` | -| `packetLossPercent` | ICMP | 丢包率百分比校验,范围 `0-100`,使用 `ValueMatcher` | -| `avgLatencyMs` | ICMP | 平均延迟校验,使用 `ValueMatcher` | -| `maxLatencyMs` | ICMP | 最大单次延迟校验,使用 `ValueMatcher` | +**配置示例** -**ContentRules 校验项**(`body`、`stdout`、`stderr`、`banner`、`response`、`output`、`result` 均使用数组): +```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" +``` + +--- + +### 通用校验规则 + +#### ContentRules 校验项 + +`body`、`stdout`、`stderr`、`banner`、`response`、`output`、`result` 均使用数组: - `contains` — 响应体包含指定文本 - `regex` — 正则匹配(启动期会拒绝存在 ReDoS 风险的模式) @@ -337,15 +507,20 @@ ICMP checker 通过系统 `ping` 命令执行 ICMP 探测,支持 Linux、macOS - `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: ... }`。 +#### ValueMatcher -旧字段 `maxDurationMs`、`maxPacketLoss`、`maxAvgLatencyMs`、`maxMaxLatencyMs` 和旧正则字段 `match` 已移除,请分别改用 `durationMs`、ICMP matcher 字段和 `regex`。 +`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: ... }`。 -**大小说明**:`maxBodyBytes` 和 `maxOutputBytes` 支持 `KB`、`MB`、`GB` 单位,也可直接使用数字。 +#### KeyValueExpect -**时长格式**:`500ms`、`30s`、`5m`、`2h`、`7d` +`headers`、`rows` 中每行使用的校验结构,支持 ValueMatcher 的全部字段。 -**JSON Schema**:仓库根目录导出 `probe-config.schema.json`,在 YAML 文件顶部添加 `# yaml-language-server: $schema=./probe-config.schema.json` 即可在编辑器中获得提示和校验。 +### 补充说明 + +- **大小说明**:`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 注释。 @@ -371,4 +546,4 @@ bun run verify # check + build ## License -MIT +Apache-2.0 diff --git a/assets/screenshot/dark_detail.png b/assets/screenshot/dark_detail.png new file mode 100644 index 0000000..db1389b Binary files /dev/null and b/assets/screenshot/dark_detail.png differ diff --git a/assets/screenshot/dark_index.png b/assets/screenshot/dark_index.png new file mode 100644 index 0000000..05665ba Binary files /dev/null and b/assets/screenshot/dark_index.png differ diff --git a/assets/screenshot/light_detail.png b/assets/screenshot/light_detail.png new file mode 100644 index 0000000..4d4ba64 Binary files /dev/null and b/assets/screenshot/light_detail.png differ diff --git a/assets/screenshot/light_index.png b/assets/screenshot/light_index.png new file mode 100644 index 0000000..9a58431 Binary files /dev/null and b/assets/screenshot/light_index.png differ