1
0
Files
DiAL/README.md

27 KiB
Raw Blame History

DiAL

轻量级多类型拨测监控工具

基于 Bun + TypeScript 构建 · YAML 配置驱动 · 内置 Dashboard


DiAL 是一个自托管的拨测监控工具,支持 HTTP命令行数据库TCPUDPICMPLLM 多种拨测类型。通过 YAML 配置文件定义拨测目标,后端定时并发执行拨测并将结果持久化到本地 SQLite前端 Dashboard 展示各目标的实时状态、可用率和耗时趋势。

功能亮点:

  • 多种拨测类型HTTPGET/POST/PUT 等、Cmd命令行执行、DBPostgreSQL/MySQL/SQLite、TCP端口可达性 + Banner 探测、UDP自定义 payload 请求-响应、ICMP存活检测、延迟、丢包率、LLM大模型服务应用层健康检查
  • 丰富的校验规则状态码、响应头、JSONPath、CSS 选择器、XPath、正则匹配、数值比较等
  • 结构化观测数据:检查结果保留按需读取的 HTTP body 预览、TCP/UDP 响应摘要、ICMP 丢包率、CMD 输出预览、LLM token 用量等 observation便于排障和后续分析
  • 响应式 Dashboard实时状态、可用率统计、耗时趋势图、手动/自动刷新、版本号展示
  • 多主题支持:系统、明亮、黑暗三种主题模式
  • 零外部依赖:数据存储使用 SQLite无需额外数据库服务

版本管理

DiAL 使用 package.json.version 作为唯一版本源Dashboard Header 展示当前运行实例版本号(如 v0.1.0)。

版本升迁命令:

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。

应用截图

亮色 暗色
主页 index-light index-dark
详情页 detail-light detail-dark

快速开始

前置条件: Bun >= 1.0

ICMP checker 依赖系统 ping 命令。精简容器镜像需额外安装,例如 Alpine 可安装 iputils-ping

# 克隆仓库
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。

生产部署

# 构建
bun run build

# 运行
./dist/dial-server ./probes.yaml

构建产物为独立可执行文件,只需一个 YAML 配置文件即可运行。

Docker 部署

DiAL 提供基于 Alpine 的多阶段镜像。构建阶段使用 Bun 生成 musl 目标单可执行文件,运行阶段只包含 dial-server、基础证书、ping、musl executable 必需运行库、时区数据和容器运行所需目录。

# 构建当前架构镜像
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,默认监听 0.0.0.0:3000,并将 SQLite 数据和日志写入 /data/dial

多架构镜像可通过 Docker Buildx 构建:

docker buildx build --platform linux/amd64,linux/arm64 -t dial:alpine .

如需在容器中运行 ICMP checker除镜像内置的 iputils-ping 外,还需要授予 NET_RAW capability

docker run --rm --cap-add=NET_RAW -p 3000:3000 -v dial-data:/data/dial dial:alpine

官方镜像不内置 bunnodecurldigpsqlmysqlredis-cli 等 CMD checker 可能需要的额外命令。需要这些命令时请使用派生镜像自行安装:

FROM dial:alpine

USER root
RUN apk add --no-cache curl bind-tools postgresql-client
USER dial

跨平台发布打包

# 编译全部 7 个目标平台
bun run release

# 编译指定平台
bun run release --target linux-x64
bun run release --target linux-x64,windows-x64,darwin-arm64

支持的目标平台:linux-x64linux-arm64linux-x64-musllinux-arm64-muslwindows-x64darwin-x64darwin-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.yamlLICENSE,解压后可直接使用。

配置文件

程序通过 YAML 配置文件定义所有运行参数,完整示例参见 probes.example.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: # 拨测目标列表(必填)
  - id: "baidu-home"
    name: "Baidu"
    type: http
    http:
      url: "https://www.baidu.com"
    expect:
      # ...
  - id: "my-cmd"
    name: "脚本检查"
    type: cmd
    cmd:
      # ...
    expect:
      # ...
  # ... 更多 targets

server.listen — 监听配置

字段 说明 必填 默认值
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 按时间滚动:hourlydailyweekly daily
server.logging.file.rotation.maxFiles 保留的归档文件数量(不含活跃日志) 14

