2010-05-04 11 views
14

Tôi đang sử dụng ELMAH để đăng nhập lỗi .net của tôi. Nó hoạt động rất tốt, nhưng tôi muốn mở rộng quá trình ghi lỗi để bao gồm các lỗi phía máy khách, tức là các lỗi JavaScript tùy ý. Tôi có thể nắm bắt các lỗi bằng cách sử dụng sự kiện window.onerror và sau đó gọi một .net handler (.ashx) để đăng nhập lỗi trong elmah, nhưng đây chỉ là hack nhỏ của tôi để giải quyết vấn đề. Có cách nào tốt hơn để đăng nhập lỗi phía khách hàng để elmah?Ghi nhật ký lỗi khách hàng bằng cách sử dụng Elmah

+0

và tôi cũng muốn có thể đăng nhập lỗi cổ điển asp –

+0

nhận được một chút javascript thú vị để nắm bắt các lỗi đơn giản có thể được đưa vào bất kỳ trang nào, nhưng vẫn cảm thấy như hack –

+0

hi Daniel, có thể bạn đăng lên javascript bạn đang sử dụng cho điều này? –

Trả lời

1

Catch tất cả các lỗi javascript bằng cách xử lý sự kiện window.onerror và thực hiện cuộc gọi ajax để tự đăng nhập lỗi trong ELMAH

window.onerror = function (msg, url, linenumber) { 

//make ajax call with all error details and log error directly into the elmah database 

//show freindly error msg here to user 

//hide error from browser 
return true; 
} 

Không giải pháp tốt hơn đã được tìm thấy vào thời điểm đó.

3

Hãy xem hoptoadapp.com và cách họ thực hiện báo cáo javascript.

Đó là điều chính xác như nhau, nhưng một phụ trợ khác nhau :-)

+0

Điều này có vẻ tuyệt vời! Tại sao tôi chưa từng nghe về điều này? :-) –

+0

Điều tốt tôi có thể giúp! Bạn có thể đánh dấu câu hỏi là được chấp nhận không? ;-) – changelog

9

Dưới đây là một giải pháp hoàn chỉnh hơn (Tôi nghĩ rằng tôi nắm lấy nó từ trang web ELMAH ... không thể nhớ)

ErrorLogging.js:

window.onerror = function (msg, url, line) { 
     logError(msg, arguments.callee.trace()); 
    } 
    function logError(ex, stack) { 
     if (ex == null) return; 
     if (logErrorUrl == null) { 
      alert('logErrorUrl must be defined.'); 
      return; 
     } 

     var url = ex.fileName != null ? ex.fileName : document.location; 
     if (stack == null && ex.stack != null) stack = ex.stack; 

     // format output 
     var out = ex.message != null ? ex.name + ": " + ex.message : ex; 
     out += ": at document path '" + url + "'."; 
     if (stack != null) out += "\n at " + stack.join("\n at "); 

     // send error message 
     jQuery.ajax({ 
      type: 'POST', 
      url: logErrorUrl, 
      data: { message: out } 
     }); 
    } 

    Function.prototype.trace = function() 
    { 
     var trace = []; 
     var current = this; 
     while(current) 
     { 
      trace.push(current.signature()); 
      current = current.caller; 
     } 
     return trace; 
    } 

    Function.prototype.signature = function() 
    { 
     var signature = { 
      name: this.getName(), 
      params: [], 
      toString: function() 
      { 
       var params = this.params.length > 0 ? 
        "'" + this.params.join("', '") + "'" : ""; 
       return this.name + "(" + params + ")" 
      } 
     }; 
     if (this.arguments) 
     { 
      for(var x=0; x<this.arguments.length; x++) 
       signature.params.push(this.arguments[x]); 
     } 
     return signature; 
    } 

    Function.prototype.getName = function() 
    { 
     if (this.name) 
      return this.name; 
     var definition = this.toString().split("\n")[0]; 
     var exp = /^function ([^\s(]+).+/; 
     if (exp.test(definition)) 
      return definition.split("\n")[0].replace(exp, "$1") || "anonymous"; 
     return "anonymous"; 
    } 

Layout/Master Page:

<script src="@Url.Content("~/Scripts/ErrorLogging.js")" type="text/javascript"></script> 

<script type="text/javascript"> 
    //This needs to be here to be on everypage 
    var logErrorUrl = '@Url.Action("LogJavaScriptError", "Home")'; 
</script> 

HomeController.cs:

[HttpPost] 
    public void LogJavaScriptError(string message) { 
     ErrorSignal.FromCurrentContext().Raise(new JavaScriptErrorException(message)); 
    } 

JavaScriptErrorException.cs:

[Serializable] 
public class JavaScriptErrorException: Exception{ 
    public JavaScriptErrorException(string message) : base (message){} 
} 
+1

Không hoạt động. 'msg' là một chuỗi, nó không chứa các trường fileName, stack ...' arguments.callee.trace() 'sẽ chỉ trả về cuộc gọi trước đó (tức là xử lý onerror). – Gabriel

+1

Nó hoạt động.msg chứa tất cả thông tin trừ đi ngăn xếp cuộc gọi. Nó cho bạn biết số dòng và lỗi. Ví dụ: JavaScriptErrorException: Uncaught TypeError: Object [object Array] không có phương thức 'hide': tại đường dẫn tài liệu 'http: // xxxx/Reports/TableBreakdown? StartDate = 02% 2F27% 2F2013% 2009% 3A44% 3A46 & endDate = 03 % 2F27% 2F2013% 2009% 3A44% 3A46 & phân tích = TopIssues '. tại ẩn danh ('Loại không bắt buộc: Đối tượng [đối tượng mảng] không có phương thức' ẩn '', 'http: // xxxx/Báo cáo/BảngBreakdown? startDate = 02% 2F27% 2F2013% 2009% 3A44% 3A46 & endDate = 03% 2F27% 2F2013 % 2009% 3A44% 3A46 & phân tích = TopIssues ',' 130 ') – rbj325

0

Hãy xem xét điều này.

http://joel.net/logging-errors-with-elmah-in-asp.net-mvc-3--part-5--javascript

Việc sửa đổi duy nhất mà tôi đã phải thực hiện với mã ở trên liên quan các bó.

tôi thay

... với @ Scripts.Render ("~/stacktrace.js")

Và trong bó cấu hình của tôi tôi đã thêm dòng ... bundles.Add (ScriptBundle mới ("~/stacktrace.js") Bao gồm ("~/Scripts/stacktrace.js"));

Điều này làm cho mã tương thích với gói MVC 4 mới hơn.