2013-10-07 25 views
4

如何精確定位來自其他域的腳本中發生的客戶端錯誤?記錄客戶端錯誤和「腳本錯誤」

爲了清楚起見,我們假設我們有一個平均大小的Web應用程序,它使用由其他域託管的多個腳本(如Google Maps JS SDK)。

有一天,您開始在錯誤日誌中接收Script error,這意味着第三方代碼中出現錯誤。

但是,如何在代碼中找到調用最終失敗的第三方代碼的確切方法?

PS:錯誤不是開發人員可以重現的,只是發生在客戶端機器上很少發生。

PPS:對於上面的錯誤window.onerror不是提供調用堆棧,正確的錯誤消息,文件名和行號。因此它除了Script error錯誤消息之外幾乎沒有任何幫助。

PPPS:

第三方腳本使用<script src="http://..."></script>標籤包含和執行使用someFunctionFromTheThirdPartyScript();

+0

使用elmah https://code.google.com/p/elmah/這可以記錄所有例外與最可能的信息 – HaBo

+0

@HaBo:uhm,asp.net? o_O – zerkms

+0

如果你希望它是獨立的框架工作,你可以嘗試這個window.onerror調用一個Ajax方法來存儲錯誤。 – HaBo

回答

1

我有一個類似的問題一次,我的解決辦法是......

// The parameters are automatically passed to the window.onerror handler... 
function myErrorFunction(message, url, linenumber) { 
    $.post(
     "https://host.and/path/to/script/that/stores/entries", 
     { 
      "url":url, // URL of the page where the error occured 
      "lineNumber":linenumber, // Line number where the error occer 
      "message":message //error message 
     }, 
     function(){ 
      //callback function for the $.post() 
      if(console) 
       if(console.log) 
        console.log("Error reported."); 
     } 
    ); 
} 
window.onerror = myErrorFunction; //adds function "myErrorFunction" to the onError Event 

爲了得到更多複雜的,你將需要利用一些技巧,我已經把我的調試項目放在: https://github.com/luke80/JavaScript-DebugTools-Luke

編輯: 好吧,我就收集了該項目適用於您的問題的重要位:

/* 
    String prototype .hashCode() 
    From: http://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript-jquery 
*/ 
if(typeof String['hashCode'] == "undefined") { 
    String.prototype.hashCode = function(){ 
    var hash = 0, i, char; 
    if (this.length == 0) return hash; 
    for (i = 0, l = this.length; i < l; i++) { 
     char = this.charCodeAt(i); 
     hash = ((hash<<5)-hash)+char; 
     hash |= 0; // Convert to 32bit integer 
    } 
    return hash; 
}; 
// Start of vars 
var _LOG_CALLERARGS_ON = true, 
    getCallerHash = function(funcString) { 
     return callerFunc.toString().hashCode(); 
    }, 
    getCallerArgs = function(obj) { 
     return JSON.stringify(Array.prototype.slice.call(obj),this._detectCircularity(Array.prototype.slice.call(obj))).replace(/^\[/,"(").replace(/\]$/,")"); 
    }, 
    detectCircularity = function(obj) { // From: http://stackoverflow.com/questions/4816099/chrome-sendrequest-error-typeerror-converting-circular-structure-to-json 
     return (function() { 
      var i = 0; 
      return function(key, value) { 
       if(i !== 0 && typeof(obj) === 'object' && typeof(value) == 'object' && obj == value) return '[Circular]'; 
       if(i >= 29) return '[Too deep, not mined]'; 
       ++i; 
       return value; 
      } 
     })(detectCircularity); 
    }, 
    caller = this.o.caller || arguments.callee.caller || "top"; 
// End of vars 
if(typeof caller != "string") { 
    if(caller) { 
     var callerData = ((caller.name)?caller.name:"Unnamed Caller:"+getCallerHash(caller))+((_LOG_CALLERARGS_ON)?getCallerArgs(caller.arguments):""); 
     // Since this loop could easily become problematic (infinite loop, anyone?) lets impose a limit. 
     var maxLoops = 64; 
     var loopCounter = 0; 
     // Now we gather all (or 64 of them) the caller names (and optionally their parameters) 
     while(caller.caller && loopCounter < maxLoops) { // <--- there was an error here that I fixed on Oct 15, 2013 @ 11:55AM 
      callerData += " <- "+((caller.caller.name)?caller.caller.name:"Unnamed Caller:"+getCallerHash(caller.caller))+((_LOG_CALLERARGS_ON)?getCallerArgs(caller.caller.arguments):"") 
      caller = caller.caller; 
      loopCounter++; 
     } 
     // callerData is now populated with your stack trace. 
    } else { 
     // Can't get errors from a non-existent caller 
    } 
} 

callerData變量應該有功能名稱的字符串(或函數的散列來填充內容,所以你可以半身份識別他們)可選的參數與函數被調用。

雖然不能總是獲取函數名,但可以識別這些函數的內容(因爲它們應該保持不變),並且仍然可以從傳遞的參數中獲得有用的調試信息等。

注意:我實際上沒有測試上面的代碼,但它應該與我的回購代碼大致相同。如果不起作用,請參考回購協議,並根據您的需要重新編制代碼。 :)

我希望有所幫助。

+1

如果在第三方腳本中發生錯誤,那麼'url'將是空的,'linenumber'將是'0','message'將是'Script error'。請閱讀問題的「PPS」部分。對不起,但沒有答案。 – zerkms

+0

你是對的,但「爲了更復雜,你需要利用一些技巧,我把它放到我的調試項目:https://github.com/luke80/JavaScript-DebugTools-Luke」 - 我打算把這個作爲我的回答,並描述一個人會怎麼做。也許我會。 – Luke

+0

hm,我不確定如何使用你的'Log'類 – zerkms