我把 SDK 按职责拆成错误采集、性能采集、行为追踪和统一上报模块,由入口负责配置和生命周期管理。

模块之间通过一个共享事件总线通信,采集模块发布事件,上报模块订阅事件后完成数据整理、入队和发送,因此采集逻辑不需要直接依赖上报实现。

比如发生错误时,错误模块发布 error:captured,上报模块收到后通过总线获取最近的行为面包屑,再组装错误数据;会话录制模块也能订阅同一事件,截取相关录制片段。

这样新增处理能力时,可以增加订阅者,减少对已有模块的修改。

体积方面,我对 rrweb、Source Map 等依赖采用按需加载,并通过功能配置控制采集开销。具体 gzip 体积会以构建产物测量为准。


我使用浏览器原生的错误通知机制实现多维度采集:

  • 通过 window.onerror 捕获 JavaScript 运行时错误,记录消息、脚本地址、行列号和堆栈;
  • 通过 unhandledrejection 捕获未处理的 Promise 拒绝;
  • 通过捕获阶段监听 error 事件,根据目标元素识别脚本、样式和图片等资源加载失败。

不同类型的错误统一整理后,通过事件总线交给上报模块。

上报时关联最近的点击、路由和网络请求面包屑,帮助还原错误发生前的操作过程。

同时提供可选的 Source Map 解析模块,将压缩后的堆栈位置映射回源码,并缓存解析结果以减少重复开销。

当前解析能力已实现,自动关联到上报数据的流程还需要完善。


页面性能方面,我接入 web-vitals,通过统一回调收集 FCP、LCP、CLS 等指标,整理后通过事件总线交给上报模块。

网络请求方面,我保存并包装原生 XHR 和 Fetch。

  • XHR 在 open 时记录请求信息,在 send 中监听完成、失败和中止事件;
  • Fetch 则在调用前记录时间,在 Promise 成功或失败后记录状态和耗时,同时保留响应返回和错误抛出的行为。

这些请求记录会进入行为面包屑,并与页面性能指标一起通过统一队列批量上报,帮助排查慢请求、异常响应和页面体验问题。

这里的“统一回调”指的是 handleWebVital(metric):不同指标产生结果后,都交给这个函数整理和发布。它做两件事:

  1. 整理数据:从 metric 中提取指标名称、数值、变化量等信息,再补上类型和采集时间。
  2. 发布事件:通过事件总线把数据交给上报模块,后续完成入队和批量发送。

我在统一上报模块里用内存数组暂存错误、性能和行为数据,采用数量阈值与定时触发相结合的批量上报策略。

达到批量大小就立即发送,数量不足时由定时器触发,同时设置最大队列阈值,减少请求次数并控制数据积压。

发送时支持 Fetch、Beacon 和 Image 三种通道。

Beacon 不可用或返回 false 时降级到 Fetch,Fetch 不可用时再降级到 Image;Fetch 的网络失败则进入重试流程。

这样能够适配不同浏览器和发送场景,提高上报的可靠性。


可视化方面,我用 Vue 搭建监控页面,将接口返回的聚合数据转换成 ECharts 配置,展示错误趋势和性能指标变化,并提供页面分布、错误详情等视图。

图表的初始化、数据更新、尺寸调整和销毁统一封装在 useChart 中,减少重复代码。


会话回放方面,我接入 rrweb,通过会话采样控制录制比例,使用有上限的事件缓冲保存近期记录,并配置输入遮盖和区域屏蔽,减少采集开销和敏感信息暴露。

发生错误时记录时间和事件位置,继续录制一段时间后截取相关片段上报,平台再使用 Replayer 重建操作过程,辅助还原错误现场。