跳转到内容

健康检测与 Provider 监控体系

健康检测与 Provider 监控体系

学习目标

  • 理解 CC Switch 的三种检测方式:端点测速、流式检测、用量同步
  • 掌握自定义端点管理和健康数据持久化策略
  • 了解日志压缩与定期维护机制

前置知识

下文聚焦 CC Switch 的具体实现。


项目实践

端点测速(Speedtest)

CC Switch 提供端点延迟测量功能,实现在 src-tauri/src/services/speedtest.rs

test_api_endpoints(provider_config) {
for each endpoint in (built-in + custom_endpoints):
start_time = now()
response = GET(endpoint.url + "/v1/models")
latency = now() - start_time
record(endpoint.id, latency, response.status_code)
}

测速目标:默认使用 /v1/models 端点,这是最轻量且最广泛支持的 API。对于不支持该端点的供应商,用户可以添加自定义检测端点。

自定义端点管理

  • 用户可以添加任意数量的自定义检测端点
  • 每个端点有独立的名称、URL、最后检测时间、延迟值
  • 支持一键删除不需要的端点

流式健康检查(Stream Check)

端点测速只检测”能不能连上”,流式检测验证”能不能正常生成”。

实现在 src-tauri/src/proxy/ 的流式检测模块中:

stream_check_provider(provider_id) {
1. 构造极小请求: {messages: ["Say OK"], max_tokens: 1, stream: true}
2. 通过代理发送请求(经过正常的整流流程)
3. 检测指标:
- TTFT (Time to First Token): 首 chunk 到达时间
- 流完整性: 是否正常收到 [DONE] / message_stop
- 错误类型: 5xx / 超时 / 认证失败 / 连接拒绝
4. 记录到 stream_check_logs 表
}

流式检测配置save_stream_check_config):

  • 检测超时时间
  • 检测间隔
  • 使用的测试模型
  • 自动检测开关

启动时同步:应用启动时自动执行一次流式检测(stream_check_provider 在 startup 流程中被调用),确保用户打开应用就能看到最新的健康状态。

用量统计同步

CC Switch 提供用量追踪功能,数据来源有三:

  1. 代理层记录:代理在转发请求时记录每个 Provider 的请求数、Token 数、成本
  2. Claude 会话日志:解析 Claude Code 的会话日志文件(~/.claude/ 目录),提取 Token 用量
  3. Codex/Gemini 日志:类似地解析 Codex 和 Gemini 的本地日志

定期同步(后台任务):

每 60 秒执行:
sync_claude_session_logs() // 从 Claude 会话日志同步
sync_codex_usage() // 从 Codex 日志同步
sync_gemini_usage() // 从 Gemini 日志同步

数据压缩

  • 原始请求日志保留 7 天
  • 7 天后 ROLLUP 为日级统计摘要(每日总请求数、总 Token、总成本)
  • 启动时自动执行 PRUNE(清理 7 天前的原始日志)+ 增量 vacuum

健康数据的数据库存储

stream_check_logs 表 {
id: INTEGER PRIMARY KEY,
provider_id: TEXT,
check_time: DATETIME,
latency_ms: INTEGER,
status_code: INTEGER,
is_success: BOOLEAN,
error_message: TEXT,
}
provider_health 衍生数据 {
通过 SQL 聚合查询从 stream_check_logs 计算:
- 成功率 = 成功请求数 / 总请求数
- P50/P95/P99 延迟
- 最后成功时间
}

维护定时器:应用启动时注册一个 24 小时间隔的定时器(periodic_maintenance_timer),定期执行:

  • periodic_backup_if_needed() — 快照备份
  • rollup_and_prune(30) — 日志聚合与清理
  • incremental_vacuum — 回收数据库空间

问题与规避

陷阱 1:流式检测产生额外费用

问题:流式检测发送实际的生成请求,每个 Provider 每次检测都会产生 Token 费用。

CC Switch 的解决方案

  • 使用 max_tokens=1 最小化 Token 消耗
  • 检测间隔默认较长(用户可配置)
  • 用量统计中记录检测产生的费用,用户可见

陷阱 2:启动时同步拖慢应用启动

问题:如果每次启动都等待流式检测完成再显示 UI,应用启动可能慢 10-30 秒。

CC Switch 的解决方案

  • 流式检测在后台异步执行(tauri::async_runtime::spawn
  • UI 先显示上次的缓存健康状态
  • 检测完成后通过 Tauri 事件推送更新到前端

陷阱 3:日志表膨胀

问题:如果不定期清理,stream_check_logs 表可能积累数十万行数据。

CC Switch 的解决方案

  • 启动时自动执行 cleanup_old_stream_check_logs(7) — 删除 7 天前的原始日志
  • rollup_and_prune(30) — 将原始日志聚合为日级摘要后再删除原始行
  • PRAGMA incremental_vacuum — 回收被删除行的空间

设计取舍

代理层记录 vs 外部日志解析

方案优势劣势
代理层记录精确、完整、实时只在代理运行时有效
外部日志解析不依赖代理、覆盖全量历史依赖外部日志格式、可能有延迟

CC Switch 两者都用:代理运行时精确记录,后台定期解析外部日志补充非代理时段的用量数据。这确保了无论用户是否使用代理模式,用量统计都完整。


参考来源

  • CC Switch 源码: src-tauri/src/services/speedtest.rs
  • CC Switch 源码: src-tauri/src/proxy/stream_check.rs
  • CC Switch 源码: src-tauri/src/services/session_usage*.rs