作者:彭莉,火山引擎 APM 研发工程师,2020年加入字节,负责前端监控 SDK 的开发维护、平台数据消费的探索和落地。
摘要
-
字节内部监控环境多样( Web 应用、小程序、Electron 应用、跨端应用等等), SDK 如何保证底层逻辑的复用、上层逻辑的解耦。
-
在业务庞杂、监控需求多样的背景下, SDK 如何做到足够灵活,如何实现插件化,并且支持业务自行扩展的。
-
大型 C 端业务非常注重业务自身的正确性和性能,监控 SDK 如何保证原有业务的正确性;如何保持 SDK 自身的性能,减少对业务的影响。
-
接入业务众多,上报量级近千万 QPS ,在日常需求迭代中, SDK 是如何确保自身稳定性的。
逻辑解耦
前端的领域广阔,所以作为前端监控,也不只局限在浏览器环境,需要同时解决小程序、 Electron 、 Nodejs 等等其他环境的监控需求。不同环境之间差异巨大,从提供的配置项,到监控的功能、上报的方式都会不一样。
一个 SDK 不可能既支持多环境,又满足体积小、功能全面的要求,这本身互相矛盾。只要兼容其他环境,打包进来的代码会导致体积变大,因此设计之初的目标就是同一套设计组装成不同的 SDK 。此设计的第一要务是要逻辑解耦。虽然多环境下差异很大,但要做的事情是一样的,比如配置、采集数据、组装数据、上报数据。
我们设计了五个角色,每个角色只需要实现约定的接口即可。这样就保证了不同的环境下,各个角色合作的方式是相同的,在实现了一套内核模版后,不同的监控 SDK 就可以快速搭建出来。
Monitor
收集器 ,主动或被动地采集特定环境下的原始数据,组装为平台无关事件。
Monitor 有若干个,每一个 Monitor 对应一个功能,比如关于 JS 错误的监控是一个 Monitor ,关于请求的监控又是另一个 Monitor 。
Builder
组装器,负责将收集器上报的平台无关事件转换为特定平台的上报格式。
主要负责包装特定环境下的上下文信息。在浏览器环境下,上下文信息包括页面地址、网络状态、当前时间等等,再结合收到的 Monitor 的数据,完成上报格式的组装。
Sender
发送器,负责发送逻辑,比如批量,重试等功能。
监控 SDK 的 Sender 都是 BatchSender ,它会负责维护一个缓存队列,按照一定的队列长度或者缓存时间间隔来聚合上报数据,会开放一些方法自定义缓存队列长度和缓存间隔时间,也支持立即上报和清空队列等操作。
特定环境下的 Sender 也需要负责处理一些边缘 case ,比如浏览器环境下的 Sender 在页面关闭时,需要使用 sendBeacon 立即上报所有队列数据,以免漏报。
在实际实践中,我们对 Sender 进行了进一步抽象, Sender 不会内置发送的能力,关于如何发送数据,不同环境依赖的 API 不同,因此会由 Client 在创建 Sender 时将具体的发送能力传入 Sender 中。
ConfigManager
配置管理器,负责配置逻辑,比如