阅读 1268

第五期 | 前端监控的设计和实现

前言

前端监控对于很多前端小伙伴来说就是一块还未开发的地图板块,下面我们一起来看看如何打造这块版图,开辟更宽广视野。

文中的调研和设计思想来自前端早早聊大会的分享讲师,我是站在这些巨人的肩膀上做了一些整合,并且加了一些自己的想法。

若本文对你有所助益,手留一赞,若有不同看法,评论区我等你(^ω^)。

场景:为什么做监控

从事前端多年,经常碰到这类场景:

  • 前端数据监控到底是在监控什么,有什么价值?
  • 需求方不断堆页面,到底页面的使用率高不高?
  • 端/平台多了,PC/H5/小程序/APP 的线上产品异常到底如何?
  • 从多端的 SDK 封装到数据加工与告警如何建设?
  • 数据监控只能由后台来做么,前端也可以做到吗?
  • 监控系统 SDK 设计,如何做到非侵入式的功能嵌入?
  • 那么多业务场景,具体怎么针对场景设计分析的规则?
  • 对于比较大的日志量,前端和后端应该怎么配合呢?
  • 用户的报错在本地很难还原场景,有什么好的定位办法?
  • 工程多了,各 BU(Business Unit,业务单元)各自为政,如何很好整合与打通?
  • ...

效率质量是所有技术团队的立命之本,关于效率是最能具象可见的部分,但质量测往往把控不足,特别是上线后的多端全链路用户行为数据、线上页面异常数据,可度量的产品使用情况等。如何在版本发布后半小时内快速响应、如何保证线上项目持续友好与安全、如何使线上问题快速得到解决等等,这就需要一个完善、健壮和敏捷的平台来监控和调度了。

商业产品 vs 自研产品

为了解决上述问题,摆在面前的有 2 个方案:是选择市场上的相对成熟的商业产品还是组织员量身打造一款产品呢?在选择或决定之前,我们需要做 2 件事:

  • 调研商业产品,了解其特性;
  • 整理我们需要的的监控平台真正要关心的问题;

商业产品

商品统计结果可能有误差,仅供参考。

1.Fundebug

  • ⽀持的平台有 H5,Node.js,Java,RN... 不支持 Weex;
  • ⽀持 SourceMap,提高错误排查效率;
  • 支持用户行为回溯,同时支持强⼤的场景重现功能;
  • 缺乏统计信息;
  • 不支持拓展;

2.Sentry

  • 支持的平台有 H5、Node.js,不支持 Weex、⼩程序;
  • 检索条件丰富度高,但是检索后错误数量与检索条件⽆关,错误详情⻚不可检索;
  • 稳定性差,错误大量爆发的时候 100% 挂;
  • ⽆法扩展;
  • ⽀持语言多;

3.FrontJS

  • 仅支持 Web 端和小程序;
  • 每分钟监控事件数受限(⾼级版) ;
  • 告警通知受限,不支持拓展;
  • 筛选问题历史时间选择受限;

4.Bugly

  • 仅支持 Android 平台、iOS 平台、Cocos2D、Unity3D;
  • 支持 AourceMap;
  • 不支持拓展;

真正要关心的

通过各家商品的了解,业界方案各有利弊,我们真正需要关心的问题有稳定性、可扩展性、智能聚合、可回溯性、端侧支持和 SourceMap,还有比较现实的一个问题价格成本

方案对比

Fundebug Sentry FrontJS Bugly 自研产品
价格 30 万/年起 80 美元/月 专业版 2999/月 免费
可扩展性 稳定 不稳定 稳定 稳定
可扩展性 不可扩展 不可扩展 不可扩展 不可扩展
智能聚合 支持 支持 支持 支持
可回溯性 30 天 90 天 近 15 天 50 天
端侧支持 不支持客户端 不支持 Weex 不支持客户端 不支持前端
SourceMap 支持 支持 支持 支持

业界产品费用:80(工程数) * 12(月)* 299(每月/每工程)= 287040(每年) 自研产品费用:180人日 = 150000(前期稳定版)

所以,如果公司决心做好这件事且一直要做下去,那就考虑自研,开始内部抽人或社会招人吧。

设计思路

  • 应用接入
  • 错误收集和错误上报
  • 数据清洗
  • 数据存储
  • 数据服务
  • 展示调度

应用接入

即各端 SDK 实现错误捕获和上报

错误收集和错误上报

  • 日志接收,大数据日志平台

数据清洗与数据存储

  • 临时存储错误日志,ES(ElasticSearch)文档型数据库(数据符号化任务);
  • 清洗任务、日志分析、聚合等、定时任务;
  • DB(MySql)持久化存储

数据服务

  • Node.js 服务;
  • 提供 Web Server 接口;
  • 推荐 nest.js 或 egg.js,个人喜欢 nest.js,有意向的可联系互相交流 nest.js;

展示交互与调度

  • 数据可视化
  • 监控
  • 通知责任人

落地实践

提醒:这块篇幅会比较长,可以喝杯水、休息下,再一鼓作气看完编排代码。

