健康检测与 Provider 监控体系
健康检测与 Provider 监控体系
学习目标
- 理解 CC Switch 的三种检测方式:端点测速、流式检测、用量同步
- 掌握自定义端点管理和健康数据持久化策略
- 了解日志压缩与定期维护机制
前置知识
- API Provider 健康监控:健康检测的通用原理与指标体系
下文聚焦 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 提供用量追踪功能,数据来源有三:
- 代理层记录:代理在转发请求时记录每个 Provider 的请求数、Token 数、成本
- Claude 会话日志:解析 Claude Code 的会话日志文件(
~/.claude/目录),提取 Token 用量 - 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