前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >前端异常监控实践

前端异常监控实践

作者头像
用户1687375
发布2019-07-31 16:47:30
1.2K0
发布2019-07-31 16:47:30
举报
文章被收录于专栏:较真的前端较真的前端

为什么要做前端异常监控

bug是不可能被全部测试出来的,由于成本和上线档期的考虑,测试无法做到“面面俱到”,即使时间充裕也总会有这样或那样的bug埋藏在某个角落。

此外,一个可靠的前端监控系统还可以化被动为主动,不再被动的等待客服来找,而是在问题出现时开发人员可以第一时间知道并解决。

捕获方式

可以捕获JavaScript错误的基本方法有以下三个:

  • try…catch
  • window.onerror
  • 利用Promise.prototype.catch()

各个方法的优缺点:

评价捕获错误方式的好坏可以从以下几个维度考虑:

  • 错误信息的完整性可读性,包括完整的错误堆栈(Error Stack)
  • 是否可以捕获异步错误
  • 是否可以捕获跨域脚本的错误
  • 对源代码的破坏性

下面来逐个对比上面三种方式。

try..catch优点是可以返回完整的错误堆栈,缺点是无法捕获异步异常,看下面的代码:

代码语言:javascript
复制
// 同步异常的捕获
function foo () {
  doSomething()
}

try {
  foo()
} catch (e) {
  console.log(e)
}
// 会打印出完整的错误堆栈
// ReferenceError: doSomething is not defined
//  at foo (<anonymous>:2:3)
//  at <anonymous>:6:3
代码语言:javascript
复制
// 异步异常的捕获
function onloadHandler () {
  doSomething()
}
try {
  window.onload = onloadHandler
} catch (e) {
  // 获取不到任何信息!
}

除了对于异步异常无法捕获之外,try…catch势必也会修改源代码,如果想通过try…catch捕获到全部异常的话,要在大量的代码中追加try…catch处理。

window.onerror的优点可以捕获同步和异步的异常,但是它受到同源策略的限制,只能捕获当前域名下的错误。

比如下面的情况:

代码语言:javascript
复制
// @file: example1.com/index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <script>
    window.onerror = function (...args) {
      console.log('--------------')
      console.log(args)
      console.log('--------------')
    }
  </script>
  <script src="http://example2.com/main.js"></script>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
    ...
</body>
</html>

exampl2.com/main.js中如果出现异常,window.onerror虽然会被触发,但是回调获取的信息没有任何参考价值,内容如下:

代码语言:javascript
复制
 ["Script error.", "", 0, 0, null]
0: "Script error."
1: ""
2: 0
3: 0
4: null

这是浏览器出于安全考虑,禁止了获取跨域脚本的错误信息。但是可以通过在<script>中设置crossoriginanonymous来解决,同时服务器端也要做出修改,设置responese headers Access-Control-Allow-Origin:*。但是要注意,关于crossorigin也有他的局限性,并不是所有浏览器都完美支持,下面是各浏览器支持的情况:

图片来自《把前端监控做到极致》

利用Promise.prototype.catch()可以捕获Promise实例中发生的异常。

看下面的例子:

代码语言:javascript
复制
function queryData () {
  return myFetch('example.com/user?id=2393')
  .then(response => {
    // response.msg并不存在,所以对其调用toLowerCase()方法会报错
    console.log(response.msg.toLowerCase())
  })
}

//由于queryData()返回的是一个promise实例,所以可以用catch对异常进行捕获
queryData().catch(error => {
  console.log(error)
})

缺点是只能捕获promise内部的错误。

通过上面三种方式的对比,貌似没有哪个可以作为完美的解决方案。

不过我们还可以看看其他解决方案。

其他捕获异常方式

现在市面上已经有很多比较成型的解决方案。

  • 框架提供的处理方式:
  • Vue提供的错误处理回调——Vue.errorHandler(无法捕获异步异常)
  • 微信小程序提供的错误处理——onError(异步、同步都可以捕获)。
  • 第三方错误监控解决方案——sentrybugsnag
  • 第三方的解决方案是前后端整体,只需要几行代码就可以完成所有处理
  • 但是商用是需要花钱的。。。
  • hack手法——利用babel,将源码解析成功AST语法树,然后在所有function追加try…catch,重写js原生方法如setTimeout、forEach等方法。(这样代码体积会膨胀)

小结

根据上面的诸多对比,如果你的web应用是移动端的话,window.onerror是不错的选择。因为移动端的浏览器版本更高,支持性更好。

应用层的使用

如果想做一个前端监控平台的话,你需要完成以下几个目标:

  1. 可靠性:尽可能地捕获到所有异常,包括JS运行错误,网络资源加载失败等等。
  2. 完整性:可以拿到完整的错误信息,以便排查问题。
  3. 易用性:希望错误采集代码可以以SDK的形式进行安装,对应用代码尽量不做改动。
  4. 一致性:希望不论用户的使用什么浏览器,上报的错误信息是统一的。需要排除浏览器内核的不同、系统语言设置的不同等等
  5. 完备性:除了JavaScript错误本身,应该还可以上报其他有用的信息,比如浏览器信息、用户信息、定位或网络连接状态等等。

第5点完备性比较依赖于前端监控平台的“消费端”,即不同的应用场景对于完备性有不同程度上的要求。但是前4点应该所有前端监控平台有着大致相同的需求。

错误上报SDK的实现

篇幅有限,不能面面俱到,只提关键的几点。

前端打包,上报错误的行号是经过编译压缩后的文件行号,所以为了方便分析,一定要在打包时生成sourceMap,方便后续的分析。

错误上报,采用image ping的方式,即将上报服务器地址当做为image url,将要上报的参数编码成url参数加载image url后面。这样做的原因如下:

  • 有跨域需求,image ping可以跨域
  • 只关心上报本身,无需关心是否上报成功

服务端,利用Nginx将上报信息转发到日志系统,不要做任何其他应用来进行“信息转译再存储”的动作,因为错误日志的数据量是庞大的,这样会消耗服务端的性能。

分析端,定期将日志转译、归并再存储到数据库中,然后再做分析处理(离线分析)。因为分析端(或者称“消费端”),是希望可以做到快速响应的,所以离线分析是个不错的方案。

图片来自《把前端监控做到极致

总结

如果你已经部署了一套稳定的前端监控系统之后,你会发现bug的数量是无法想象的。大数据处理是个难点。

今后如果有时间,我会整理一下关于如何处理庞大的错误日志。(挖个坑~~?)

参考文章:

  • 把前端监控做到极致
  • [浏览器端 JavaScript 异常监控 For Dummies.pdf](https://github.com/kof97/QCon/blob/master/全球软件开发大会2016上海PDF/浏览器端 JavaScript 异常监控 For Dummies.pdf)

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-07-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 较真的前端 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 为什么要做前端异常监控
    • 捕获方式
      • 各个方法的优缺点:
    • 其他捕获异常方式
      • 小结
        • 应用层的使用
          • 错误上报SDK的实现
            • 总结
            相关产品与服务
            前端性能监控
            前端性能监控(Real User Monitoring,RUM)是一站式前端监控解决方案,专注于 Web、小程序等场景监控。前端性能监控聚焦用户页面性能(页面测速,接口测速,CDN 测速等)和质量(JS 错误,Ajax 错误等),并且联动腾讯云应用性能监控实现前后端一体化监控。用户只需要安装 SDK 到自己的项目中,通过简单配置化,即可实现对用户页面质量的全方位守护,真正做到低成本使用和无侵入监控。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档