前端线上监控体系设计

1,902 阅读4分钟

为什么

线上监控可以让我们方便的了解到业务产品的真实指标,如访问量、用户交互数据、页面错误、性能等关键信息。对于应用的体验优化和用户精细化运营至关重要。

线上监控是个比较复杂的体系,包括数据采集、处理计算、可视化等方面。这里篇幅和知识所限,只说端上的数据采集方面。

做什么

我们已经了解到监控的所需要的数据指标,基于此我们要采集哪些类型的数据呢?

具体如下:

  • 应用加载、卸载,这是访问量
  • 路由切换,对于单页面很重要
  • 性能,包括加载时,运行时
  • 错误,接口错误,JS 错误
  • 用户交互数据,点击、眼球曝光埋点

不做什么

我们整个线上监控体系设计的目标是稳定(不会影响正常业务,埋点不会轻易失效),高效(不会对应用产生性能负担),无侵入性(不会限制业务)。基于此我们放弃以下方案。

不做无埋点/可视化埋点

无埋点和可视化埋点的原理都是利用 DOM 属性或 css 选择器将埋点和元素一一对应。而页面结构变动反过来会影响埋点的定位。这也是它们不稳定的根本原因。抛弃这类方案的原因在于:它提供的收益(埋点开发效率)和成本(埋点失效后的排查、反馈、修复)不成正比。

数据模型

我们现在已经知道了线上监控所关心的具体指标和数据类型,那么具体到某一条数据,我们关系哪些参数、用一个什么样的数据模型来指导我们的采集和分析呢?

总的来看,我们关注这些数据:

  • 用户是谁 用户的设备ID,账号
  • 用户的设备信息,什么系统,什么浏览器,4G 还是 WIFI
  • 时间信息,错误,用户交互产生的时间
  • 用户产生了什么行为,点击,眼球曝光,页面切换
  • 其他上下文信息,IP,业务自定义数据

采集原理

应用加载卸载

当然是监听 loadbeforeunload 事件

路由切换

当然可以使用 hashchange 、hack history API,但这些很难获取到动态路由的信息。比如如果一个路由的 path 为 blog/:id。就很难将 blog/ablog/b 做数据聚合。这方面可以提供一个 sendPageView 方法给到业务,业务自己在路由钩子内调用该方法即可。

性能数据

使用 performance API,具体不在赘述。

错误信息

可以使用 window.onerror 来监听一部分错误,但这个方法兼听不到 promise 错误和 script error 。一些前端框架的错误,如 react 的 componentDidCatch 也需要做特殊定制。

用户交互数据

用户交互数据也就是通常所说的埋点,实现起来其实非常简单。

比如我们通过声明式埋点来上报数据,埋点标识为属性中带 data-track-id 的元素。

document.addEventListener('click', (e) => {
    if (e.path.some(el => el.matches('[data-track-id]'))) {
    // 上报数据
    }
}, true)

数据上报

之前也说到,监控方案的目标是稳定和高效。为了不影响业务应用的性能,我们会把采集的关键逻辑使用 window.requestIdleCallback 包裹起来。

为了在浏览器关闭时也能上报数据,我们会使用 Navigator.sendBeacon 来上报数据,对于不支持这个 API 的浏览器,我们使用构造 image 请求来做 fallback 和跨域。

为了减少流量和服务器压力,在采集端也会做缓存,请求协议上也会做一些优化,这里不再赘述。

总结

这里简单介绍了一些前端监控体系的方向和经验之谈。没有涉及大数据处理,也不包括数据的聚合展示,数据采集只是这个体系中很小的一环。而线上监控其实也只是整个前端工程体系中的一小部分。作为一个前端工程师,如果不懂运维,不懂后端,那么能在整个前端工程体系中发挥的作用就很有限。