SKD 设计

1.⾃动上报 一般用在能全局捕获的场景下。非常适合直接从第三方库引⼊后直接调用执行。

import monitor from 'monitor';

monitor();
复制代码

2.手动上报 一般出现在业务的 try/catch 中,method 可以按错误级别分类,比如 errorwarninfo

import monitor from 'monitor';

monitor.error(msg);
复制代码

错误捕获机制

1.运行时错误捕获,监听 window.onerror

当发生 JavaScript 运⾏时错误(包括处理程序中引发的语法错误和异常)时,使⽤接口 ErrorEvent 的 error 事件将在 window 被触发,并被 window.onerror() 调用。

2.监听 unhandledrejection 事件

当 Promise 被 reject 并且没有得到处理的时候,会触发 unhandledrejection 事件。所以可以对此事件进⾏监听,将错误信息捕获上报。

3.跨域脚本错误 劫持原⽣方法,使⽤ try/catch 绕过(浏览器不会对 try-catch 起来的异常进行跨域拦截),将错误抛出

4.其它技术栈 比如 Vue.js 劫持 Vue.config.errorHandler (errorCaptured),当 Vue 的项 ⽬中发生错误时,将错误捕获上报。

比如 React.js 监听 componentDidCatch,当 React 的项目中发生错误时,将错 误捕获上报。

环境收集

  • 业务信息,主动上报、客户端能力、SKD 获取;
  • 设备信息,客户端能力(UserAgent);
  • 网络信息,客户端能力(UserAgent);
  • SKD 信息,SKD 中获取(package.json);

行为收集

1.浏览器行为

发起请求、跳转、前进/后退、关闭和新开窗口等。

1)发送请求行为。监听 XMLHttpRequest 对象的 onreadystatechange 回调函数,在回调函数执行时收集数据。

2)⻚面跳转。监听 window.onpopstate,⻚面跳转的时会触发此方法,将信息收集。

2.用户行为

即事件行为:点击、滚动、聚焦/失焦、长按等。使用 addEventListener 全局监听点击事件,将⽤户行为(clickinput)和 dom 元素名字收集。当错误发生将错误和行行为⼀起上报。

3.控制台打印行为

类似 console.log()等。改写 console 对象的 infowarnerror 方 法,在 console 执行时将信息收集。

数据上报

此时,我们已经得到了错误、环境、⾏为信息,接下来需要将它们上报,就是调接口咯,但是这⾥有个小技巧:使⽤ GET 一个 .gif 对其进行上报

为什么要用 1x1 像素的 .gif?

  • 没有跨域问题;
  • 发 GET 请求之后不需要获取和处理数据,服务器也不需要发送数据;
  • 不会携带当前域名 cookie;
  • 不会阻塞页面加载,影响用户的体验,只需 new Image 对象;
  • 相比于 BMP/PNG 体积最小,可以节约 41%/35% 的⽹络资源;

以上步骤,可总结为:监听/劫持原始⽅法,获取需要上报的数据,在错误发⽣时触发函数,使⽤ .gif 上报。

数据清洗

1.为什么进行数据清洗?

  • 收集到的数据量和体积会非常大;
  • 此时数据是没有分类和聚合的;
  • ⾮法数据没有进⾏过滤;

2.如何清洗?

  • 【ES】(临时存储)
  • 【获取数据 - 数据预处理 - 数据聚合】(使用 Node.js 脚本定时任务)
    • 获取数据。通过 GET 请求从 ES 获取近一分钟的错误信息;设置阈值(削峰机制):每分钟数据获取上限 10000 条,超过就采样入库 同类型错误数量⼤大于 200 条,只统计数量;
    • 数据预处理。String 格式数据需要 JSON.parse();去除原始数据⾥无用信息,减小存储体积。
    • 数据聚合。聚合的目的是使得存储性能变小,查询性能加快。聚合纬度或规则格式可以:

3.清洗任务结果与清洗过程监控

1)结果

2)过程监控

预警通知

1.消息格式约定如下

  • 标题:告警来源 + 错误等级 + 业务
  • 内容:错误描述 + 影响多少用户

2.消息下发形式

  • 普通告警,比如邮箱;
  • 升级告警,比如短信 + 工作群(xxxhook)/钉钉机器人 webhook + 电话

数据存储

数据上传后需要存储,这里涉及到临时存储和持久化存储

1.为什么要分这两种存储呢?

  • ES 临时存储,快速定位问题,数据清洗后,进入持久化存储;
  • DB 持久化存储,需要时间,便于后期图表展示和分析;

2.这两钟存储要选择什么样的工具呢?

总结下,监控平台核心和差异化就在数据存储和数据清洗这块,也是难点之处。任务微小的优化,对整体性能和成本就是巨大的,尤其是业务量很大的情况下,其价值更指数级放大。

数据输出服务

提供 Dataservice 数据输出服务。

可视化展示

将持久化数据来通过可视化展示出来,便于后期数据分析。

  • 监控看板,数据实时大盘
  • 可视化报表平台