<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                [TOC] # 收集用戶信息 ## navigator API * 當前的網絡狀態 * 運營商 * 地理位置 * 訪問時間 * 客戶端的版本(如果是通過客戶端訪問) * 系統版本 * 瀏覽器信息 * 設備分辨率 * 頁面的來源 * 用戶賬號信息 * 頁面訪問流程各階段耗時 * js代碼報錯信息 * 用戶的瀏覽器語言編碼 * 瀏覽器語言設置 * flash的版本 * 網頁的標題 * 網頁的來源 * cookie的數據 <br> # 各階段訪問耗時記錄 ## performance timing [performance API](https://developer.mozilla.org/en-US/docs/Web/API/Performance) * DNS 查詢耗時 :domainLookupEnd - domainLookupStart * TCP 鏈接耗時 :connectEnd - connectStart * request 請求耗時 :responseEnd - responseStart * 解析 dom 樹耗時 : domComplete - domInteractive * 白屏時間 :responseStart - navigationStart * domready 時間 :domContentLoadedEventEnd - navigationStart * onload 時間 :loadEventEnd – navigationStart 具體參見[W3C Resource timing](https://www.w3.org/TR/resource-timing/),[Performance.getEntries()](https://developer.mozilla.org/zh-CN/docs/Web/API/Performance/getEntries) ## performance getEntries 通過performance.getEntries(),可以得到一個數組,其中的每個元素分別代表著一個資源,元素對象包括的屬性跟上面的performance timing有點接近,還有不同的屬性包括name代表資源的地址,請求花費的時間duration。 <br> ## 其他方法 記錄訪問開始的時間可有以下的方法: * 服務器將訪問的時間渲染到頁面上 * SPA的話,記錄前一個頁面卸載的時間 記錄訪問過程的時間 * 在head標簽解析后,渲染body標簽前加入script標簽進行打點,一般將這個時間視為白屏時間 * 捕獲DOMContentLoaded事件來記錄dom元素加載完畢的時間 * 在首屏頁面的所有圖片加載完后進行記錄,保存首屏時間 * 捕獲load事件記錄頁面加載完成的時間 <br> <br> # 錯誤采集 ## window.onerror window.onerror可以捕捉運行時錯誤,可以拿到出錯的信息,堆棧,出錯的文件、行號、列號 ~~~ window.onerror = function(msg, url, row, col, error){ report({ msg, // 錯誤信息 url, // 發生錯誤對應的腳本鏈接 row, // 行號 col // 列號 }) } ~~~ > 注: onerror兼容性有問題,ie10 & safari6 才完整支持以上全部參數。 > 要注意以下幾點: * 要把 `window.onerror` 這個代碼塊分離出去,并且比其他腳本先執行(注意這個前提!)即可捕捉到語法錯誤。 * 由于網絡請求異常事件不會冒泡,需要在**捕獲**階段進行處理 * 不能捕獲 **promise** 的錯誤信息 * 跨域資源需要專門處理,需要在script標簽加上 **crossorigin** 屬性,服務器設置 `Access-Control-Allow-Origin` * window.onerror 函數只有在返回 true 的時候,異常才不會向上拋出,否則即使是知道異常的發生控制臺還是會顯示 Uncaught Error: xxxxx。 <br> ## 跨域資源處理 Script error 是瀏覽器在同源策略限制下產生的,瀏覽器處于對安全性上的考慮,當頁面引用非同域名外部腳本文件時中拋出異常的話,此時本頁面是沒有權利知道這個報錯信息的,取而代之的是輸出 Script error 這樣的信息。 首先為頁面上的 script 標簽添加 crossOrigin 屬性 ~~~html <script src="http://localhost:8081/test.js" crossorigin></script> ~~~ 其次,后端在響應頭里加上 ~~~ Access-Control-Allow-Origin: * ~~~ <br> ## promise的錯誤處理 通過 Promise 可以幫助我們解決異步回調地獄的問題,但是一旦 Promise 實例拋出異常而你沒有用 catch 去捕獲的話,onerror 或 try-catch 也無能為力,無法捕捉到錯誤。 ~~~js window.addEventListener('error', (msg, url, row, col, error) => { console.log('我感知不到 promise 錯誤'); console.log( msg, url, row, col, error ); }, true); Promise.reject('promise error'); new Promise((resolve, reject) => { reject('promise error'); }); new Promise((resolve) => { resolve(); }).then(() => { throw 'promise error' }); ~~~ 所以如果你的應用用到很多的 Promise 實例的話,特別是你在一些基于 promise 的異步庫比如 axios 等一定要小心,因為你不知道什么時候這些異步請求會拋出異常而你并沒有處理它,所以你最好添加一個 Promise 全局異常捕獲事件 `unhandledrejection`。 ~~~ window.addEventListener("unhandledrejection", function(e){ // Event新增屬性 // @prop {Promise} promise - 狀態為rejected的Promise實例 // @prop {String|Object} reason - 異常信息或rejected的內容 // 會阻止異常繼續拋出,不讓Uncaught(in promise) Error產生 e.preventDefault() }) ~~~ <br> ## try catch 無法捕捉到語法錯誤,只能捕捉運行時錯誤; 可以拿到出錯的信息,堆棧,出錯的文件、行號、列號; 需要借助工具把所有的function塊以及文件塊加入try,catch,可以在這個階段打入更多的靜態信息。 要注意的是try catch只能捕獲同步代碼的異常,對回調,setTimeout,promise等無能為力 <br> ## 網絡異常錯誤 由于網絡請求異常不會事件冒泡,因此必須在捕獲階段將其捕捉到才行,但是這種方式雖然可以捕捉到網絡請求的異常,但是無法判斷 HTTP 的狀態是 404 還是其他比如 500 等等,所以還需要配合服務端日志才進行排查分析才可以。 ~~~ <img src="./404.png" alt=""> <script> window.addEventListener('error', (msg, url, row, col, error) => { console.log('我知道 404 錯誤了'); console.log( msg, url, row, col, error ); return true; }, true); </script> ~~~ <br> <br> # 上報錯誤 * 后端提供接口,前端ajax上傳 * 創建一個新的圖片,url參數帶上錯誤信息 使用創建圖片的好處是簡單方便可跨域,可以防止重復請求,但要注意到地址欄可以攜帶的信息有限。 ~~~ function report(error) { var reportUrl = 'http://xxxx/report'; new Image().src = reportUrl + 'error=' + error; } ~~~ ### 頁面加載時間統計 ~~~ window.logInfo = {}; window.logInfo.openTime = performance.timing.navigationStart; // 白屏時間 window.logInfo.whiteScreenTime = +new Date() - window.logInfo.openTime; document.addEventListener('DOMContentLoaded', function (event) { window.logInfo.readyTime = +new Date() - window.logInfo.openTime; }); window.onload = function () { window.logInfo.allloadTime = +new Date() - window.logInfo.openTime; window.logInfo.nowTime = new Date().getTime(); var timname = { whiteScreenTime: '白屏時間', readyTime: '用戶可操作時間', allloadTime: '總下載時間', mobile: '使用設備', nowTime: '時間', }; var logStr = ''; for (var i in timname) { console.warn(timname[i] + ':' + window.logInfo[i] + 'ms'); if (i === 'mobile') { logStr += '&' + i + '=' + window.logInfo[i]; } else { logStr += '&' + i + '=' + window.logInfo[i]; } } (new Image()).src = '/action?' + logStr; }; ~~~ <br> ### 統計用戶使用設備 ~~~ window.logInfo.mobile = mobileType(); function mobileType() { var u = navigator.userAgent, app = navigator.appVersion; var type = {// 移動終端瀏覽器版本信息 ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios終端 iPad: u.indexOf('iPad') > -1, //是否iPad android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1, //android終端或者uc瀏覽器 iPhone: u.indexOf('iPhone') > -1 || u.indexOf('Mac') > -1, //是否為iPhone或者QQHD瀏覽器 trident: u.indexOf('Trident') > -1, //IE內核 presto: u.indexOf('Presto') > -1, //opera內核 webKit: u.indexOf('AppleWebKit') > -1, //蘋果、谷歌內核 gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1, //火狐內核 mobile: !!u.match(/AppleWebKit.*Mobile/i) || !!u.match(/MIDP|SymbianOS|NOKIA|SAMSUNG|LG|NEC|TCL|Alcatel|BIRD|DBTEL|Dopod|PHILIPS|HAIER|LENOVO|MOT-|Nokia|SonyEricsson|SIE-|Amoi|ZTE/), //是否為移動終端 webApp: u.indexOf('Safari') == -1 //是否web應該程序,沒有頭部與底部 }; var lists = Object.keys(type); for(var i = 0; i < lists.length; i++) { if(type[lists[i]]) { return lists[i]; } } } ~~~ <br> ### 錯誤量的統計 ~~~ var defaults = { msg: '', // 錯誤的具體信息 url: '', // 錯誤所在的url line: '', // 錯誤所在的行 col: '', // 錯誤所在的列 nowTime: '',// 時間 }; window.onerror = function (msg, url, line, col, error) { col = col || (window.event && window.event.errorCharacter) || 0; defaults.url = url; defaults.line = line; defaults.col = col; defaults.nowTime = new Date().getTime(); if (error && error.stack) { // 如果瀏覽器有堆棧信息,直接使用 defaults.msg = error.stack.toString(); } else if (arguments.callee) { // 嘗試通過callee拿堆棧信息 var ext = []; var fn = arguments.callee.caller; var floor = 3; while (fn && (--floor > 0)) { ext.push(fn.toString()); if (fn === fn.caller) { break; } fn = fn.caller; } ext = ext.join(","); defaults.msg = error.stack.toString(); } var str = '' for (var i in defaults) { // console.log(i,defaults[i]); if (defaults[i] === null || defaults[i] === undefined) { defaults[i] = 'null'; } str += '&' + i + '=' + defaults[i].toString(); } srt = str.replace('&', '').replace('\n', '').replace(/\s/g, ''); (new Image()).src = '/error?' + srt; } ~~~ ### 數據處理、數據展示 # 工具、平臺 ## [Fundebug](https://www.fundebug.com/) ## [AlloyLever](https://github.com/AlloyTeam/AlloyLever) <br> # 參考資料 [搭建一個前端監控系統,不再錯過BUG - 掘金](https://juejin.im/post/5a372716518825258a5fbc80) [前端錯誤監控與收集探究 | hpoenixf's blog](http://hpoenixf.com/前端錯誤監控與收集探究.html) https://juejin.im/post/5b35921af265da598f1563cf https://juejin.im/post/5aaa93345188257bf550cbfd https://juejin.im/post/5b5dcfb46fb9a04f8f37afbb [前端代碼異常監控實戰](https://zhuanlan.zhihu.com/p/31979395) https://zhuanlan.zhihu.com/p/27305665
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看