前端异常 跨终端实时追踪 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
famanoder
V2EX    程序员

前端异常 跨终端实时追踪

  •  
  •   famanoder
    famanoder 2016-12-08 21:21:49 +08:00 3490 次点击
    这是一个创建于 3230 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我已沦为 IE 狗!!!

    从 9 月份一开始,新项目正式启动,产品以客户端的形式发布,目前用的是.NET 的 WebBrowser 内嵌网页的形式开发,对于后端来说,一切都是那么自然、简单;可对于前端来说,彻底将我带入到了 IE 的黑洞,自此万劫不复!说实话,我内心无比鄙视这个 WebBrowser ,因为 windows 绑定了 IE , WebBrowser 默认使用 IE 内核,按理说现在 win7 及以上系统居多,所以这个内核怎么也是 IE9+居多才对啊,可恶的是,众多系统都是重装的非正版阉割后的系统,可恶的是, WebBrowser 在这些系统哪怕是装的 win7 、 IE11 都调的是 IE7 ,可恶的是程序对其不可控!可恶的是这个调用的 IE7 与浏览器的 IE7 还不太一样,我叫它非 7 非 8 ,有时我在 IE7 浏览器里看到一个样子,到了黑壳子里弹出检测结果是 IE7 ,样子居然和浏览器上不一样,完全(想骂人。。。)不在套路上!而且没有控制台,任意一个异常,无论是否影响程序,都会弹出一个讨人厌的脚本错误的提示框!由于我在浏览器上调试和开发的,所以一开始并不知道会有这些问题,即便当时我兼容到了 IE7 ,到了壳子里面又是一番乌七八糟的问题!当时每天下班回家躺在床上,我都在怀疑自己的前端之路是不是走进了一条死胡同,完全看不到光,说好的炫酷呢,说好的大前端呢?尼玛这都什么鬼?

    欣慰的是后端同学在积极研究怎么切换到 webkit 的壳子,基于一些不可预知的问题,以及项目催的太紧,到目前为止,我依然天天面对着 IE7891011 。。。。。不要拦我。。。让我哭会儿。。。

    话说还是要做个坚强的孩子!自己选择的路,再苦再累也要咬牙走完呀;一方面,兼容问题是前端不可避免的问题;另一方面,既然眼下没有更好的方案,只有靠自己一步步走稳脚下的路了;

    皇天不负苦心人,终于让我磨出了一个 ErrorInspector 模块!

    基于以上可恶的让人怀疑人生的问题,首先解决以下问题:

    1 、兼容到 IE7 ;

    2 、异常的反馈与追踪(支持跨域);

    3 、屏蔽掉那个讨人厌的脚本错误提示框;

    4 、要跨终端,比如那个丑的不要的 IE 壳子,不可调试;

    5 、错误实时上报并通知和展示;

    6 、一并追踪与后端交互的错误,比如: 500 、 404 ,把 Jquery 的 ajax 拉进来;

    7 、包装 try_catch ,多用 try_catch ;

    由于要兼容到 IE7 ,那么基础库用 Jquery 肯定最好了,加上自己平时造的一些模块和组件以及 Jquery 的插件,基本够开发用了;可怜的我再次与牛逼的 React 、 Angular 擦肩而过了;现在以 Nodejs 的模块化方式开发,用 webpack 打包合并,目前感觉还凑合;

    最初的想法是,通过 window.onerror 和 try_catch 捕获并上报错误到一个独立的错误收集站点,不需要后端配合,自己用 Express 造一个简单的站点就是,通过 H5 的 webSocket 和 Node 的 Socket.io 实时响应上报的错误,如果已打开浏览器端无需刷新即可收到通知,或者直接发送邮件提示,达到跨终端实时追踪上报;如果可以的话,在 Web 上可以做更多工作,比如,图形化分析和展示,常见错误的解决方法的预测和提示,如果是线上收集站点还可以对错误极其解决方法做分类收集,供浏览者参考;总之, face to error,just do it !

    因为问题最终上报到我这,所以就不存在浏览器兼容问题了,当然选最好的谷歌了, BSIE !!!;没做太多优化,第一版错误反馈展示的页面大概是这个傻样子:

    图片描述

    当然,图片里是测试的结果,每条展开有更多错误的详情,包括错误引发的文件地址、行号、错误类型、浏览器版本、时间、所在页面、触发节点等;实际发现, window.onerror 捕获的错误并不总是很详细,最好是多用包装好的 try_catch 去主动上报,才会比较容易定位错误源,多用 try_catch 是个好习惯;因为难免存在跨域的问题,默认使用 new Image 的方式 GET 数据,当然,这不是必须的,支持自定义上报地址和上报方法;至于屏蔽掉那个讨人厌的脚本错误提示框,其实很简单,在 window.onerror 最后 return true 就是的,但是在谷歌里就会屏蔽掉控制台输出的内容,最好在线上环境使用,毕竟本地开发还得在控制台里调试;

    由于 Jquery 的 Ajax 使用特别灵活,所以做好全局去捕获 Ajax 与后端交互的错误;看看 Jquery 的 Ajax 常见用法:

    // 以 GET 为例 $.ajax({ url:'', success:function(data){}, error:function(){} }); $.get(url,data,function(data){}); $.get(url,data).success(function(data){}).error(function(){}); $.get(url,data).then(function(data){},function(err){}); // ... 

    这么多种用法,每次都去捕获 error 事件,然后在里面上报,肯定是相当不靠谱的; Jquery 是很好用的,可以通过设置全局的 error 事件来捕获上面各种方式下的错误,爽不爽?比如这样:

    $.ajaxSetup({ timeout:setAjax.$.timeout, error: function(xhr){ setTimeout(function () { util.getArgType(setAjax.$.onError)=='function'?setAjax.$.onError(xhr):alert(xhr.status+','+xhr.statusText); }, 1); } }); 

    不过这种错误一般后端的可能性大些,前端常见的就是这里的参数没传好,引发的后端错误,当然可以选择屏蔽不上报,或简单的提示个服务器异常就行了;

    ErrorInspector 的用法:

    1 、最好放在各大 library 的后面,你写的 JS 前面,因为框架本身一般不会引发错误,主要是监控自己写的代码可能存在的未预知的异常;

    2 、初始化配置:

    ErrorInspector.COnfig={ url:'http://localhost:2333/ErrorInspector/xiaofeng', //上报地址 qs:{ id:location.host, //默认以当前域为 id page:location.host+location.pathname,//错误页面地址 from:Url, //错误来源的地址 row:Number, //错误行号 col:Number, //错误列号 msg:String, //错误详情 browser:util.Browser, //浏览器类型及版本,默认几大主流浏览器,后续完善 time:util.fmtTime(), //错误触发的时间 inspector:String, //上报者 window|user|log...... // ...其他参数 ext:'hufeng' //扩展的参数 }, $:{ timeout:Number, //Jquery 的 Ajax 超时设置,会触发 onError onError:function(xhr){} //全局的 Jquery 的 Ajax 错误捕获 }, submit:function(data){}, //自定义上报方式,回调了上报内容 IgnoreFromJSPattern:/reg/ig, //屏蔽错误来源的地址,比如第三方的广告 IgnoreMsgPattern:/reg/ig, //屏蔽上报的消息内容,比如没太大意义的 script.error IgnoreBrowserError:0|1 //是否屏蔽控制台,主要屏蔽掉那个 IE 上讨厌的弹框 } 

    ErrorInspector.Config.qs 里的参数一般无需过问,错误触发时会自己收集上报;

    3 、 Tryit(function(report,log){});

    包装好的 try_catch ,回调的 ErrorInspector.report 和 ErrorInspector.log 其实大同小异,除了 try_catch 里的上报外,可以用回调值继续自定义上报;一般用这个函数包装代码块;

    4 、 ErrorInspector.report({name:value});

    主动上报;

    5 、 ErrorInspector.log;

    模拟简单的 console.log ,其实更像 alert ,可以充当统计代码用,或许还需改进;

    6 、后端使用 Express 和 Socket.io ,玩过 H5 的 webSocket 的同学立马就懂了,不解释;

    这些天被 IE 忙活坏了,例子未整理,唉,其实 IE 并非那么可怕! ErrorInspector.js 仅作分享,能力有限,欢迎改进! github 地址: https://github.com/famanoder/face2error/blob/master/public/ErrorInspector.js

    如果你已在路上,就勇敢的向前吧!

    原文来自:http://famanoder.com/bokes/5839e76bd37f5e680891fb47

    11 条回复    2016-12-09 17:35:51 +08:00
    mingyun
        1
    mingyun  
       2016-12-08 23:17:29 +08:00
    厉害了
    Rice
        2
    Rice  
       2016-12-09 08:53:42 +08:00
    终端报错能实时追踪啊,这个不错
    Rice
        3
    Rice  
       2016-12-09 08:54:19 +08:00
    感觉这个非常有用啊。
    Clarencep
        4
    Clarencep  
       2016-12-09 09:03:26 +08:00
    哎,心疼 LZ...

    咋不一上来就用 eletron 呢
    hiro0729
        5
    hiro0729  
       2016-12-09 09:51:21 +08:00
    node-webkit , nwjs , Electron ,选择这么多,偏偏要自虐进 ie 的坑。。。
    gongbaodd
        6
    gongbaodd  
       2016-12-09 09:56:49 +08:00
    判断不到那么精确吧, js 都是经过压缩过的
    xieyu33333
        7
    xieyu33333  
       2016-12-09 10:13:43 +08:00
    你应该使用 sentry
    wangxkww
        8
    wangxkww  
       2016-12-09 14:52:35 +08:00
    这时候不应该上 https://github.com/cefsharp/CefSharp 么……
    famanoder
        9
    famanoder  
    OP
       2016-12-09 17:33:49 +08:00
    @wangxkww 后端在研究中
    famanoder
        10
    famanoder  
    OP
       2016-12-09 17:35:08 +08:00
    @gongbaodd 所以一般 Tryit 或 report 主动上报
    famanoder
        11
    famanoder  
    OP
       2016-12-09 17:35:51 +08:00
    @hiro0729 后端是.NET ,我做不了主啊
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     877 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 19:17 PVG 03:17 LAX 12:17 JFK 15:17
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86