日志等级支持:tracedebuginfowarnerrorfatal

控制台始终输出pretty 格式),文件始终输出 JSONL 格式并支持滚动。rotation.sizerotation.frequency 任一条件触发即滚动。

内置默认值

未显式配置时,系统使用以下内置默认值:

  • interval30s(拨测间隔)
  • timeout10s(超时时间)
  • 各 checker 专属默认值见对应章节

如需在配置文件中共享相同的配置值,可使用 variables 定义变量,然后在 serverprobestargets 中通过 ${var} 引用。例如在 variables 中定义 default_interval: "30s",在多个 target 的 interval 字段写 ${default_interval}

variables — 配置变量

variables 是顶层动态键值表key 必须符合 [a-zA-Z_][a-zA-Z0-9_]*value 仅支持 string、number、boolean。serverprobestargets 中的字符串值可引用变量:

  • ${key}:引用 variables 或环境变量
  • ${key|default}:变量和环境变量都不存在时使用默认值,第一个 | 后的内容为默认值
  • ${key|}:变量和环境变量都不存在时使用空字符串作为默认值
  • $${key}:转义输出字面量 ${key}

解析优先级为 variables -> process.env -> 默认值,三者均不存在时配置校验失败。字段值完整等于单个变量引用时会保留 number/boolean/string 类型,环境变量和默认值会做类型推断,但空字符串保持为字符串;部分拼接时统一转为字符串。变量替换作用于 serverprobestargets,不作用于 variables 段自身,且不会替换 targets[].idtargets[].type 字段;对象 key 不参与替换。

targets — 拨测目标列表(必填)

每个 target 的通用字段:

字段 说明 必填 默认值
id 目标唯一标识,最长 30 字符,支持字母数字、下划线、连字符,不参与变量替换
name 展示名称,最长 30 字符,支持变量替换,可省略或显式 null前端展示时 null 回退到 id
description 目标描述,最长 500 字符,支持变量替换,可省略或显式 null允许空字符串
type 目标类型:httpcmddbtcpudpicmpllm
group 分组名称 default
interval 拨测间隔,未配置时使用内置默认值 30s 30s
timeout 超时时间,未配置时使用内置默认值 10s 10s

HTTP Checkertype: 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

配置示例

- 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 Checkertype: cmd

配置项

字段 说明 必填 默认值
cmd.exec 可执行文件名或路径
cmd.args 命令行参数列表 []
cmd.env 环境变量覆盖(继承进程环境变量并合并)
cmd.cwd 工作目录(相对于配置文件所在目录)

expect 校验项

字段 说明 必填 默认值
exitCode 可接受的退出码列表 [0]
stdout 标准输出校验,使用 ContentExpectations 数组
stderr 标准错误校验,使用 ContentExpectations 数组
durationMs 完整执行耗时校验,使用 ValueMatcher

配置示例

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

DB Checkertype: db

配置项

字段 说明 必填 默认值
db.url 数据库连接字符串,支持 postgres://mysql://sqlite://
db.query SQL 查询语句,不配置时仅测试连接

expect 校验项

字段 说明 必填 默认值
rowCount 查询返回行数校验,使用 ValueMatcher
rows 查询结果逐行校验,数组内每行为列名到 KeyedExpectations 的映射
result 完整查询结果 { rows, rowCount } 校验,使用 ContentExpectations 数组
durationMs 完整执行耗时校验,使用 ValueMatcher

配置示例

- 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 Checkertype: 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

配置示例

- id: "redis-port"
  name: "Redis 端口可达"
  type: tcp
  tcp:
    host: "127.0.0.1"
    port: 6379
  expect:
    durationMs:
      lte: 3000

UDP Checkertype: udp

配置项

字段 说明 必填 默认值
udp.host 目标主机地址
udp.port 目标端口1-65535
udp.payload 发送数据 ""
udp.encoding payload 编码:texthexbase64 text
udp.responseEncoding 响应解码:texthexbase64 text
udp.maxResponseBytes 响应最大字节数,支持 KB/MB/GB 单位 4KB

