1
0
2026-05-09 14:48:49 +08:00
2026-05-09 14:48:49 +08:00

DiAL

基于 Bun + TypeScript 的多类型拨测监控工具。通过 YAML 配置文件定义 HTTP 和命令行拨测目标,后端按配置定时并发拨测,结果持久化到本地 SQLite前端 Dashboard 展示各目标实时状态、可用率、耗时趋势等并支持手动、10 秒、30 秒、1 分钟、5 分钟刷新频率切换,以及系统、明亮、黑暗三种主题模式。主题模式选择会保存在当前浏览器本地存储中,同一浏览器再次访问时自动恢复。

快速开始

bun install
cp probes.example.yaml probes.yaml
bun run dev probes.yaml

bun run dev 启动双进程开发服务器Vite :5173 + Bun API :3000访问 http://127.0.0.1:5173

开发验证

bun run check   # schema:check + typecheck + lint + bun test
bun run verify  # check + build

verify 会基于当前源码重新构建生产 executable。原 smoke test 已移除executable/E2E 验证后续单独补充。

配置文件

程序通过 YAML 配置文件定义所有运行参数:

# yaml-language-server: $schema=./probe-config.schema.json

server:
  host: "127.0.0.1"
  port: 3000
  dataDir: "/tmp/probes_data"

runtime:
  maxConcurrentChecks: 20
  retention: "7d"

defaults:
  interval: "5s"
  timeout: "10s"
  http:
    method: GET
    maxBodyBytes: "10MB"
  cmd:
    maxOutputBytes: "1MB"

targets:
  - name: "Baidu"
    type: http
    http:
      url: "https://www.baidu.com"
    expect:
      status: [200]
      maxDurationMs: 10000

  - name: "JSON API 示例"
    type: http
    http:
      url: "https://httpbin.org/json"
    expect:
      status: [200]
      headers:
        Content-Type:
          contains: "application/json"
      body:
        - contains: "slideshow"
        - json:
            path: "$.slideshow.title"
            equals: "Sample Slide Show"

  - name: "HTML 页面示例"
    type: http
    http:
      url: "https://httpbin.org/html"
    expect:
      status: [200]
      body:
        - contains: "Moby-Dick"
        - xpath:
            path: "/html/body/h1/text()"
            equals: "Herman Melville - Moby-Dick"

  - name: "Bun 脚本检查"
    type: cmd
    cmd:
      exec: "bun"
      args: ["-e", "console.log('ok')"]
    expect:
      exitCode: [0]
      stdout:
        - contains: "ok"

