腳本錯誤量極致優化-監控上報與Script error

AngK62 7年前發布 | 12K 次閱讀 前端技術 JavaScript

在前端開發工作中,除了項目開發保質保量上線以外,項目的數據監控也應該配套起來,確保線上的正常運轉。如上報 pv 監控項目是否正常運轉;測速上報反應項目質量;腳本錯誤監控作為監控中重要一環,當頁面發生報錯的時候,通過上報錯誤信息,能及時發現存在問題,修復優化、減少損失。

本文基于在手Q家校群前端腳本錯誤量優化的方案,致力于打造極致的腳本錯誤優化。

作為首篇,主要講解基礎的腳本錯誤監控和上報方式,以及常會遇到的 Script error. 的產生原因和處理方法。

監控上報

腳本錯誤主要有兩類:語法錯誤、運行時錯誤。

監控的方式主要有兩種:try-catch、window.onerror。

監控方式

示例 · try-catch

try {
    test  // <- throw error
} catch(e){
    console.log('運行時錯誤信息 ↙');
    console.log(e);
}

通過給代碼塊進行 try-catch 包裝,當代碼塊出錯時 catch 將能捕獲到錯誤信息,頁面也將繼續執行。

當發生語法錯誤或異步錯誤時,則無法正常捕捉。

示例 · try-catch (語法報錯)

try {
    function empty()   // <-  throw error 語法錯誤
} catch(e){
    console.log('語法錯誤信息 ↙');
    console.log(e);
}

無法捕捉錯誤

示例 · try-catch (異步錯誤)

try {
    setTimeout(function() {
        test // <- throw error 異步錯誤
    },0)
} catch(e){
    console.log('異步錯誤信息 ↙');
    console.log(e);
}

無法捕捉錯誤

語法錯誤無法在 try-catch 中進行捕抓、而異步報錯則可以通過為異步函數塊再包裝一層 try-catch,增加標識信息來配合定位,可以用工具來進行處理,這里不展開。

示例 · window.onerror

/**
 * @param {String}  msg    錯誤信息
 * @param {String}  url    出錯文件
 * @param {Number}  row    行號
 * @param {Number}  col    列號
 * @param {Object}  error  錯誤詳細信息
 */
window.onerror = function (msg, url, row, col, error) {
    console.log('onerror 錯誤信息 ↙');
    console.log({
        msg,  url,  row, col, error
    })
};

test // <-  throw error

window.onerror 能捕捉到當前頁面的語法錯誤或運行時報錯,是十分強大的。

那么try-catch 是否不再需要呢?其實并不是。

在使用過程中的體會:onerror 主要用來捕獲預料之外的錯誤,而 try-catch 則可以用在預知情況下監控特定錯誤,兩種形式結合使用更加高效。

上報方式

監控錯誤拿到了報錯信息,接下來則是將捕抓的錯誤信息發送到信息收集平臺上,發送的形式主要有兩種:

  1. 通過Ajax發送數據
  2. 動態創建 img 標簽的形式

示例 · 動態創建 img 標簽進行上報

function report(msg, level) {
    var reportUrl = "http://localhost:8055/report";
    new Image().src = reportUrl + '?msg=' + msg;
}

監控上報整體流程

監控報錯,并將捕捉到的錯誤信息上報給數據收集平臺,如下圖

錯誤信息分析 · Script error

有了監控了后,就可以在收集平臺上進行查看腳本錯誤量的日志統計。

發現占據榜首的錯誤信息 “Script error.” 具有非常高的比例,沒有無具體的錯誤信息,無法定位問題,而這是怎么產生的呢?

產生 Script error 的原因

翻看在 webkit 的源碼 可以看到 “Script error.” 是瀏覽器在同源策略限制下所產生的。瀏覽器出于安全上的考慮,當頁面引用的非同域的外部腳本中拋出了異常,此時本頁面無權限獲得這個異常詳情, 將輸出 Script error 的錯誤信息。

優化 Script error

Script error 來自同源策略的影響,那么解決的方案之一是進行資源的同源化,另外也可以利用跨源資源共享機制( CORS )。

方案一:同源化

  1. 將js代碼內聯到html文件中
  2. 將js文件與html文件放到同一域名下

以上兩種方式能夠簡單直接地解決問題,但也可能帶來其他影響,如內聯資源不好利用文件緩存,同域無法充分利用cdn優勢等等。

方案二:跨源資源共享機制( CORS )

跨源資源共享 ( CORS )機制讓Web應用服務器能支持跨站訪問控制,從而能夠安全地跨站數據傳輸。主要是通過給請求帶上特定頭信息,服務器實現了CORS接口,就可以跨源通信,從而能夠看到具體報錯信息。

1. 為頁面上script標簽添加crossorigin屬性。

<script src="http://127.0.0.1:8077/main.js" crossorigin></script>

增加 crossorigin 屬性后,瀏覽器將自動在請求頭中添加一個 Origin 字段,發起一個 跨來源資源共享 請求。Origin 向服務端表明了請求來源,服務端將根據來源判斷是否正常響應。

2. 響應頭中增加 Access-Control-Allow-Origin 來支持跨域資源共享。

Access-Control-Allow-Origin: * 表示通過該跨域請求,且該資源可以被任意站點跨站訪問。而當該資源僅允許來自 http://127.0.0.1:8066 的跨站請求,其它站點都不能跨站訪問時,將可以返回:

Access-Control-Allow-Origin:http://127.0.0.1:8066

3. 指定域名的 Access-Control-Allow-Origin 的響應頭中需帶上Vary:Origin。

Vary 字段的作用在于為緩存服務器提供緩存規則及緩存篩選的依據。當增加 Vary:Origin 響應頭后,緩存服務器將會按照 Origin 字段的內容,緩存不同版本,在請求響應時根據請求頭中的 Origin 決定是否能夠使用緩存響應。

舉例 · 不加 Vary 將存在錯誤命中緩存的問題

上圖中,第一個請求(Origin: 127.0.0.1:8066)響應被瀏覽器緩存了,當第二個請求(Origin: 127.0.0.1:8888)發起,被錯誤命中了前一個請求的緩存,收到了 Access-Control-Allow-Origin: http://127.0.0.1:8066 的響應時,將導致資源加載失敗。

所以當 Access-Control-Allow-Origin 不是返回為 * 時,需要加上 Vary 返回頭來避免引緩存導致的權限問題。

跨域腳本報錯產生 Script error. 通過以上方式進行處理后將能夠捕獲到具體的報錯信息了。在 NodeJS 的實現中主要通過添加以下代碼:

app.use(function *(next){
    // 拿到請求頭中的 Origin
    var requestOrigin = this.get('Origin'); 
    if (!requestOrigin) { // 不存在則忽略
      return yield next;
    }

    // 設置 Access-Control-Allow-Origin: Origin
    this.set('Access-Control-Allow-Origin', requestOrigin);

    // 設置 Vary: Origin
    this.vary('Origin');
    return yield next;
});

以上為本文所有內容,兄弟篇:( coming soon.. )

 

 

來自:https://github.com/joeyguo/blog/issues/13

 

 本文由用戶 AngK62 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!