最近和Youwei 兰兰一起写开源项目 bugWatch 由于精力比较少,没有贡献代码,但是碎片时间还是做了一些功课,把做的功课分享给大家。

1. 为什么要做前端异常监控

在 Web 应用异常复杂的今天,一个页面不单单只包含文字、图片和超链接,还可能包含复杂表单、大量动画、海量交互。很多 Web 应用完全单页化,操作体验、复杂程度堪比原生应用。这对开发者们来说,是巨大的挑战,纵然有 unit test、code review、各种黑白盒测试保价护航,也无法保证代码上线后,面对成千上万用户、在各类浏览器下、遇到未知数据时不出问题。所以,对一个拥有大量用户的互联网产品而言,一个可靠的前端异常数据采集、上报、处理、监控、报警平台是非常有必要的。

2. 采集哪些异常

  1. HTML 标签异常,CSS 展现异常,样式、图片、脚本文件的请求异常、脚本执行异常
  2. 用户自身的网络环境,如网速很慢、被运营商强行注入标签或脚本
  3. 交互逻辑错误、获取填充数据提交导致的脚本错误

3. 采集方法

3.1 主动上报API

设计诸如此类的错误我们的设计原则:1 非阻塞 2 非入侵。秉持统计代码和业务代码分离的原则,但是留出业务代码中主动上报的接口。
思路:

1
2
3
4
5
6
7
8
9
10
11
12
// test.js
// 业务代码
function calc(){
// code...
return val;
}
if(calc() !== "someVal"){
Reporter.send({
position: "test.js::<Function>calc"
msg: "calc error"
});
}

3.2 进化版本

try..catch 判断一个代码段中存在的错误

1
2
3
4
5
6
try {
init();
// 业务代码段入口
} catch(e){
Reporter.send(format(e));
}

也属于主动上报范畴 以init 为程序的入口,代码中所有同步执行出现的错误都会被捕获,这种方式也可以很好的避免程序刚跑起来就挂。
主动上报,说个有意思的案例:哔哩哔哩的播放器,用户点击后主动收集客户端的所有信息以及cookie,ls等信息。

3.3 捕获全局错误

我们可以通过 window.onerror 来捕获页面上的各种脚本执行异常,它能帮助我们获取有用的信息。这个方法存在兼容性问题,在不同的浏览器上提供的数据不完全一致,部分过时的浏览器只能提供部分数据。它的标准函数签名是这样的:

1
window.onerror = function (message, url, lineNo, columnNo, error)

  • message {String} 错误信息。直观的错误描述信息,不过有时候你确实无法从这里面看出端倪,特别是压缩后脚本的报错信息,可能让你更加疑惑。
  • url {String} 发生错误对应的脚本路径。
  • lineNo {Number} 错误发生的行号。
  • columnNo {Number} 错误发生的列号。
  • error {Object} 具体的 error 对象,继承自 window.Error 的某一类,部分属性和前面几项有重叠,但是包含更加详细的错误调用堆栈信息,这对于定位错误非常有帮助。

3.4 Ajax 上下文

Ajax 的请求上下文对于排错会有一定帮助,可以使用XMLHttpRequest.prototype 上的各类方法,也可以获取返回数据的 statusCode、statusText,甚至是 responseText(不建议获取这种可能会是大容量数据的信息

3.5 三方库依赖

现在的系统,几乎都是构建在一些流行的库之上的。jQuery、angular、react.js、vue.js、backbone、underscore、knockout,这些常用的类库,发布时大都会带版本信息,如

1
2
3
4
5
6
7
8
`jQuery`, `jQuery.fn.jquery`,
`jQuery ui`, `jQuery.ui.version`,
`lodash(underscore)`,`_.VERSION`,
`Backbone`, `Backbone.VERSION`,
`knockout`, `ko.version`,
`Angular`, `angular.version.full`,
`React`, `React.version`,
`Vue`, `Vue.version`,

3.6 浏览器数据

这个就比较简单了,收集userAgent

4. 采集上报数据接口设计


以上为标准格式设计,在ext中可以个性化的设置一些错误类型

  • 针对业务设计 token userid
  • 辅助调试类

5. 采集结果的输出

篇幅有限暂时不展开
前端同学可以用egg.js + vue + g2.js(D3,js) 配合elasticsearch的API来做接口,来输出bugwatch 管理后台
管理后台的思路:

  1. 用户管理。
  2. 权限管理。
  3. 错误聚合以及展示
  4. 错误详情展示

如果敏感模块报错,或者报错密度比较集中(可以设计阀值),开启短信,邮件推送,聊天机器人推送等等。(本人非常讨厌 2333333)

6.总结。

错误难免,监控要到位

参考开源库:

  • flextracker
  • badjs
  • JSTracker
  • saijs
  • ravenjs