配置说明

  • server: 服务配置(均可省略,使用默认值)
    • host: 监听地址,默认 127.0.0.1
    • port: 监听端口,默认 3000
    • dataDir: 数据目录,默认 ./data,相对路径基于配置文件所在目录解析
  • runtime: 运行时配置
    • maxConcurrentChecks: 最大并发拨测数,默认 20
    • retention: 历史数据保留时长,默认 7d,支持 ms/s/m/h/d 单位
  • defaults: 全局默认值(均可省略)
    • interval: 拨测间隔,默认 30s
    • timeout: 超时时间,默认 10s
    • http: HTTP 类型默认值
      • method: HTTP 方法,默认 GET,必须使用大写枚举值,支持 GETHEADPOSTPUTPATCHDELETEOPTIONS
      • maxBodyBytes: 响应体最大字节数,默认 100MB
      • headers: 默认请求头target 中的 headers 会合并覆盖 defaults 中的同名头)
    • cmd: Cmd 类型默认值
      • maxOutputBytes: 输出最大字节数,默认 100MB
      • cwd: 默认工作目录(相对于配置文件所在目录解析,默认 .
  • targets: 拨测目标列表(必填)
    • name: 目标名称(必填,唯一)
    • type: 目标类型,httpcmd(必填)
    • group: 分组名称(可选,默认 "default"
    • http: HTTP 拨测配置type 为 http 时必填)
      • url: 目标 URL
      • methodheadersbody: 请求参数(headers 会与 defaults.http.headers 合并target 优先)
      • ignoreSSL: 是否忽略 HTTPS 证书校验,默认 false,用于自签名或私有证书服务
      • maxRedirects: 最大重定向跟随次数,默认 0(不跟随重定向)
    • cmd: 命令行拨测配置type 为 cmd 时必填)
      • exec: 可执行文件名或路径
      • args: 命令行参数列表
      • env: 环境变量覆盖(可选,继承进程环境变量并合并覆盖)
      • cwd: 工作目录(可选,相对于配置文件所在目录解析,默认 .
    • intervaltimeout: 覆盖全局默认值
    • expect: 期望校验
      • status: 可接受的状态码列表HTTP支持精确状态码和范围模式"2xx")混合配置;未指定时默认 [200]
      • exitCode: 可接受的退出码列表Cmd未指定时不校验退出码
      • headers: 响应头校验HTTP支持字符串精确匹配或操作符对象
      • maxDurationMs: 最大耗时阈值(毫秒)
        • HTTP覆盖完整执行含重定向、响应体读取和 expect 校验)
        • Cmd覆盖命令执行耗时含 stdout/stderr 读取)
      • body: HTTP 响应体校验(数组,可组合使用)
        • contains: 响应体包含的文本
        • regex: 响应体匹配的正则表达式(启动期会拒绝嵌套量词等存在 ReDoS 风险的模式)
        • json: JSONPath 提取值比较
          • path: JSONPath 表达式(必填,如 $.slideshow.title
          • 比较操作符(可选,无操作符时仅检查路径对应值是否存在)
        • css: CSS 选择器提取 HTML 元素比较
          • selector: CSS 选择器(必填)
          • attr: 提取元素属性值而非文本内容(可选,如 hrefclass
          • 比较操作符(可选,无操作符时仅检查元素是否存在)
        • xpath: XPath 提取 XML/HTML 节点比较
          • path: XPath 表达式(必填,如 /html/body/h1/text()
          • 比较操作符(可选,无操作符时仅检查节点是否存在)
      • stdout / stderr: Cmd 输出校验(数组,每项为一个操作符对象)
      • 比较操作符:equals(默认)、containsmatch(正则,启动期会拒绝存在 ReDoS 风险的模式)、emptyexistsgteltegtlt

大小说明:maxBodyBytesmaxOutputBytes 支持单位 KBMBGB,也可直接使用数字(非负安全整数字节数)。

配置校验:系统启动时会先用 TypeBox 生成的 JSON Schema 契约校验字段类型、必填字段、枚举、数组/对象形状和未知字段,再执行语义 validator 校验 target name 唯一性、URL、正则、JSONPath、XPath、size/duration 解析等规则。非法配置会阻止启动并输出中文错误信息。

未知字段:除 http.headersdefaults.http.headersexpect.headerscmd.env 等动态键值表外,未知字段会导致启动失败。配置备注请使用 YAML 注释,不要添加 notecomment 等未声明字段。

JSON Schema仓库根目录导出 probe-config.schema.json,可在 YAML 文件顶部添加 # yaml-language-server: $schema=./probe-config.schema.json 获取编辑器提示和静态校验。该 schema 由运行期契约 fragments 生成,提交前可用 bun run schema:check 检查同步。

时长格式支持:500ms30s5m2h7d

API 端点

端点 说明
GET /health 健康检查
GET /api/meta 运行时元信息checker 类型列表)
GET /api/dashboard?window=24h&recentLimit=30 Dashboard 首屏聚合数据summary + targets
GET /api/targets/:id/metrics?from=ISO&to=ISO&bucket=1h 指定目标的统计、可靠性指标和按小时趋势
GET /api/targets/:id/history?from=ISO&to=ISO&page=1&pageSize=20 指定目标的拨测记录(时间范围 + 分页,pageSize 最大 200

响应字段

DashboardResponse: summarytargets

DashboardResponse.summary: totalupdownlastCheckTimeincidentswindow

MetaResponse: checkerTypes(已注册 checker 类型标识符列表)

TargetStatus: idnametypechecker 类型,如 http/cmdtargetURL 或命令摘要)、groupintervallatestCheckstatscurrentStreakrecentSamples

RecentSample: timestampdurationMsup

CheckResult: timestampmatcheddurationMsstatusDetailfailure

CheckFailure: kinderror/mismatchphasepathmessageexpected?(仅 mismatchactual?(仅 mismatch

TargetStats: totalChecksupChecksdownChecksavailability

CurrentStreak: upcountcapped?

TargetMetricsResponse: targetIdwindowstatstrend

TargetMetricsResponse.stats: totalChecksupChecksdownChecksavailabilityavgDurationMsp95DurationMsp99DurationMsmttrlongestOutageincidentCountcurrentStreak

TrendPoint: bucketStartavgDurationMsminDurationMsmaxDurationMsavailabilitytotalChecksupChecksdownChecks

HistoryResponse: itemsCheckResult[])、totalpagepageSize

错误响应

API 错误返回 ApiErrorResponse 格式:

{ "error": "描述信息", "status": 400 }
状态码 触发场景
400 参数格式错误(无效 ID、from/to 缺失或格式错误、page/pageSize 非正整数、pageSize 超过 200
404 目标不存在、API 路由未匹配、非 GET 方法请求 API 路由

运行参数

CLI 只接受一个参数YAML 配置文件路径。

./dist/dial-server ./probes.yaml

目标状态判定

单层判定模型,适用于 HTTP 和 Cmd 两种类型:

  • matched: 是否符合 expect 规则HTTP 未指定 expect.status 时默认检查 [200]
  • UP = matched
  • DOWN = NOT matched

执行失败(网络错误、超时、进程崩溃)和 expect 不匹配都统一为 matched=false,通过 failure.kind 区分("error" vs "mismatch")。


开发相关文档(项目结构、构建、测试、代码规范等)请参阅 DEVELOPMENT.md

Description
No description provided
Readme Apache-2.0 5.7 MiB
Languages
TypeScript 99.1%
CSS 0.5%
JavaScript 0.3%
Dockerfile 0.1%