zoukankan      html  css  js  c++  java
  • 前端错误监控

    最近一直在做前端js错误监控的工作,在不断的打磨和完善中,发现里面还是知识点不少,现在就前端js错误监控做一些笔记和总结

    为什么要做前端错误监控?

    1. 为了保证产品的质量

    2. 有些问题只存在于线上特定的环境

    3. 后端错误有监控,前端错误没有监控

    下面会讲:

    • 前端错误的分类
    • 错误的捕获方式
    • 上报错误的基本原理

    一. 前端错误的分类

    1. 即时运行错误:代码错误
    2. 资源加载错误:(js、css、图片加载失败)

    二. 错误的捕获方式

    • 即时运行错误的捕获方式
      • try....catch
      • window.onerror
    • 资源加载错误的捕获方式
      • object.onerror
      • performance.getEntries
      • Error事件捕获

    1.即时运行错误的捕获方式

    1.try...catch

    通过try...catch我们能够知道出错的信息,并且也有堆栈信息可以知道在哪个文件第几行第几列发生错误。

    try {
               // 代码段
         } catch (err) {
              console.log(err.message)
         }
    

    缺点:

    1. 没法捕捉try,catch块,当前代码块有语法错误,JS解释器压根都不会执行当前这个代码块,所以也就没办法被catch住;
    2. 没法捕捉到全局的错误事件,也即是只有try,catch的块里边运行出错才会被你捕捉到,这里的块你要理解成一个函数块

    2.window.onerror

    全局捕获。window.onerror会在页面发生js错误时被调用可以收集到错误字符串信息、发生错误的js文件,错误所在的行数、列数、和Error对象(里面会有调用堆栈信息等),还可以在window.onerror最后return true让浏览器不输出错误信息到控制台

    /*
             * @param message{String}:错误消息
             * @param source{String}:引发错误的脚本的URL
             * @param lineno{Number}:发生错误的代码行
             * @param colno{Number}:发生错误的代码列
             * @param error{object}:错误对象
    */
    
            window.onerror = function (msg, url, line, colunm, error) {
                // 返回 true 则错误消息不显示在控制台,返回 false,则错误消息将会展示在控制台
                return true;
            }
    

    3.object.onerror

    img、script标签都可以添加onerror事件,当资源请求失败的时候,都会触发该事件。

    var img = document.getElementById('img');
    img.onerror=function(){
        console.log("出错啦");
    }
    

    4.performance.getEntries

    performance是h5的新特性之一,使用该方法能获取到当前页面已经加载到的资源,返回的是一个数组对象。

    例子获取页面中没有成功加载的图片资源?

    let arr = [],
        imgList=null,
        num=0,
        reg = (/.jpg$|.jpeg$|.png$|.gif$/i);
    
    // 1.通过performance.getEntries()获取已经加载了的图片资源
    performance.getEntries().forEach(item => {
        if (reg.test(item.name)) {
            arr.push(item.name)
        }
    })
    // 2.获取页面中所有的img标签
    imgList=document.getElementsByTagName('img');
    // 3.利用获取到的img的长度减去已经加载到的长度,如果大于0的部分,就是加载失败的
    num=imgList.length-arr.length; 
    

    控制台使用: var arr=[]; performance.getEntries().forEach((item,i)=>{console.log(arr[i]=item.name)}) 打印出网站中成功加载的所有资源。

    通过 document.getElementsByTagName('img').length减去上面的成功加载就能得出报错的图片资源数量了。

    // 返回网站内所有成功加载的png文件数量
    var arr=[]; 
    performance.getEntries().forEach((item,i)=>{console.log(arr[i]=item.name)})
    arr.filter(function(item, index, arr){
        var search1 = arr[index];
        return search1.includes('.png',search1.length-4) != false;
    }).length;
    

    5. Error事件捕获

    资源加载错误,虽然会阻止冒泡,但是不会阻止捕获。true:捕获,false:冒泡

    // window.addEventListener第三个参数是true的时候是捕获的过程,false是冒泡的过程 
    window.addEventListener('error',function(e){
            console.log("捕获",e)
        },true)
    

    6.延伸

    为了提升web性能,大部分web产品都有CDN部署,将资源部署到不同的域名上,但是我们都知道浏览器是有同源策略的,当加载不同域名的脚本发生错误时,语法错误的细节不会报告,仅返回"Script error"

    既然跨域JS运行错误可以捕获,错误提示是什么,应该怎么处理?

    捕获跨域错误

    必须做俩件事:

    • 客户端:在请求资源的script标签中增加crossorigin属性
    • 服务端:设置 js资源响应头Access-Control-Origin:*
    <script type="text/javascript" src="http://domain.com/a.js"  crossorigin></script>
    

    三. 上报错误的方式

    开发 Web 应用程序过程中的一种常见的做法,就是集中保存错误日志,以便查找重要错误的原因。那么我们怎么将js的错误信息记录到服务器数据库库中呢。

    • 采用Ajax通信的方式上报 (所有的错误监控都不是通过这种方式来做的;)
    • 利用Image对象上报(所有的监控体系都是这样做的,如谷歌)

    1. 采用Ajax通信的方式上报

    ajax来实现的弊端

    • 不支持跨域操作,因为很多情况下是一台服务器要负责处理多台服务器的错误;

    • 大多数Ajax通信都是通过javascript库提供的包装函数来处理,如果库代码本身就有问题, 而你还在依赖该库记录信息,可想而知,错误消息是不肯能得到记录的。

    怎么办?我们可以使用Image对象巧妙的解决这个问题

    2.利用Image对象上报

    Image对象的优点:

    • 所有浏览器都支持 Image 对象,包括那些不支持XMLHttpRequest对象的浏览器。

    • 可以避免跨域限制。通常都是一台服务器要负责处理多台服务器的错误,而这种情况下使用 XMLHttpRequest 是不行的。

    • 在记录错误的过程中出问题的概率比较低。大多数 Ajax 通信都是由 JavaScript 库提供的包装函 数来处理的,如果库代码本身有问题,而你还在依赖该库记录错误,可想而知,错误消息是不 可能得到记录的。

    /* 方法1 */
    //利用这种方式发送一个请求非常简单,比Ajax简单,不需要借助任何第三方库;
    (new Image()).src="http://baidu.com/test?r=error";
    //一行代码实现一个资源向上报;/test?这个是上报路径;r=error加信息
    
    
    /* 方法2 配合try...catch 更佳*/
    function logError(sev, msg){
         var img = new Image(); 
         img.src = "log.php?sev=" + encodeURIComponent(sev) + "&msg=" + encodeURIComponent(msg);
     } 
    
    for (var i=0, len=mods.length; i < len; i++){
         try { 
                mods[i].init(); 
          } catch (ex){
                logError("nonfatal", "Module init failed: " + ex.message); 
          }
    } 
    

    参考文章1

    参考文章2

    参考文章3

  • 相关阅读:
    如何在视频中添加字幕
    需要查询的东西
    VC++6.0选择打开文件命令时停止工作解决方法
    DMA方式的数据传送过程
    MFC如何创建目录
    opencv配置Debug,
    MFC中关闭窗口的几种办法+MFC中MessageBox的用法
    静态RAM和动态RAM的比较
    openCV学习笔记(2)--cvCreateTrackbar
    WWDC 2015动画效果 transform transition animation 练习
  • 原文地址:https://www.cnblogs.com/jing-tian/p/12386060.html
Copyright © 2011-2022 走看看