内容简介:从自测到QA测试以及上线前的Code Review ,进过层层检查,还是会有疏忽。代码上线后,我们更多的是通过用户反馈或者后台的数据统计、异常数据来分析,找问题、定位问题。那么前端是否也能弄用一套比较完善的代码异步监控?例子错误:在某些情况下,上诉的src可能是null,导致这里调用null的indexOf方法发生异常。导致代码不往下走了。
从自测到QA测试以及上线前的Code Review ,进过层层检查,还是会有疏忽。代码上线后,我们更多的是通过用户反馈或者后台的数据统计、异常数据来分析,找问题、定位问题。那么前端是否也能弄用一套比较完善的代码异步监控?
例子错误:
src = img.getAttribute("src"); src.indexOf("http://XXX.com/"); 复制代码
在某些情况下,上诉的src可能是null,导致这里调用null的indexOf方法发生异常。导致代码不往下走了。
正常情况下,前端页面的语法错误以及运行时错误,都会在浏览器的console里边体现出来,包含错误的文件、行号、堆栈信息等。 那么有什么方法可以抓到错误日志?有两个方案:
-
try...catch(e)
针对某个代码块使用try...catch(e) 包装,这样错误就能被捕获到。缺点:
- 捕获不了异步错误(所以很多node,走的是回调的形式)
- 捕获不了全局错误事件
// demo2 可以捕获 try{ var i = 0; console.log(I) var c = b + cc }catch(e){ console.log(e) } // demo3 无法捕获 try{ setTimeout(()=>{ var i = 0; console.log(I) var c = b + cc }, 0) }catch(e){ console.log(e) } 复制代码
- window.onerror
window.onerror 可以拿到出错信息的文件名、行号、列号,还可以在window.onerror最后return true让浏览器不输出错误信息到控制台。 注意:
- window.onerror 代码块需要独立出去,避免与业务代码块、语法错误的代码块一起,避免事件不生效。
-
对于跨域的JS 资源,window.onerror 也无法监听到。
- js 处加上 crossorigin
- 加上 Access-Control-Allow-Origin
因此通常路径是监听全局的window.onerror 事件捕获到运行时的错误,然后上报到采集端,最后再做一个页面展示数据。
利用new Image 的方式采集日志
window.onerror = function (msg, url, line, col, error) { // 最后实时过滤出日志 (new Image).src = `/data?msg=${msg}&url=${url}&line=${line}&col=${col}&error=${error}` console.log(msg) console.log(url) console.log(line) console.log(col) console.log(error) // return true 实现错误日志不输出到console 处 return true } 复制代码
最终形式:
window.onerror = function(msg,url,line,col,error){ //没有URL不上报!上报也不知道错误 if (msg != "Script error." && !url){ return true; } //采用异步的方式 //我遇到过在window.onunload进行ajax的堵塞上报 //由于客户端强制关闭webview导致这次堵塞上报有Network Error //我猜测这里window.onerror的执行流在关闭前是必然执行的 //而离开文章之后的上报对于业务来说是可丢失的 //所以我把这里的执行流放到异步事件去执行 //脚本的异常数降低了10倍 setTimeout(function(){ var data = {}; //不一定所有浏览器都支持col参数 col = col || (window.event && window.event.errorCharacter) || 0; data.url = url; data.line = line; data.col = col; if (!!error && !!error.stack){ //如果浏览器有堆栈信息 //直接使用 data.msg = error.stack.toString(); }else if (!!arguments.callee){ //尝试通过callee拿堆栈信息 var ext = []; var f = arguments.callee.caller, c = 3; //这里只拿三层堆栈信息 while (f && (--c>0)) { ext.push(f.toString()); if (f === f.caller) { break;//如果有环 } f = f.caller; } ext = ext.join(","); data.msg = ext; } //把data上报到后台! },0); return true; }; 复制代码
前端日志存储,通常不会去实时上传日志,而是先存储,比如: Cookie, localStorage, sessionStorage, IndexDB, webSQL, FileSystem 几种毕竟方式
存储方式 | cookie | localStorage | sessionStorage | IndexDB | webSQL |
---|---|---|---|---|---|
容量 | 4K | 5M | 5M | 500M | 60M |
进程 | 同步 | 同步 | 同步 | 异步 | 异步 |
检索 | key | key | key | key, index | field |
IndexedDB是最好的选择,它具有容量大、异步的优势,异步的特性保证它不会对界面的渲染产生阻塞。而且IndexedDB是分库的,每个库又分store,还能按照索引进行查询,具有完整的数据库管理思维,比localStorage更适合做结构化数据管理。但是它有一个缺点,就是api非常复杂,不像localStorage那么简单直接。针对这一点,我们可以使用hello-indexeddb这个工具,它用Promise对复杂api进行来封装,简化操作,使IndexedDB的使用也能做到localStorage一样便捷
框架层异常处理
vue 中的 Vue.config.errorHandler
, React 有ErrorBoundary 。
class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } componentDidCatch(error, info) { this.setState({ hasError: true }); // 在这里可以做异常的上报 logErrorToMyService(error, info); } render() { if (this.state.hasError) { return <h1>Something went wrong.</h1>; } return this.props.children; } } // 在使用时,用 ErrorBoundary 包裹你的业务组件即可: <ErrorBoundary> <MyWidget /> </ErrorBoundary> 复制代码
window.performance 有浏览器相关时间的api
监听hash change 变化上报pv
以上所述就是小编给大家介绍的《前端监控了解与简易实现》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
文明之光(第二册)
吴军 / 人民邮电出版社 / 2014-6 / 59.00元
【《文明之光》系列荣获由中宣部、中国图书评论学会和中央电视台联合推选的2014“中国好书”奖】 吴军博士从对人类文明产生了重大影响却在过去被忽略的历史故事里,选择了有意思的几十个片段特写,以人文和科技、经济结合的视角,有机地展现了一幅人类文明发展的宏大画卷。 《文明之光 》系列大致按照从地球诞生到近现代的顺序讲述了人类文明进程的各个阶段,每个章节相对独立,全景式地展现了人类文明发展历程......一起来看看 《文明之光(第二册)》 这本书的介绍吧!