2011-09-16 37 views
241

Có thể thực hiện các thao tác sau bằng ELMAH không?Cách sử dụng ELMAH để ghi nhật ký lỗi theo cách thủ công

logger.Log(" something"); 

tôi đang làm một cái gì đó như thế này:

try 
{ 
    // Code that might throw an exception 
} 
catch(Exception ex) 
{ 
    // I need to log error here... 
} 

ngoại lệ này sẽ không được tự động đăng nhập bằng ELMAH, bởi vì nó đã được xử lý.

+1

Để tham khảo trong tương lai, tôi đã viết một bài về chính xác điều đó: [Lỗi ghi nhật ký lập trình] (http://docs.elmah.io/logging-errors-programmatically/). [Hướng dẫn ELMAH] của tôi (http://blog.elmah.io/elmah-tutorial/) cũng có một số thông tin về điều này. – ThomasArdal

Trả lời

383

Direct phương pháp đăng nhập văn bản, làm việc kể từ ELMAH 1.0:

try 
{ 
    some code 
} 
catch(Exception ex) 
{ 
    Elmah.ErrorLog.GetDefault(HttpContext.Current).Log(new Elmah.Error(ex)); 
} 

ELMAH 1.2 giới thiệu một API linh hoạt hơn:

try 
{ 
    some code 
} 
catch(Exception ex) 
{ 
    Elmah.ErrorSignal.FromCurrentContext().Raise(ex); 
} 

Có một sự khác biệt giữa hai giải pháp:

Phương thức
  • Raise áp dụng quy tắc lọc ELMAH cho ngoại lệ. Phương pháp Log thì không.
  • Raise là đăng ký dựa và có thể ghi lại một ngoại lệ vào một số nhật ký.
+1

sự khác nhau giữa phương pháp của bạn và các phương pháp khác là gì? – Omu

+0

Hoạt động từ ELMAH 1.0 –

+0

có sự khác biệt nào giữa cách đăng nhập và tăng không? – Omu

16
catch(Exception ex) 
{ 
    Elmah.ErrorSignal.FromCurrentContext().Raise(ex); 
} 
28

Bạn có thể sử dụng phương thức Elmah.ErrorSignal() để ghi nhật ký sự cố mà không tăng ngoại lệ.

try 
{ 
    // Some code 
} 
catch(Exception ex) 
{ 
    // Log error 
    Elmah.ErrorSignal.FromCurrentContext().Raise(ex); 

    // Continue 
} 
14

Có, có thể. ELMAH được thiết kế để ngăn chặn các ngoại lệ chưa được giải quyết. Tuy nhiên, bạn có thể báo hiệu một ngoại lệ cho ELMAH thông qua lớp ErrorSignal. Những ngoại lệ đó không được ném lên (không làm bong bóng), nhưng chỉ được gửi tới ELMAH (và cho các thuê bao của sự kiện Raise của lớp ErrorSignal).

Một ví dụ nhỏ:

protected void ThrowExceptionAndSignalElmah() 
{ 
    ErrorSignal.FromCurrentContext().Raise(new NotSupportedException()); 
} 
87

Tôi muốn giới thiệu gói cuộc gọi tới Elmah trong một lớp trình bao bọc đơn giản của riêng bạn.

using Elmah; 

public static class ErrorLog 
{ 
    /// <summary> 
    /// Log error to Elmah 
    /// </summary> 
    public static void LogError(Exception ex, string contextualMessage=null) 
    { 
     try 
     { 
      // log error to Elmah 
      if (contextualMessage != null) 
      { 
       // log exception with contextual information that's visible when 
       // clicking on the error in the Elmah log 
       var annotatedException = new Exception(contextualMessage, ex); 
       ErrorSignal.FromCurrentContext().Raise(annotatedException, HttpContext.Current); 
      } 
      else 
      { 
       ErrorSignal.FromCurrentContext().Raise(ex, HttpContext.Current); 
      } 

      // send errors to ErrorWS (my own legacy service) 
      // using (ErrorWSSoapClient client = new ErrorWSSoapClient()) 
      // { 
      // client.LogErrors(...); 
      // } 
     } 
     catch (Exception) 
     { 
      // uh oh! just keep going 
     } 
    } 
} 

Sau đó, chỉ cần gọi nó bất cứ khi nào bạn cần đăng nhập lỗi.

try { 
    ... 
} 
catch (Exception ex) 
{ 
    // log this and continue 
    ErrorLog.LogError(ex, "Error sending email for order " + orderID); 
} 

này có các lợi ích sau:

  • Bạn không cần phải nhớ cú pháp hơi cổ xưa này của cuộc gọi ELMAH
  • Nếu bạn có nhiều DLL bạn không cần phải tham khảo ELMAH Cốt lõi từ mỗi một - và chỉ cần đặt này trong của riêng bạn 'Hệ thống' DLL.
  • Nếu bạn cần thực hiện bất kỳ thao tác đặc biệt nào hoặc chỉ muốn đặt điểm ngắt để gỡ lỗi bạn có tất cả ở một nơi.
  • Nếu bạn di chuyển khỏi Elmah, bạn chỉ có thể thay đổi một địa điểm.
  • Nếu bạn có nhật ký lỗi kế thừa bạn muốn giữ lại (tôi chỉ xảy ra một cơ chế ghi lỗi đơn giản được gắn vào một số UI mà tôi không có thời gian để xóa).

Lưu ý: Tôi đã thêm thuộc tính 'contextualMessage' cho thông tin theo ngữ cảnh. Bạn có thể bỏ qua điều này nếu bạn thích nhưng tôi thấy nó rất hữu ích. Elmah tự động mở các ngoại lệ, vì vậy ngoại lệ cơ bản sẽ vẫn được báo cáo trong nhật ký nhưng contextualMessage sẽ hiển thị khi bạn nhấp vào nó.

+1

Câu trả lời hay. Có lẽ ELMAH nên thực hiện một cái gì đó tương tự ra khỏi hộp. Đôi khi thực sự khó gỡ lỗi mà không có ngữ cảnh. – ra00l

+2

Tôi thích tất cả nhưng nuốt bất kỳ lỗi phụ nào với '// uh oh! cứ tiếp tục đi'. Nếu việc xử lý lỗi của tôi bị lỗi thì tôi muốn biết. Tôi muốn nó làm ồn. –

+3

@JeremyCook Tôi đồng ý, nhưng với thông báo trước rằng nếu bạn không cẩn thận thất bại trong việc xử lý lỗi thường có xu hướng kết thúc tự gọi mình và sau đó thổi lên (oh và tôi cũng thực sự gọi API bên thứ ba ở đây để đăng nhập lỗi). Tôi có lẽ không nên để điều này trong câu trả lời này nhưng tôi đã có kinh nghiệm xấu với một điều như vậy xảy ra trước khi –

11

Tôi đang tìm cách làm điều tương tự trong một chủ đề tôi đã bắt đầu xếp hàng thư từ trong ứng dụng MVC4 của tôi, vì vậy tôi không có HttpContext sẵn có khi ngoại lệ được nêu ra. Để làm điều này tôi đã kết thúc với những sản phẩm sau dựa trên câu hỏi này và câu trả lời khác được tìm thấy trên đây: elmah: exceptions without HttpContext?

Trong tập tin cấu hình tôi đã chỉ định một tên ứng dụng:

<elmah> 
    <security allowRemoteAccess="false" /> 
    <errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="ELMAH" applicationName="myApplication"/> 
</elmah> 

Sau đó trong mã (như câu trả lời cung cấp ở trên, nhưng không có HttpContext), bạn có thể vượt qua null thay vì HttpContext:

ThreadPool.QueueUserWorkItem(t => { 
    try { 
     ... 
     mySmtpClient.Send(message); 
    } catch (SomeException e) { 
     Elmah.ErrorLog.GetDefault(null).Log(new Elmah.Error(e)); 
    } 
}); 
+0

Tôi thích giải pháp của bạn; tuy nhiên, tôi không thể giải quyết "Elmah". trong dự án của tôi. Tôi đã thử thêm "sử dụng Elmah;" trong mã của tôi, nhưng nó không tồn tại trong ngữ cảnh hiện tại của tôi. – Taersious

+0

@Taersious 'packages.config' của bạn trông như thế nào? Bạn có thấy một cái gì đó như: '' '' ' ''? Bạn đã cài đặt với NuGET chưa? – Matthew

+0

Tôi muốn nói có, nhưng dự án của tôi hiện đang bị khóa trong kiểm soát nguồn. Tôi đã thực hiện elmah theo cách thủ công từ tệp cấu hình mẫu trong dự án. – Taersious

2

có thể không có sẵn trong một số trường hợp.

Xác định

public class ElmahLogger : ILogger 
{ 
    public void LogError(Exception ex, string contextualMessage = null, bool withinHttpContext = true) 
    { 
     try 
     { 
      var exc = contextualMessage == null 
         ? ex 
         : new ContextualElmahException(contextualMessage, ex); 
      if (withinHttpContext) 
       ErrorSignal.FromCurrentContext().Raise(exc); 
      else 
       ErrorLog.GetDefault(null).Log(new Error(exc)); 
     } 
     catch { } 
    } 
} 

Sử dụng

public class MyClass 
{ 
    readonly ILogger _logger; 

    public MyClass(ILogger logger) 
    { 
     _logger = logger; 
    } 

    public void MethodOne() 
    { 
     try 
     { 

     } 
     catch (Exception ex) 
     { 
      _logger.LogError(ex, withinHttpContext: false); 
     } 
    } 
} 
0

Tôi đã cố gắng để viết tin nhắn tùy chỉnh vào các bản ghi ELMAH sử dụng Signal.FromCurrentContext() Nâng cao (ví dụ). và tìm thấy rằng những trường hợp ngoại lệ được sôi nổi, ví dụ:

try 
{ 
    ... 
} 
catch (Exception ex) 
{ 
    Elmah.ErrorSignal.FromCurrentContext().Raise(ex); 
    // this will write to the log AND throw the exception 
} 

Bên cạnh đó tôi không thấy như thế nào ELMAH hỗ trợ cấp độ khác nhau của khai thác gỗ - là nó có thể tắt tiết đăng nhập bằng một thiết lập web.config?

+1

Nếu bạn bắt một ngoại lệ và không ném nó một lần nữa, ngoại lệ không bong bóng lên. Có lẽ tôi hiểu lầm? ELMAH không hỗ trợ các mức ghi nhật ký khác nhau. Nó chỉ dành cho các lỗi. – ThomasArdal

+0

Cảm ơn, Thomas. Đó là chính xác những gì tôi đã cố gắng xác nhận –

Các vấn đề liên quan