前端全(无)埋点之JS异常上报

2018-07-13 admin

左鹏飞 2017.11.29

相关阅读

1.前言

JS报错是比较常见的一个情景,但是有一些错误:例如后端接口字段发生变化了导致前端发生运行时错误;那么我们在本地测试的时候是测试不出来的,只有当发布到线上之后才可以发生异常。如果抢救及时,那还好,假如很晚才发现,那就可能造成很大的损失了。如果我们前端可以监控到这种报错,并及时上报的话,那我们的问题就比较好解决了。

2.什么是前端JS代码异常

前端代码异常指的是以下两种情况:

  • JS脚本里边存着语法错误;

  • JS脚本在运行时发生错误。

3. 错误异常信息应该包括什么

  • message {String} 错误信息。直观的错误描述信息。

  • url {String} 发生错误对应的脚本路径,比如是你的a.js 报错了还是 b.js 报错了。

  • lineNo {Number} 错误发生的行号。

  • columnNo {Number} 错误发生的列号。

  • error {Object} 具体的 error 对象,包含更加详细的错误调用堆栈信息,这对于定位错误非常有帮助。

4. try-catch捕获异常

  • try-catch能捕捉到被其内部代码运行时发生的错误
  • 如果有异步promise代码,不能正常捕获异常
  • 想捕获全局的错误事件,需要给整体的代码都包try-catch:通常的做法是打包后的整体JS外部包一个try-catch;每个方法内部都要包在try-catch里面
  • 通常需要借助工程化工具来实现包裹try-cath:例如:babel-plugin-try-catch-wrapper

5. window.onerror事件捕获异常

5.1 兼容性问题

  • 错误描述信息message,无法从这里面看出端倪,特别是压缩后脚本的报错信息。
  • 不同浏览器对同一个错误的message是不一样的。
  • IE10浏览器只能获取到message,url和lineNo,columnNo以及具体的error是获取不到的;不过 window.event 对象提供了errorLine和errorCharacter,以此来对应相应的行列号信息。
//不一定所有浏览器都支持col参数,如果不支持就用window.event来兼容
col = col || (window.event && window.event.errorCharacter) || 0;

  • 可以使用arguments.callee.caller 来递归出调用堆栈,这一类信息是最直接的错误信息信息
if (error && error.stack){
  //如果浏览器有堆栈信息,直接使用
  defaults.msg = error.stack.toString();

}else if (arguments.callee){
  //尝试通过callee拿堆栈信息
  var ext = [];
  var fn = arguments.callee.caller;
  var floor = 3;  //这里只拿三层堆栈信息
  while (fn && (--floor>0)) {
     ext.push(fn.toString());
     if (fn  === fn.caller) {
          break;//如果有环
     }
     fn = fn.caller;
  }
  ext = ext.join(",");
  defaults.msg = error.stack.toString();
}

5.2 其他注意事项

  • window.onerror的脚本必须要放到所有代码的最前边,否则会导致有些异常信息捕获不到,因为发生异常了,js也就不会往下执行了

  • 对于跨域的JS资源(通常异常捕获代码内联在主域名下,其他静态资源在静态资源集群CDN上),默认情况下,在本域名下捕获到一个跨域脚本的错误信息时,只能获取到一条信息 Script error.,没有文件信息,没有行列号数据,更没有详细的错误对象。针对window.onerror拿不到详细的信息,需要往资源的请求添加额外的头部。静态资源请求需要加多一个Access-Control-Allow-Origin头部,也就是需要后台加一个Access-Control-Allow-Origin,同时script引入外链的标签需要加多一个crossorigin的属性。这样就可以获取准确的出错信息。

  • 目前大多数站点的静态脚本文件,上线时都要压缩混淆的。所以发生错误时,获取到的行号就是第 1 行,列号会是一个巨大无比的数。这时你只能依赖错误信息和文件路径来定位错误。好在我们有 sourcemap,有了它,我们可以定位到源代码的位置。关于 sourcemap, 阮大这篇 详解 你可以去了解 sourcemap 的原理,mozilla 开源了一个 sourcemap 的工具,可以靠它来生成 sourcemap 或者根据 sourcemap 反算出变量名称和行列号。

  • 一个错误发生时,上报的数据量还是蛮大的。如果一个异常一直重复触发,连续不断的向服务器轰炸,既是数据冗余,也造成流量浪费。所以,对于异常信息的上报,从上报内容和上报频率上,应该加以限制。

