当前位置: 首页 > 科技观察

前端一站式异常监控捕获解决方案

时间:2023-03-15 09:38:09 科技观察

【引用自ouven的博客】1.前端异常监控的重要性软件异常监控往往直接关系到软件本身的质量,一个完整的异常监控系统往往可以快速定位到运行的软件,可以帮助我们快速定位到异常的来源,提高软件的质量。在服务器开发中,我们经常使用日志来记录请求错误和服务器异常,但是在客户端,前端应用是直接部署在用户浏览器中运行的。如果发生错误,应该如何捕获并发送到服务器?将前端错误日志传输到服务器非常简单。发生异常时直接发送请求即可。下面我们主要讨论错误捕获方案。2、现有的异常监控方案window.onerror全局异常捕获目前,前端捕获页面异常主要有两种方式。window.onerror捕获整个页面运行的错误。领域支持,即需要涉及到服务器的修改成本,否则无法得到运行时具体的堆栈错误信息,而是“脚本错误”的信息,不利于我们定位问题。window.onerror=function(msg,file,row,column,errorObj){console.log(msg);//scripterror.console.log(file);//console.log(row);//0console.log(column);//0console.log(errorObj);//{}setTimeout(function(){//发送请求上报日志信息errorReport(e.name,e.message+e.stack);},5000);}try-catch运行时方案现有的另一种方案是try-catch。对于一个方法函数,我们可以这样定义来捕获函数中的运行时异常,但是try-catch只能捕获当前单个作用域内的异常。另外,使用try-catch会带来一定的性能损失。根据循环测试,平均性能会损失6%到10%。但是,为了提高应用程序的质量和稳定性,这些都是可以接受的。functionwrapFunction(fn){returnfunction(){try{returnfn.apply(this,arguments);}catch(e){console.log(e);_errorProcess(e);return;}};}//fn函数内部当代码运行错误时,可以捕获它。fn=wrapFunction(fn);//或者异步函数中回调函数的错误也可以通过var_setTimeout=setTimeout;setTimeout=function(fn,time){return_setTimeout(wrapFunction(fn),time);}//模块定义函数也可以改写定义var_require=require;require=function(id,deps,factory){if(typeof(factory)!=='function'||!factory){return_require(id,deps);}else{return_require(id,deps,wrapFunction(factory));}};然后我们可以重新定义常用的模块入口函数,包括define、require等,这样就可以通过try-catch捕获模块主作用域内的异常。在前面的处理方式中,这种方式非常有效,可以直接获取到大部分错误栈中的异常和栈信息。3.改进的一站式解决方案在React开发时代,这种方法不能直接使用。我们知道React的组件都是类,类其实就是构造函数。这里普及一下类和构造函数其实很相似。除了A类的构造函数是A类,其他信息和A函数类似,typeof得到的类型也一样。但是我们不能把构造函数A直接放到try-catch中运行,因为它需要通过关键字new来实例化,创建一个新的作用域。这时候我们要处理的问题就是捕捉React中属性方法的错误。你应该记住,JavaScript中的函数有一个特殊的属性原型。当函数用作构造函数时,原型中的属性将被实例化。属性方法,这个属性对类也是有效的。那么我们就可以在React中对class的特殊属性prototype的内容进行处理,将方法函数封装在Component中。functiondefineReact(Component){varproto=Component.prototype;for(varkeyinproto){if(typeof(proto[key])==='function'){proto[key]=_wrapFunction(proto[key]);}}returnComponent;这样就可以捕获实例化生成的React组件内部方法中的错误。classcomponenttextendsReact.Component{componentDidMount(){vara={};console.log(a.b.c);}render(){return

helloworld
;}}exportdefaultdefineReact(component);这里可以添加defineReact操作,在构建打包工具中处理,避免我们直接修改代码层。React直接报错不利于定位问题,打包后直接获取堆栈错误错误捕获的范围增加了,不仅可以帮助我们快速定位开发中的问题,也可以捕获React线上应用的运行时错误。