expect 校验项

字段 说明 必填 默认值
responded 期望是否收到响应 true
response 响应内容校验,使用 ContentExpectations 数组
responseSize 响应字节数校验,使用 ValueMatcher
sourceHost 响应来源地址校验,使用 ValueMatcher
sourcePort 响应来源端口校验,使用 ValueMatcher
durationMs 完整执行耗时校验,使用 ValueMatcher

配置示例

- 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 Checkertype: 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

配置示例

- 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 Checkertype: llm

配置项

字段 说明 必填 默认值
llm.provider 模型提供方:openaiopenai-responsesanthropic
llm.url API base URL
llm.model 模型名称
llm.prompt 单轮 prompt
llm.mode 调用模式:http(非流式)或 stream(流式) http
llm.key API key支持 ${VAR} 变量替换 ""
llm.authToken Bearer tokenanthropic providerkey 互斥)
llm.headers 附加请求头
llm.ignoreSSL 忽略 HTTPS 证书校验 false
llm.options 生成选项
llm.providerOptions Provider 专属选项

llm.options 支持 maxOutputTokens(默认 16)、temperature(默认 0)、topPtopKpresencePenaltyfrequencyPenaltystopSequencesseed

expect 校验项

字段 说明 必填 默认值
status 可接受的状态码列表,支持精确码和范围(如 "2xx" [200]
headers 响应头校验,使用动态键名和 KeyedExpectations
output 模型输出校验,使用 ContentExpectations 数组
finishReason finish reason 校验,使用 ValueMatcher
rawFinishReason 原始 finish reason 校验,使用 ValueMatcher
usage Token usage 校验(inputTokens/outputTokens/totalTokens matcher
stream 流式断言(completedfirstTokenMs matchermode: stream
durationMs 完整执行耗时校验,使用 ValueMatcher

配置示例

- 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 校验项

bodystdoutstderrbannerresponseoutputresult 均使用数组:

  • contains — 响应体包含指定文本
  • regex — 正则匹配(启动期会拒绝存在 ReDoS 风险的模式)
  • json — JSONPath 提取值比较(path 必填,如 $.slideshow.title
  • css — CSS 选择器提取 HTML 元素(selector 必填,attr 可选提取属性)
  • xpath — XPath 提取 XML/HTML 节点(path 必填,如 /html/body/h1/text()

ValueMatcher

equalscontainsregexemptyexistsgteltegtltequals 支持 JSON 深度相等;regex 固定使用无 flags 正则;提取器未配置 matcher 时等价于 exists: true。ValueMatcher expect 字段也可直接写 string、number、boolean 或 null等价于 { equals: value };数组和对象必须显式写成 { equals: ... }

KeyedExpectations

headersrows 中每行使用的校验结构,支持 ValueMatcher 的全部字段。

补充说明

  • 大小说明maxBodyBytesmaxOutputBytesmaxResponseBytesmaxBannerBytes 支持 KBMBGB 单位,也可直接使用数字
  • 时长格式500ms30s5m2h7d
  • JSON Schema:仓库根目录导出 probe-config.schema.json,在 YAML 文件顶部添加 # yaml-language-server: $schema=./probe-config.schema.json 即可在编辑器中获得提示和校验
  • 旧字段移除maxDurationMsmaxPacketLossmaxAvgLatencyMsmaxMaxLatencyMs 和旧正则字段 match 已移除,请分别改用 durationMs、ICMP matcher 字段和 regex

注意: 配置校验在启动时执行,非法配置会阻止启动并输出错误信息。除动态键值表(headersenvvariables)外,未知字段会导致启动失败,请使用 YAML 注释。

目标状态判定

采用单层判定模型:

  • UP = 拨测结果符合 expect 规则
  • DOWN = 拨测结果不符合 expect 规则

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

API 返回的检查结果包含 detailobservationdetail 是后端按 checker 类型从结构化 observation 动态生成的人可读摘要,observation 保存该次检查的结构化观测数据。detail 不写入 SQLite存储层仅持久化 observation JSON、failure JSON、匹配状态、耗时和时间戳。

开发

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

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

License

Apache-2.0