//采用异步的方式,避免阻塞
  setTimeout(function() {

      //不一定所有浏览器都支持col参数,如果不支持就用window.event来兼容
      col = col || (window.event && window.event.errorCharacter) || 0;

      defaults.url = url;
      defaults.line = line;
      defaults.col =  col;

      if (error && error.stack){
          //如果浏览器有堆栈信息,直接使用
          defaults.msg = error.stack.toString();

      }else if (arguments.callee){
          //尝试通过callee拿堆栈信息
          var ext = [];
          var fn = arguments.callee.caller;
          var floor = 3;  //这里只拿三层堆栈信息
          while (fn && (--floor>0)) {
             ext.push(fn.toString());
             if (fn  === fn.caller) {
                  break;//如果有环
             }
             fn = fn.caller;
          }
          ext = ext.join(",");
          defaults.msg = error.stack.toString();
      }

  }, 0);

6.总结

QA不是万能的,用户的浏览环境非常复杂,很多情况无法靠测试用例去覆盖,所以最好建立一个前端错误日志,在真实用户端收集bug。

原文链接:https://github.com/zuopf769/notebook/blob/9fbe547a907f9f601ce15c386ddddaea38a6f9e5/fe/ 前端全(无)埋点之JS异常上报/README.md

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-35869.html

文章标题:前端全(无)埋点之JS异常上报

相关文章
从2014年的发展来展望JS的未来将会如何
<font face="寰�杞�闆呴粦, Arial, sans-serif ">2014骞达紝杞�浠惰�屼笟鍙戝睍杩呴€燂紝鍚勭�嶈��瑷€灞傚嚭涓嶇┓锛屼互婊¤冻鐢ㄦ埛涓嶆柇鍙樺寲鐨勯渶姹傘€傝繖浜涜��...
2015-11-12
Vue.js组件tab实现选项卡切换
本文实例为大家分享了vue插件tab选项卡的具体代码,供大家参考,具体内容如下 效果图: 代码如下: <!DOCTYPE html> <html lang="en"> <head> ...
2017-03-13
ajax为什么令人惊异?ajax的优缺点
使用Ajax的最大优点,就是能在不更新整个页面的前提下维护数据。这使得Web应用程序更为迅捷地回应用户动作,并避免了在网络上发送那些没有改变的信息。 Ajax不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。就像DHT...
2015-11-12
破解前端面试(80% 应聘者不及格系列):从 闭包说起
不起眼的开始 招聘前端工程师,尤其是中高级前端工程师,扎实的 JS 基础绝对是必要条件,基础不扎实的工程师在面对前端开发中的各种问题时大概率会束手无策。在考察候选人 JS 基础的时候,我经常会提供下面这段代码,然后让候选人分析它实际运行的结...
2017-06-02
JavaScript教程:JS中的原型
Keith Peters 几年前发表的一篇博文,关于学习没有“new”的世界,其中解释了使用原型继承代替构造函数。两者都是纯粹的原型编码。 标准方法(The Standard Way) 一直以来,我们学习的在 JavaScript 里创建对...
2015-11-12
three.js实现围绕某物体旋转
话不多说,请看代码: 可以拖动右上角观察变化 <!DOCTYPE html> <html lang="en" style="width: 100%; height:100%;"&gt...
2017-02-17
前端交流QQ群
我们建立了一个前端交流QQ群供大家交流,有什么问题都可以在群里提问,欢迎你的加入,也希望我们大家能够在群里互帮互助,同时也能学到东西。 我们相信,前端有你更精彩! 为了让更多的小伙伴加入我们,欢迎大家转发扩散! 长按以上二维码加入我们 ...
2016-04-01
NodeJS参考手册pdf版
下载地址:Nodejs参考手册PDF版下载 ...
2015-11-12
Riot.js:不足1KB的MVP客户端框架
Riot.js是一款MVP(模型-视图-呈现)开源客户端框架,其最大的特点就是体积非常小,不足1KB,虽然体积小,但它可以帮助用户构建大规模的Web应用程序。 Riot.js是由Moot公司开发,目前最新版本为v0.9.2,遵循MIT开源许...
2016-03-11
Node.js学习(1)----HTTP服务器与客户端
Node.js 标准库提供了 http 模块,其中封装了一个高效的 HTTP 服务器和一个简易的HTTP 客户端。http.Server 是一个基于事件的 HTTP 服务器,它的核心由 Node.js 下层 C++部分实现,而接口由 Jav...
2015-11-12
回到顶部