# PulseGuard
**Repository Path**: yunyoko/PulseGuard
## Basic Information
- **Project Name**: PulseGuard
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Apache-2.0
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-06-15
- **Last Updated**: 2026-06-15
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# PulseGuard
[简体中文](./README.md) | [English](./README.en.md)
PulseGuard(脉守)是一个面向本地和局域网的小型 UI/API 探活控制台。它适合团队在内网环境里持续检查后台页面、登录前置流程、健康接口、批处理心跳、证书和基础网络可达性,并把运行历史、失败证据、告警策略和只读状态统一放在一个单实例控制台中管理。
PulseGuard 不是 SaaS、公开状态页、完整 E2E 测试管理平台或 incident/on-call 系统。当前边界是单实例、本地或 LAN 使用,默认 SQLite 持久化。
## 核心能力
- UI/API 探活任务:支持定时执行、手动执行、草稿调试、结构化断言和高级 Python 脚本。
- UI 前置脚本:扫描、草稿调试和正式运行都会先执行 `setup_script`,用于准备登录态、页面前提和业务上下文。
- 规则维护:支持 UI selector 稳定性提示、规则失效检测、API 响应字段预览和一键生成基础断言。
- 批量操作:按类型、标签和启用状态批量执行、启停、调频,并用命中数量防止误操作。
- 运行记录:已保存任务的定时、手动、批量和重跑均属于正式执行,会影响健康状态、成功率与告警;只有编辑器配置试运行不影响状态且不触发告警。
- 可信健康状态:支持健康、疑似故障、故障、疑似恢复、未知、观测陈旧、停用,Runner 异常不会误报为目标故障。
- 证据保留:失败时保存错误摘要、截图、Trace 和 Response Body;成功 API 响应默认只保留摘要。
- 执行节点追踪:记录本机和子节点名称、地址、网络区域、浏览器版本,并支持启停、认证心跳、可用状态和状态列表。
- 失败归因:区分被探测目标失败和 Runner 执行环境失败,便于判断是业务/断言问题还是探针环境问题。
- 告警策略:支持全局、标签级、任务级告警策略,覆盖冷却、恢复通知和通知渠道。
- 运维审计:记录任务、设置、批量操作、配置导入和版本恢复等关键操作。
- 任务版本:保存任务变更快照,支持查看和恢复历史版本。
- 只读出口:提供只读快照、JSON 指标和 Prometheus 指标。
- 配置迁移:支持配置导出、脱敏导出、导入预检和应用导入,可把配置 JSON 纳入 Git 管理。
- CLI/CI:支持按任务 ID、类型或标签运行探活,并用 exit code 表达流水线结果。
- 扩展探活:通过模板和 `ctx` helper 支持被动心跳、TLS 到期、HTTP keyword/redirect/asset、TCP、DNS 等检查。
## 技术栈
- Backend: FastAPI, SQLite, Playwright Python, `uv`
- Frontend: React, TypeScript, Vite, Ant Design
- Runtime: Docker Compose 或本地开发进程
- Persistence: SQLite + 本地 `data/`、`reports/`
## 快速启动
推荐用 Docker Compose 运行完整生产构建:
```powershell
docker compose up --build -d
```
默认发布到 `0.0.0.0:8787`:
- 本机访问:`http://127.0.0.1:8787`
- 局域网访问:`http://<本机局域网 IP>:8787`
常用检查:
```powershell
docker compose ps
docker compose logs --tail 80 pulseguard
Invoke-WebRequest -UseBasicParsing http://127.0.0.1:8787/api/health
```
如只允许本机访问,可在 `.env` 中设置:
```env
PULSEGUARD_PUBLISH_HOST=127.0.0.1
PULSEGUARD_HOST=0.0.0.0
PULSEGUARD_PORT=8787
PULSEGUARD_PUBLISH_PORT=8787
PULSEGUARD_ALERT_DETAIL_BASE_URL=http://127.0.0.1:8787
```
## 本地开发
后端依赖使用 `uv`:
```powershell
uv sync
uv run python -m playwright install chromium
uv run uvicorn app.main:app --app-dir backend --host 127.0.0.1 --port 8787 --reload
```
前端依赖使用 npm:
```powershell
cd frontend
npm ci
npm run dev
```
前端默认开发地址是 `http://127.0.0.1:5173`。如需要指定端口和后端代理:
```powershell
cd frontend
$env:VITE_DEV_API_TARGET="http://127.0.0.1:8787"
npm run dev -- --host 127.0.0.1 --port 5175
```
## UI 浏览器生命周期
UI 任务支持 `chromium`、`firefox`、`webkit` 三类 Playwright browser type。系统设置里可以分别配置:
- `enabled_browser_types`:允许任务选择和执行的 browser type。
- `prewarmed_browser_types`:后端启动或设置变更时自动预热的 browser type,必须是已启用类型,可以多选或为空。
- `browser_pool_sizes`:每个 browser type 独立的空 `BrowserContext` 储备数量,单类默认 5。
每个预热的 browser type 会保留 1 个 Playwright browser 进程,并按该 type 的 pool size 预创建空 `BrowserContext`。UI 任务会独占租用 1 个 context/page;任务结束只关闭 context,不关闭 browser,资源池随后补齐空 context。Web 与 H5 尺寸通过 context options 区分,同一个 browser 进程下可以并发运行不同 viewport 的任务。
`browser_type` 只对 UI 任务生效。任务执行时先解析执行节点,再在每个节点内解析 browser type;节点多选和 browser type 多选会按节点 × browser type 矩阵创建运行记录。只有“已启用且该节点已安装”的 browser type 会实际执行,缺失或未启用的组合会记录为 Runner 异常。启用新的 browser type 后,主节点会请求本机和可用子节点安装对应 Playwright browser,子节点也会在健康检查中上报当前已安装和可用的 browser type。
## 多运行节点
PulseGuard 默认保留并启用内置 `local` 节点。子节点是独立部署的执行服务,只负责暴露受 token 保护的健康检查和执行接口、执行主节点下发的任务、回传运行结果和证据文件;子节点不会主动注册到主节点、不会启动调度器、不会写主节点数据库,也不会发送告警。
创建子节点:
1. 在子节点服务器上用 worker 命令部署并启动服务,终端会输出当前子节点地址和认证 token。
2. 在主节点打开“系统设置 > 执行配置”。
3. 点击“新增子节点”,填写节点名称、子节点可被主节点访问的地址、网络区域和终端输出的认证 token。这个操作只在主节点保存节点记录,不会让子节点主动注册。
4. 点击“测试连接”确认主节点可以访问子节点 `/api/worker/health`。
5. 在任务详情或编辑抽屉中选择“多选并行”并勾选节点,或选择“轮询所有启用节点”。
结果展示:
- 多选并行时,同一次触发会为每个节点创建运行记录,并写入同一个 `run_group_id`;如果 UI 任务同时选择多个 browser type,会按节点和 browser type 的矩阵创建记录。
- 运行详情和运行抽屉会在“多节点执行结果”中展示同组所有节点、browser type、节点执行状态、运行状态、失败来源、耗时、错误摘要和证据文件入口;点击下方节点详情 Tab 可在当前详情内切换不同节点和 browser type 的完整结果。
- 多节点聚合只更新一次任务健康状态:任一可用节点出现目标失败/超时,本轮任务失败;全部可用节点成功才算成功;节点不可用只记录 `failure_kind=runner`,不计入目标失败。
- 运行记录页可按执行节点筛选;需要按一次触发查看全量节点结果时,可用 `run_group_id` 查询同组运行记录。
下面的子节点启动命令都在子节点服务器执行,不在主节点执行。主节点只负责在页面里手动添加该子节点的地址和 token。
子节点一行启动(源码方式,不需要前端):
```powershell
uv run python -m backend.app.worker --host 0.0.0.0 --port 8788
```
需要命名或标记区域时再追加 `--name office-worker-1 --region office-lan`。启动后会打印:
```text
PulseGuard worker node is ready.
name: office-worker-1
address: set this in the main console, for example http://:8788
region: office-lan
token: pgrn_xxx
token_source: ...
```
`address` 不需要由子节点自动决定。主节点页面添加子节点时,填写主节点实际能访问到的地址,例如 `http://<子节点 IP>:8788`。
如果没有显式传入 `--token` 或 `PULSEGUARD_WORKER_TOKEN`,worker 会把 token 保存到 `PULSEGUARD_WORKER_TOKEN_FILE`,默认是数据目录下的 `worker-token`,后续重启会复用同一个 token。
Docker 子节点不需要复制完整源码,也不建议默认在子节点从源码构建。推荐直接运行预构建 worker 镜像;这样启动时只拉取 worker 镜像,不会在子节点额外拉取 `uv` 镜像或执行 `uv sync`。
Windows PowerShell 直连 GitHub 可直接执行:
```powershell
mkdir pulseguard-worker -Force; cd pulseguard-worker
Invoke-WebRequest -UseBasicParsing "https://raw.githubusercontent.com/liyanqing90/PulseGuard/codex/github-publish/docker-compose.worker.yml" -OutFile docker-compose.worker.yml
$env:PULSEGUARD_WORKER_NAME = $env:COMPUTERNAME
$env:PULSEGUARD_WORKER_REGION = "default"
$env:PULSEGUARD_WORKER_IMAGE = "ghcr.io/liyanqing90/pulseguard-worker:codex-github-publish"
$env:COMPOSE_PROJECT_NAME = "pulseguard-worker"
docker compose -f docker-compose.worker.yml pull
docker compose -f docker-compose.worker.yml up -d
docker update --restart unless-stopped pulseguard-worker
docker logs --tail 80 pulseguard-worker
```
Linux shell 可用:
```sh
mkdir -p pulseguard-worker && cd pulseguard-worker
curl -fsSL "https://raw.githubusercontent.com/liyanqing90/PulseGuard/codex/github-publish/docker-compose.worker.yml" -o docker-compose.worker.yml
export PULSEGUARD_WORKER_NAME="$(hostname)"
export PULSEGUARD_WORKER_REGION="default"
export PULSEGUARD_WORKER_IMAGE="ghcr.io/liyanqing90/pulseguard-worker:codex-github-publish"
export COMPOSE_PROJECT_NAME="pulseguard-worker"
docker compose -f docker-compose.worker.yml pull
docker compose -f docker-compose.worker.yml up -d
docker update --restart unless-stopped pulseguard-worker
docker logs --tail 80 pulseguard-worker
```
命令默认后台启动容器并设置 Docker 自启策略。启动后用 `docker logs --tail 80 pulseguard-worker` 查看认证 token;需要持续观察日志时再执行 `docker logs -f pulseguard-worker`。默认 `docker-compose.worker.yml` 不包含源码构建配置,不会隐式访问 GitHub。
worker 会在 `/api/worker/health` 上报版本、构建 SHA、当前镜像和是否启用平台更新。管理平台“执行节点”列表会展示这些信息。
如果希望管理平台可以主动向子节点推送更新,需要显式启用 updater profile。updater 会挂载宿主机 Docker socket,因此只允许更新当前 `pulseguard-worker` 服务,不支持任意命令:
```powershell
$env:COMPOSE_PROJECT_NAME = "pulseguard-worker"
$env:COMPOSE_PROFILES = "updater"
$env:PULSEGUARD_WORKER_UPDATER_URL = "http://pulseguard-worker-updater:8790"
$env:PULSEGUARD_WORKER_UPDATE_IMAGE = "ghcr.io/liyanqing90/pulseguard-worker:codex-github-publish"
docker compose -f docker-compose.worker.yml pull
docker compose -f docker-compose.worker.yml up -d
docker update --restart unless-stopped pulseguard-worker pulseguard-worker-updater
```
启用后,主节点“执行节点”列表会显示“支持平台更新”,可以点击“更新节点”。更新过程由子节点 updater 执行:拉取目标镜像、重建 worker、检查 `/api/worker/health`,失败时尝试回滚到旧镜像。
中国内地服务器访问 GitHub Raw 较慢或不稳定时,可以使用加速链接下载 compose 文件。这个加速链接只用于中国内地网络场景,并且只加速 compose 文件下载,不加速容器镜像拉取:
```powershell
mkdir pulseguard-worker -Force; cd pulseguard-worker
Invoke-WebRequest -UseBasicParsing "https://gh-proxy.org/https://raw.githubusercontent.com/liyanqing90/PulseGuard/codex/github-publish/docker-compose.worker.yml" -OutFile docker-compose.worker.yml
$env:PULSEGUARD_WORKER_NAME = $env:COMPUTERNAME
$env:PULSEGUARD_WORKER_REGION = "default"
$env:PULSEGUARD_WORKER_IMAGE = "ghcr.io/liyanqing90/pulseguard-worker:codex-github-publish"
$env:COMPOSE_PROJECT_NAME = "pulseguard-worker"
docker compose -f docker-compose.worker.yml pull
docker compose -f docker-compose.worker.yml up -d
docker update --restart unless-stopped pulseguard-worker
docker logs --tail 80 pulseguard-worker
```
如果中国内地服务器拉取 GHCR 镜像较慢,推荐先把 `ghcr.io/liyanqing90/pulseguard-worker:codex-github-publish` 同步到内网或国内镜像仓库,再把命令里的 `PULSEGUARD_WORKER_IMAGE` 替换成你的镜像地址。
如果子节点服务器不能访问 GitHub,建议在可访问的位置放一份定制的 `docker-compose.worker.yml`,让这个 compose 文件直接指向内网镜像。子节点服务器只需要下载这份 compose 文件再启动:
```sh
curl -fsSL "http://<可访问地址>/docker-compose.worker.yml" -o docker-compose.worker.yml
docker compose -f docker-compose.worker.yml up -d
docker update --restart unless-stopped pulseguard-worker
docker logs --tail 80 pulseguard-worker
```
只有在没有预构建镜像或内网镜像时,才建议使用源码构建备用路径。该路径会拉取 Playwright 基础镜像和 `uv` 镜像,国内网络下通常更慢:
```powershell
mkdir pulseguard-worker -Force; cd pulseguard-worker
Invoke-WebRequest -UseBasicParsing "https://raw.githubusercontent.com/liyanqing90/PulseGuard/codex/github-publish/docker-compose.worker.yml" -OutFile docker-compose.worker.yml
Invoke-WebRequest -UseBasicParsing "https://raw.githubusercontent.com/liyanqing90/PulseGuard/codex/github-publish/docker-compose.worker.build.yml" -OutFile docker-compose.worker.build.yml
$env:PULSEGUARD_WORKER_NAME = $env:COMPUTERNAME
$env:PULSEGUARD_WORKER_REGION = "default"
$env:PULSEGUARD_WORKER_BUILD_CONTEXT = "https://github.com/liyanqing90/PulseGuard.git#codex/github-publish"
$env:COMPOSE_PROJECT_NAME = "pulseguard-worker"
docker compose -f docker-compose.worker.yml -f docker-compose.worker.build.yml up --build -d
docker update --restart unless-stopped pulseguard-worker
docker logs --tail 80 pulseguard-worker
```
源码构建时如需使用内网或国内镜像仓库,可以在构建前覆盖基础镜像:
```powershell
$env:PULSEGUARD_UV_IMAGE = "registry.example.com/astral-sh/uv:0.9.30"
$env:PULSEGUARD_PLAYWRIGHT_IMAGE = "registry.example.com/playwright/python:v1.49.1-noble"
```
Token 存储与刷新:
- Docker 子节点默认把 token 存到容器内 `/app/data/worker-token`,`docker-compose.worker.yml` 已经把 `/app/data` 挂到 `pulseguard-worker-data` 卷,容器重建后 token 仍会保留。
- 查看当前 token:
```sh
docker compose -f docker-compose.worker.yml exec pulseguard-worker python -m app.worker --show-token
```
- 刷新 token 并重启 worker:
```sh
docker compose -f docker-compose.worker.yml exec pulseguard-worker python -m app.worker --rotate-token
docker compose -f docker-compose.worker.yml restart pulseguard-worker
```
- 如果 worker 容器当前没有运行,也可以直接用同一个数据卷刷新:
```sh
docker compose -f docker-compose.worker.yml run --rm pulseguard-worker python -m app.worker --rotate-token
```
- 源码方式刷新 token:
```powershell
uv run python -m backend.app.worker --rotate-token --token-file data/worker-token
```
刷新 token 后,必须回到主节点“系统设置 > 执行配置”,对该子节点执行“更新认证”,填入新 token,然后再点“测试连接”确认可用。
网络要求:
- 主节点必须能访问子节点的 `/api/worker/health` 和 `/api/worker/run`。
- 子节点接口使用 `Authorization: Bearer ` 认证。
- 子节点不需要配置主节点地址,也不会主动访问主节点;关联动作由主节点页面手动添加节点完成。
- 远程截图、Trace 和 Response Body 通过 JSON base64 回传主节点,单个文件超过大小上限会记录日志但不会伪造成功。
- 手动停用的节点不会触发不可用告警;启用节点健康检查失败或派发失败时,同一节点只告警一次,恢复可用后重置。
常见排障:
- 主节点“测试连接”失败:检查子节点地址是否从主节点可达,端口是否放行,worker 是否用 `0.0.0.0` 或正确网卡监听。
- 节点不可用:检查主节点保存的地址和 token 是否与子节点终端输出一致;token 更新后需要在平台“更新认证”里同步。
- 任务记录显示 Runner 异常:这类记录的 `failure_kind=runner`,不会按目标失败累计;优先查看节点可用状态和子节点日志。
## 验证命令
后端:
```powershell
uv run python -m unittest discover -s backend/tests -p 'test_*.py' -v
```
前端:
```powershell
cd frontend
npm run build
```
Docker:
```powershell
uv lock --check
.\scripts\deploy.ps1
```
## 脚本任务入口
高级脚本使用固定入口:
```python
async def check(ctx):
response = await ctx.request()
ctx.assert_status(response, 200)
```
UI 任务可以先用 `setup_script` 准备页面前提:
```python
async def setup(ctx):
page = await ctx.new_page()
await page.goto(ctx.entry_url)
return page
```
结构化 UI/API 断言存在时,不强制编写高级脚本。复杂登录、多窗口或业务分支仍可使用脚本模式。
## 数据与安全边界
- 默认使用 SQLite,数据库文件位于 `data/`。
- SQLite 支持在线备份和恢复,备份位于 `data/backups/`。
- 截图、Trace、Response Body 和归档摘要位于 `reports/`。
- 环境变量、Webhook、钉钉密钥、只读令牌、常见认证 Header 和 Cookie 会在公开设置、运行记录和只读出口中脱敏。
- 用户自定义 Python 探活脚本是可信本地工具能力,不是安全沙箱。
- 录制器不是当前主线;多步骤探活优先使用模板、前置脚本和结构化规则。
## 常用接口
- `GET /api/health`:健康检查
- `GET /api/metrics.json`:JSON 指标
- `GET /api/metrics`:Prometheus 指标
- `GET /api/read-only/snapshot`:只读快照,需要配置只读令牌
- `GET /api/runners` / `POST /api/runners`:执行节点列表和创建
- `POST /api/runners/{runner_id}/update` / `GET /api/runners/{runner_id}/update-status`:主节点向子节点推送受控镜像更新和查询更新状态
- `POST /api/runners/heartbeat`:旧版 Runner 主动心跳兼容接口,新子节点默认不需要配置
- `GET /api/worker/health` / `POST /api/worker/run`:子节点健康检查和执行入口
- `POST /api/worker/browser-types/install`:主节点请求子节点安装已启用的 Playwright browser type
- `POST /api/worker/update` / `GET /api/worker/update-status`:子节点受控更新入口,需要启用 updater profile
- `GET /api/runs?runner_id=...`:按执行节点筛选运行记录
- `GET /api/runs?run_group_id=...`:按一次多节点触发分组查看所有节点运行结果
- `GET /api/runs-page?run_group_id=...`:分页查看同组运行结果
- `GET /api/runs/{id}`:查看基于执行快照的运行详情;UI 运行只附带当次快照中的基础请求信息(URL、页面模式、超时),API 运行保留 request/response snapshots,不再重新加载当前任务定义
- `POST /api/heartbeats/{key}`:被动心跳上报
## 目录结构
```text
backend/ FastAPI 后端、存储、运行器、告警、测试
frontend/ React 前端、页面、业务组件、设计样式
data/ SQLite 数据目录
reports/ 截图、Trace、Response Body 和归档摘要
docs/ 路线图和设计/功能文档
Dockerfile 主节点生产镜像构建
Dockerfile.worker 子节点独立 worker 镜像构建
Dockerfile.worker-updater 子节点 updater 镜像构建
docker-compose.yml 主节点单实例部署
docker-compose.worker.yml 子节点 worker 部署
pyproject.toml 后端依赖定义
uv.lock 后端依赖锁定
```
## 当前发展方向
近期重点是把 PulseGuard 做成稳定的内网探活工作台:
- 优先强化结构化规则、扫描候选、失败摘要和配置迁移。
- 保持 SQLite 单实例模型,除非部署形态升级到多实例、多用户或高容量历史分析。
- 冻结 AI 规则生成、Playwright 用例导入、录制器和测试报告矩阵;持续打磨远程节点调度、证据回传和可用性告警。
- 持续强化观测可信度、异常收敛、告警可靠性、证据保留和单实例长期运行能力。
## 品牌资产
PulseGuard 的基础品牌资产位于 `assets/brand/`:
- `pulseguard-mark.svg`:浅底项目图标,适合 favicon、应用侧栏和小尺寸场景。
- `pulseguard-brand-card.svg`:README 和项目介绍使用的横版品牌展示图。
- `pulseguard-brand-card.en.svg`:英文 README 和英文项目介绍使用的横版品牌展示图。
- `pulseguard-logo-concept.png`:使用 imagegen 生成的浅底概念参考,正式主标识以 SVG 文件为准。
品牌图形使用项目设计系统里的浅色面板、控制蓝和状态绿,不使用深色 icon 背景、渐变或玻璃拟态。
## 开源协议
PulseGuard 使用 [Apache License 2.0](./LICENSE) 开源。你可以商用、修改和再分发,但必须按协议要求保留版权、许可证和项目署名信息。
再分发或基于本项目修改发布时,请保留:
- [LICENSE](./LICENSE)
- [NOTICE](./NOTICE)
- 项目名称 `PulseGuard`
- 原始仓库链接 `https://github.com/liyanqing90/PulseGuard`