Skip to content

fix(web-record): 导出失败加退避与熔断,别把控制台和主线程刷爆 - #7

Merged
DZQOX merged 1 commit into
mainfrom
fix/web-record-export-backoff-circuit-breaker
Aug 25, 2026
Merged

DZQOX merged 1 commit into
mainfrom
fix/web-record-export-backoff-circuit-breaker

Conversation

@DZQOX

@DZQOX DZQOX commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

现象

甲方内网现场(2026-08-25):浏览器控制台 868 条 error,其中 429 条是同一句 [@softprobe/web-record] Failed to flush recording;页面刷新要 1.8 分钟才 finish,请求大量 (canceled) 0 B。

原因

collector 不可达时,原实现每 5 秒把同一批事件原样重发,永不放弃:

  • 控制台被 429 条同样的 error 淹掉,真正有用的报错看不见;
  • 每一轮都白做一次 JSON.stringify + 压缩(最多 500 条 rrweb 事件),主线程被反复占用;
  • 宿主 SPA 每次路由变化都调 record(),失败态下等于反复重新武装采集。

改了什么

改动 说明
连败指数退避(5s→10s→20s…封顶 5 分钟) 挡在定时器层。flush() 本身语义不变——直接调仍然立即尝试,drainFlush / stop() 行为没动
连败 5 次熔断 停采集、清缓冲,并打一条写明端点和处置办法的日志(封闭环境应去设 SOFTPROBE_BASE_URL)
只在连败第一条打日志 日志本身就是故障放大器
熔断后 record() 拒绝重新武装 否则 SPA 每导航一次就白起一轮采集

刻意没改:单次失败仍然保留缓冲(可能只是网络抖动)。

测试

新增 4 条。先红后绿都验过:

旧实现 + 新测试 →  4 failed / 8 passed
新实现 + 新测试 → 12 passed

既有 8 条(含 keeps buffer when flush fails)自始至终绿 —— 原语义没被动。

🤖 Generated with Claude Code

现场(2026-08-25,甲方内网):到不了配置的 collector,原实现每 5 秒把同一批
事件原样重发,失败 429 次没停过。后果不只是日志难看:

- 控制台 429 条同样的 error,把真正有用的报错淹了;
- 每一轮都白做一次 JSON.stringify + 压缩(最多 500 条 rrweb 事件),
  主线程被反复占用,页面肉眼可见地卡;
- 宿主 SPA 每次路由变化都会调 record(),失败态下等于反复重新武装。

四条对策:

1. 连败指数退避(5s→10s→20s…封顶 5 分钟),挡在定时器层。flush() 本身
   语义不变——直接调仍然立即尝试,drainFlush/stop 的行为没动。
2. 连败到 5 次熔断:停采集、清缓冲,并打一条写明端点和处置办法的日志
   (封闭环境该去设 SOFTPROBE_BASE_URL,而不是让它一直重试)。
3. 只在连败的第一条打日志,后续静默——日志本身就是故障放大器。
4. 熔断后 record() 拒绝重新武装。

单次失败仍然保留缓冲(可能只是网络抖动),这一点刻意不改。

测试:新增 4 条,在旧实现上全红(4 failed / 8 passed),新实现 12 全绿;
既有 8 条(含 keeps buffer when flush fails)自始至终绿,原语义没被动。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@DZQOX
DZQOX merged commit c5a64b2 into main Aug 25, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant