从架构设计上来说,我是参考的是类似 Sentry 的架构。主要核心是”分层接耦、按需加载”。

总的来说,我将 sdk 拆分为两大部分:

首先是核心包。它的整体逻辑是环境无关的。主要提供的是统一的初始化流程,进行插件注册,并对外暴露标准化的数据上报接口以及插件接口。

其次是适配包:它们基于自己环境,去实现对应的接口下各自的逻辑,性能采集在 brower 环境下依靠 performance API 相关接口,而在 node 环境下,则需要通过 node:perf_hooks 监控代码性能。

这样做的好处就是“关注点分离”和”产物轻量化”。用户在浏览器环境时,只需要引入 brower 包,不会把 Node js 的代码打包进去。

在我设计的 brower 包中,我主要干了两件事

第一件事是:基于 core 包中的标准化上报接口,基于 fetch 实现一个上报模块。在初始化时,调用 core 包的初始化流程。这样,core 包只需要负责接收数据,而 brower 包决定怎么发,发到哪。两者职责明确,互不影响。

第二件事是:集成核心监控模块。对于浏览器监控而言,性能监控和异常监控是必不可少的。它们应该作为内置模块直接初始化,而不是可选插件。这样做可以保证 sdk 开箱即用,记录信息。同时,每个模块(异常模块、性能模块)只做自己的事,一边后续的维护的迭代。

在埋点系统中,往往需要统计记录埋点触发的用户基本信息。而这个无法实现进 core 包或者核心包中,那么就可以借助插件机制,在浏览器端实现用户信息的获取,并传入初始化插件列表中。

如果想要支持新的平台,只要再实现一个适配包即可。不需要改动原有的适配包,自然引入包的客户端也不会收到影响