【这个在去年8月就起稿了,一直没有发布....】
一、前言
说到前端监控大家应该都不会陌生,这是现代前端工程的标配之一。引入前端监控系统,可以使用例如fundebug,Sentry等第三方监控神器,当然你完全可以自己定制一套符合实际情况的监控模型。一个监控系统大致可以分为四个阶段:日志采集、日志存储、统计与分析、报告和警告。下面主要从几个方面谈谈我对前端代码异常监控的一些理解。
二、JS异处理
脚本错误一般分为两种:语法错误,运行时错误。常见的处理方式有:
2.1 try..catch
捕获
用来捕获捉到运行时的同步错误,示例:
try { a // 未定义变量 ,如果这里是语法错误,是无法捕获的,不过语法错误一般都会被eslint拦下了 } catch(e) { console.log(e); //上报错误 }
2.2 window.onerror
捕获全局错误:
/** * @param {String} msg 错误信息 * @param {String} url 出错文件 * @param {Number} row 出错行号 * @param {Number} col 出错列号 * @param {Object} error 错误详细信息 */ window.onerror = function (msg, url, row, col, error) { //code //解析,收集,上报 return true;//错误便不会暴露到控制台中 }; error;
2.3 注意几点:
a、对于 onerror 这种全局捕获,最好写在所有 JS 脚本的前面,因为你无法保证你写的代码是否出错,如果写在后面,一旦发生错误的话是不会被 onerror 捕获到的。
b、onerror 是无法捕获到网络异常的错误,于网络请求异常不会事件冒泡,因此必须在捕获阶段将其捕捉到才行,我们可以:
<script> window.addEventListener(‘error‘, (msg, url, row, col, error) => { console.log(‘我知道 404 错误了‘); console.log( msg, url, row, col, error ); return true; }, true); </script> <img src="./404.png" >
c、在实际的使用过程中,onerror 主要是来捕获预料之外的错误,而 try-catch 则是用来在可预见情况下监控特定的错误,两者结合使用更加高效。
三、Promise 错误
Promise 实例抛出异常而你没有用 catch 去捕获的话,onerror 或 try-catch 也无能为力,无法捕捉到错误。
所以如果你的应用用到很多的 Promise 实例的话,特别是你在一些基于 promise 的异步库比如 axios 等一定要小心,因为你不知道什么时候这些异步请求会抛出异常而你并没有处理它,所以你最好添加一个 Promise 全局异常捕获事件 unhandledrejection。
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‘ });
四、异常上报
4.1、上报方式
监控拿到报错信息之后,接下来就需要将捕捉到的错误信息发送到信息收集平台上,常用的发送形式主要有两种:
- 通过 Ajax 发送数据
- 动态创建 img 标签的形式
实例 - 动态创建 img 标签进行上报
function report(error) { var reportUrl = ‘http://xxxx/report‘; new Image().src = reportUrl + ‘error=‘ + error; }
4.2、抽样上报错误
Reporter.send = function(data) { // 只采集 30% if(Math.random() < 0.3) { send(data) // 上报错误信息 } }
五、统计页面所有AJAX性能数据
如何统计页面所有AJAX性能数据,如何知道所有AJAX已加载完毕?鉴于绝大部分网页的ajax都是用的XMLHttpRequest对象,我们可以在页面加载之处重新定义XMLHttpRequest对象,对open,onload,onreadystatechange方法进行拦截。请求接口时长可以监听ajaxReadyStateChange事件:
/** * 拦截接口请求,上报接口信息 */ //统一拦截ajax请求 var start_time = 0, gap_time = 0; //计算请求延时 window.addEventListener(‘ajaxReadyStateChange‘, function (e) { var xhr = e.detail, status = xhr.status, readyState = xhr.readyState, responseText = xhr.responseText; /** * 计算请求延时 */ if(readyState == 1){ start_time = (new Date()).getTime(); } if(readyState == 4){ gap_time = (new Date()).getTime() - start_time; } /** * 上报请求信息 */ if(readyState == 4){ httpReport(gap_time, status, xhr.responseURL) } })
六、如何解决数据频繁写入数据量太大的问题,数据库应该怎么设计或处理
1、写定时任务,每晚几点钟对数据表进行备份,统计,或删除
....
参考:
https://github.com/happylindz/blog/issues/5
原文地址:https://www.cnblogs.com/leaf930814/p/9251776.html