收集日志的方法

发布时间:2026/7/3 1:14:14
收集日志的方法 主动判断我们在一些运算之后得到一个期望的结果然而结果不是我们想要的// test.js function calc(){ // code... return val; } if(calc() ! someVal){ Reporter.send({ position: test.js::Functioncalc msg: calc error }); }这种属于逻辑错误/状态错误的反馈在接口status判断中用的比较多。2.try..catch捕获判断一个代码段中存在的错误try { init(); // code... } catch(e){ Reporter.send(format(e)); }以init为程序的入口代码中所有同步执行出现的错误都会被捕获这种方式也可以很好的避免程序刚跑起来就挂。3.window.onerror捕获全局错误window.onerror function() { var errInfo format(arguments); Reporter.send(errInfo); return true; };在上面的函数中返回return true错误便不会暴露到控制台中。下面是它的参数信息/** * param {String} errorMessage 错误信息 * param {String} scriptURI 出错的文件 * param {Long} lineNumber 出错代码的行号 * param {Long} columnNumber 出错代码的列号 * param {Object} errorObj 错误的详细信息Anything */ window.onerror function(errorMessage, scriptURI, lineNumber,columnNumber,errorObj) { // code.. }window.onerror算是一种特别暴力的容错手段try..catch也是如此他们底层的实现就是利用 C/C 中的goto语句实现一旦发现错误不管目前的堆栈有多深不管代码运行到了何处直接跑到顶层或者try..catch捕获的那一层这种一脚踢开错误的处理方式并不是很好。☞ 收集日志存在的问题收集日志的目的是为了及时发现问题最好日志能够告诉我们错误在哪里更优秀的做法是不仅告诉错误在哪里还告诉我们如何处理这个错误。终极目标是发现错误自动容错这一步是最难的。1. 无具体报错信息Script error.先看下面的例子test.html!-- http://barret/test.html -- script window.onerror function(){ console.log(arguments); }; /script script srchttp://barret/test.js/scripttest.js// http://barret/test.js function test(){ ver a 1; return a1; } test();我们期望收集到的日志是下面这样具体的信息为了对资源进行更好的配置和管理我们通常将静态资源放到异域上!-- http://barret/test.html -- script window.onerror function(){ console.log(arguments); }; /script script srchttp://localhost/test.js/script而拿到的结果却是翻开 Chromium 的 WebCore 源码可以看到跨域情况下返回的结果是Script error.。// http://trac.webkit.org/browser/branches/chromium/1453/Source/WebCore/dom/ScriptExecutionContext.cpp#L333 String message errorMessage; int line lineNumber; String sourceName sourceURL; // 已经拿到了所有的错误信息但如果发现是非同源情况sanitizeScriptError 中复写错误信息 sanitizeScriptError(message, line, sourceName, cachedScript);旧版 的 WebCore 中只判断了securityOrigin()-canRequest(targetURL)新版中还多了一个cachedScript的判断可以看出浏览器对这方面的限制越来越严格。在本地测试了下可见在file://协议下securityOrigin()-canRequest(targetURL)也是false。☞ 为何Script error.?简单报错Script error目的是避免数据泄露到不安全的域中一个简单的例子script srcbank.com/login.html/script上面我们并没有引入一个 js 文件而是一个 html这个 html 是银行的登录页面如果你已经登录了bank.com那 login 页面就会自动跳转到Welcome xxx...如果未登录则跳转到Please Login...那么 JS 报错也会是Welcome xxx... is not definedPlease Login... is not defined通过这些信息可以判断一个用户是否登录他的银行帐号给 hacker 提供了十分便利的判断渠道这是相当不安全的。☞crossOrigin参数跳过跨域限制image 和 script 标签都有 crossorigin 参数它的作用就是告诉浏览器我要加载一个外域的资源并且我信任这个资源。script srchttp://localhost/test.js crossorigin/script然而却报错了这是意料之中的错误跨域资源共享策略要求服务器也设置Access-Control-Allow-Origin的响应头header(Access-Control-Allow-Origin: *);回头看看我们 CDN 的资源Javascript/CSS/Image/Font/SWF 等这些静态资源其实都已经早早地加上了 CORS 响应头。2. 压缩代码无法定位到错误的具体位置线上的代码几乎都是经过打包压缩的几十上百的文件压缩后打包成一个而且只有一行。当我们收到a is not defined的时候如果只在特定场景下才报错我们根本无法定位到这个被压缩的a是个什么东西那么此时的错误日志就是无效的。第一个想到的办法是利用 sourceMap利用它可以定位到压缩代码某一点在未压缩代码的具体位置。下面是 sourceMap 引入的格式在代码的最后一行加入//# sourceMappingURLindex.js.map以前使用的是 ‘//’ 作为开头现在使用 ‘//#’然而对于错误上报这玩意儿没啥用。JS 不能拿到他真实的行数只能通过 Chrome DevTools 这样的工具辅助定位而且并不是每个线上资源都会添加 sourceMap 文件。sourceMap 的用途目前还只能体现在开发阶段。当然如果理解了 sourceMap 的 VLQ编码和位置对应关系也可以将拿到的日志进行二次解析映射到真实路径位置这个成本比较高貌似暂时也没人尝试过。那么有什么办法可以定位错误的具体位置或者说有什么办法可以缩小我们定位问题的难度呢可以这样考虑打包的时候在每两个合并的文件之间加上 1000 个空行最后上线的文件就会变成(function(){var longCode.....})(); // file 1 // 1000 个空行 (function(){var longCode.....})(); // file 2 // 1000 个空行 (function(){var longCode.....})(); // file 3 // 1000 个空行 (function(){var longCode.....})(); // file 4 var _fileConfig [file 1, file 2, file 3, file 4]如果报错在第 3001 行window.onerror function(msg, url, line, col, error){ // line 3001 var lineNum line; console.log(错误位置 _fileConfig[parseInt(lineNum / 1000) - 1]); // - 错误位置file 3