前端错误监控

538 阅读4分钟

前端监控是个很庞大丰富的内容,其包含页面UI监控,网络监控,性能监控,错误监控等内容,今天来简单谈谈前端错误监控。

错误种类

这里的前端错误指的是会在控制台抛出的异常,不包括业务逻辑及UI错误。

  • JS语法错误

  • JS运行错误(分为同步错误,异步错误)

  • 网络请求错误(分为静态资源加载,异步请求)

  • promise未处理异常

  • 跨域脚本异常(script error)

错误收集方法

前端错误的种类不多,但是不同的错误往往需要不同的收集方法,所以完整的错误日志需要不同的收集方法的结合才能全部收集。

try-catch

try-catch 能捕获代码块中的JS运行错误

try {
  a
} catch (err) {
  // ReferenceError: a is not defined
  // at err.html:12
}

try-catch 无法捕获异步错误

try {
  setTimeout(() => {
    a
  })
} catch (err) {
  // 无法捕获错误
}

try-catch 无法捕获语法错误

try {
  ,
} catch (err) {
  // 无法捕获错误
}

window.onerror

onerror 可以捕获语法错误和运行时错误

语法错误

/**
 * @param {String}  msg    错误信息
 * @param {String}  url    出错文件
 * @param {Number}  row    行号
 * @param {Number}  col    列号
 * @param {Object}  error  错误详细信息
 */
window.onerror = (msg, url, row, column, error) => {
  // Uncaught SyntaxError: Invalid or unexpected token
  return true; // 控制台不再输出错误
}

,

运行错误

window.onerror = (msg, url, row, column, error) => {
  // Uncaught ReferenceError: a is not defined
}

a

异步错误

window.onerror = (msg, url, row, column, error) => {
  // Uncaught ReferenceError: a is not defined
}

setTimeout(() => {
  a
})

errorEvent

对于静态资源的加载错误我们可以用 window.addEventListener('error') 来捕获

<img src="./404.png" alt="">

能得到的错误信息较少,类型为 error 的事件对象

window.addEventListener('error', (e) => {
  // type 为 error
  // 可以通过 e.target 来判断是否为静态资源请求错误,避免和 window.onerror 重复收集
}, true);

对于接口的异步请求则需要监听 xhr 实例的方法,例如 load

const xhr = new XMLHttpRequest();

xhr.addEventListener('load', (e) => {
  const { responseURL, status, statusText } = e.target;
  // example.png 404 Not found
})

xhr.open('GET', 'example.png');
xhr.send();

一般通过 xhr 的实例方法改写来实现错误收集,网上的资料很多,大家可以自行搜索。

unhandledrejectionEvent

现在我们常用 Promise 来解决回调地狱的问题,如果 Promise 的 rejection 状态没被处理会怎么样呢?

Promise.reject(2) // Uncaught (in promise) 2

对于未处理的 rejection 会控制台输出,我们可以使用 unhandledrejection 来捕获

window.addEventListener('unhandledrejection', (e) => {
  const { type, reason } = e;
  // unhandledrejection 2
  e.preventDefault(); // 控制台不再输出reject
})

错误收集方法小结

前面我们介绍了不同的错误收集方法

JS语法错误JS运行错误JS异步错误静态资源加载请求异常Promise未处理异常
try-catchxxxxx
onerrorxxx
errorEventxxx
unhandledrejectionxxxxx
请求事件监听/重写xxxxx

可以看出,onerror 的功能最强大,可以收集最多错误类型,而且错误内容比较齐全,包含错误位置及错误信息。所以我们可以使用 onerror 作为统一的错误收集方法,同时对 静态资源加载 请求异常 Promise未处理异常 单独进行处理收集。在复杂的业务流程中则使用 try-catch 来做收集,容错处理。

注意防止重复收集。

跨域脚本异常(Script error)

Script error 是浏览器在同源策略限制下产生的,浏览器处于对安全性上的考虑,当页面引用非同域名外部脚本文件时中抛出异常的话,此时本页面是没有权利知道这个报错信息(包括语法错误,运行错误,promise未处理异常)的,取而代之的是输出 Script error 这样的信息。

所以跨域JS脚本的错误详情无法在主页面脚本捕获,只能得到 Script error,而未处理的promise异常也无法在 unhandledrejection 中捕获。

如何解决呢?在脚本标签中加上 crossorigin 属性

<script src="http://localhost:8081/test.js" crossorigin></script>

同时后端服务器按照 CORS 配置可访问域名就行,具体配置参考 CORS(跨源资源共享)

上报

上报方式和正常的请求一样,可以使用

  1. img 上报

  2. ajax 上报

function report(errInfo) {
  new Image().src = 'http://your-api-website?data=' + errInfo;
}

注意:img 请求有长度限制,数据太大最好还是用 ajax.post。

如果遇到错误信息太多的话,可以做了随机过滤

function report(errInfo) {
  if (Math.random() > 0.3) {
    new Image().src = 'http://your-api-website?data=' + errInfo;
  }
}

待完善

由于自己对 sourceMap 的原理及使用方面的知识不足,所以没有研究如何通过 sourceMap 使压缩后的行列和源码位置相对应,后期有研究再补充上。

总结

本文主要是向大家介绍了不同的错误类型及其对应的错误收集方法,如果在业务中有错误监控平台需求的话,还需了解更多的相关知识和业务经验才行。

参考


欢迎来前端菜鸟群一起摸鱼划水~516913974