搭建前端监控,如何采集异常数据?

大家好,我是若川 。持续组织了近一年的源码共读活动,感兴趣的可以点此加我微信参与,每周大家一起学习200行左右的源码,共同进步 。同时极力推荐订阅我写的《学习源码整体架构系列》包含20余篇源码文章 。历史面试系列 。另外:目前建有江西|湖南|湖北籍前端群,可加我微信进群 。
前两篇,我们介绍了为什么前端应该有监控系统,以及搭建前端监控的总体步骤,前端监控的 Why 和 What 想必你已经明白了 。接下来我们解决 How 如何实现的问题 。
如果不了解前端监控,建议先看前两篇:
本篇我们介绍,前端如何采集数据,先从收集异常数据开始 。
什么是异常数据?
异常数据,是指前端在操作页面的过程中,触发的执行异常或加载异常,此时浏览器会抛出来报错信息 。
比如说你的前端代码用了个未声明的变量,此时控制台会打印出红色错误,告诉你报错原因 。或者是接口请求出错了,在网络面板内也能查到异常情况,是请求发送的异常,还是接口响应的异常 。
在我们实际的开发场景中,前端捕获的异常主要是分两个大类,接口异常 和 前端异常,我们分别看下这两大类异常怎么捕获 。
接口异常
接口异常一定是在请求的时候触发 。前端目前大部分的请求是用 axios 发起的,所以只要获取 axios 可能发生的异常即可 。
如果你用的写法,则用 .catch 捕获:
axios.post('/test').then((res) => {console.log(res);}).catch((err) => {// err 就是捕获到的错误对象handleError(err);});
如果你用 async/await 的写法,则用 try..catch.. 捕获:
async () => {try {let res = await axios.post('/test');console.log(res);} catch (err) {// err 就是捕获到的错误对象handleError(err);}};
当捕获到异常之后,统一交给函数处理,这个函数会将接收到的异常进行处理,并调用 上报接口 将异常数据传到服务器,从而完成采集 。
上面我们写的异常捕获,逻辑上是没问题的,实操起来就会发现第一道坎:页面这么多,难道每个请求都要包一层 catch 吗?
是啊,如果我们是新开发一个项目,在开始的时候就规定每个请求要包一层 catch 也无可厚非,但是如果是在一个已有的规模还不小的项目中接入前端监控,这时候在每个页面或每个请求 catch 显然是不现实的 。
所以,为了最大程度地降低接入成本,减少侵入性,我们是用第二种方案:在 axios 拦截器中捕获异常 。
前端项目,为了统一处理请求,比如 401 的跳转,或者全局错误提示,都会在全局写一个 axios 实例,为这个实例添加拦截器,然后在其他页面中直接导入这个实例使用,比如:
// 全局请求:src/request/axios.jsconst instance = axios.create({baseURL: 'https://api.test.com'timeout: 15000,headers: {'Content-Type': 'application/json',},})export default instance
然后在具体的页面中这样发起请求:
// a 页面:src/page/a.jsximport http from '@/src/request/axios.js';async () => {let res = await http.post('/test');console.log(res);};
这样的话,我们发现每个页面的请求都会走全局 axios 实例,所以我们只需要在全局请求的位置捕获异常即可,就不需要在每个页面捕获了,这样接入成本会大大降低 。
按照这个方案,接下来我们在 src//axios.js 这个文件中动手实施 。
拦截器中捕获异常
首先我们为 axios 添加响应拦截器: