35

从 0 到 1 开始前端异常监控

 3 years ago
source link: https://mp.weixin.qq.com/s/pj5NUwSF5hbF9PWxy5qQtQ
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
f2amYrz.png!web

基础认知:

快速定位线上问题,捕获一些由于特殊情况导致的无法重现的客户问题

JS 处理异常的方式

try-catch 异常处理

但是 try-catch 处理异常的能力有限, 只能捕获捉到运行时非异步错误,对于语法错误和异步错误就显得无能为力,捕捉不到

下面是try-catch基本使用场景

示例:运行时错误

try {
  error    // 未定义变量 
} catch(e) {
  console.log('我知道错误了');
  console.log(e);
}
r2UZvmq.png!web 前端异常监控封面1

然而对于语法错误和异步错误就捕捉不到了 示例:语法错误

try {
 // ;符号大写,其实这种错误一般不会出现,因为在前期编辑器阶段就会体现出现,不会让程序正常发布
  var error = 'error';   
} catch(e) {
  console.log('我感知不到错误');
  console.log(e);
}

它会在开发的时候,浏览器就会报这个错误

V7bA7rj.png!web 前端

window.onerror 异常处理

window.onerror 捕获异常能力比 try-catch 稍微强点,无论是异步还是非异步错误,onerror 都能捕获到运行时错误。

示例:运行时同步错误

/**
 * @param {String}  msg    错误信息
 * @param {String}  url    出错文件
 * @param {Number}  row    行号
 * @param {Number}  col    列号
 * @param {Object}  error  错误详细信息
 */
window.onerror=function(msg, url, row, col, error){
  console.log('我知道错误了');
  console.log({
    msg,  url,  row, col, error
  })
  return true;
};

error;

示例:异步错误

window.onerror=function(msg,url,row,col,error){
  console.log('我知道异步错误了');
  console.log({
    msg,  url,  row, col, error
  })
  return true;
};

//定时器异步
setTimeout(() => {
  error;
});
6fiiu2u.png!web

关于 window.onerror 还有两点需要值得注意

  • 1.对于 onerror 这种全局捕获,最好写在所有 JS 脚本的前面,因为你无法保证你写的代码是否出错,如果写在后面,一旦发生错误的话是不会被 onerror 捕获到的。

  • 2.另外 onerror 是无法捕获到网络异常的错误。

当我们遇到 <img src="./404.png">404 网络请求异常的时候, onerror 是无法帮助我们捕获到异常的。

e2IF32n.png!web

可以看到没具体的错误信息和错误状态,但是有一个错误目标对象

e2IF32n.png!web

这点知识还是需要知道,要不然用户访问网站,图片 CDN 无法服务,图片加载不出来而开发人员没有察觉就尴尬了。

Promise 错误

通过 Promise 可以帮助我们解决异步回调地狱的问题,但是一旦 Promise 实例抛出异常而你没有用 catch 去捕获的话, onerrortry-catch 也无能为力,无法捕捉到错误。

window.addEventListener('error',(msg,url,row,col,error)=>{
  console.log('我感知不到 promise 错误');
  console.log(
    msg, url, row, col, error
  );
}, true);

Promise.reject('promise error');

new Promise((resolve, reject) => {
  reject('promise error');
});

new Promise((resolve) => {
  resolve();
}).then(() => {
  throw 'promise error'
});
ZjmeArm.png!web

所以我们需要主动监听 Promise 抛出的全局异常

window.addEventListener("unhandledrejection",function(e){
  e.preventDefault()
  console.log('我知道 promise 的错误了');
  console.log(e.reason);
  return true;
});

Promise.reject('promise error');

new Promise((resolve, reject) => {
  reject('promise error');
});

new Promise((resolve) => {
  resolve();
}).then(() => {
  throw 'promise error'
});

前端异常监控现状

Vue全局异常捕获

Vue 全局配置 errorHandler 可以进行全局错误收集,我们可以根据这个特性对前端异常做这样的处理:业务错误直接写在业务里;代码错误、 ajax 请求异常等错误可以进行全局捕获然后抛出,不至于前端页面挂掉

  • 代码层面的错误

import Vue from 'vue'
/**
 * err object  异常信息
 * vm          错误异常实例  
 * info        是 Vue 特定的错误信息 
 */
// 只在 2.2.0+ 可用
Vue.config.errorHandler=function(err,vm,info){
    //此处处理具体的错误信息
 return true;
 }

但是由于 errorHandler 无法捕获 promise 抛出的异常和网络层面资源的异常,所以还需要添加

//捕捉Promise异常
window.addEventListener("unhandledrejection",function(e){

});

//捕获网络错误,资源错误这些类似的错误,需要添加以下事件监听
window.addEventListener("error", function(e){
    
});

// 记住
window.addEventListener("error",()=>{})
和
`window.onerror=()=>{}`是由区别的

一个让你很开心的Api

navigator.sendBeacon() 方法可用于通过HTTP将少量数据异步传输到Web服务器。

  • 数据可靠,浏览器关闭请求也照样能发

  • 异步执行,不会影响下一页面的加载

  • 同时不会延迟页面的卸载或影响下一导航的载入性能

  • API使用简单

window.addEventListener('unload',logData,false);
function logData(){
   navigator.sendBeacon("http://mob/api/sendLog",{
     //参数
   });
}

浏览器兼容性很乐观

ryuYjiA.png!web

实现方案

1:数据传递部分 根据浏览器兼容是否支持 navigator.sendBeacon ,如果支持使用 navigator.sendBeacon 发送数据,如果不支持使用创建 Image 标签的形式发送数据

var img = new Image();
img.onload =function (){
}
img.src = `http://code/api/sendLog?data=${JSON.stringify({})}`;

//或者

window.addEventListener('unload', function(){
  navigator.sendBeacon("http://code/api/sendLog",{});
}, false);

2:需要收集的数据部分

{
    accountId:"账号标识ID",
    url:"当前页面URL",
    browser:"所属浏览器",
    version:"浏览器版本",
    system:"所属系统",
    referer:"入口页面",
    jsPath:"异常js文件路径",
    errorObj:"异常错误信息json字符串",
    connection:"连接网络情况"
}

下一篇将分享具体的功能实现,关注我下篇文件见

nYfyEjm.png!web

               


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK