Cách sử dụng ELMAH để ghi nhật ký lỗi thủ công


259

Có thể làm như sau bằng ELMAH khô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 ELMAH tự động đăng nhập, 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 rằng: Ghi nhật ký lỗi theo chương trình . Hướng dẫn ELMAH của tôi cũng có một số thông tin về điều này.
ThomasArdal

Câu trả lời:


412

Phương pháp viết nhật ký trực tiếp, hoạt động 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 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:

  • Raisephương pháp áp dụng quy tắc lọc ELMAH cho ngoại lệ. Logphương pháp không.
  • Raise là đăng ký dựa trên và có thể đăng nhập một ngoại lệ vào một số loggers.

1
sự khác biệt giữa phương pháp của bạn và những người khác là gì?
Omu

3
Những lỗi này ghi lại lỗi trong Elmah mà không khiến ứng dụng ngừng hoạt động. Nó cho phép bạn nắm bắt các ngoại lệ phổ biến, xử lý chúng đúng cách, nhưng vẫn có thể đăng nhập chúng.
PCasagrande

7
Tôi thấy rằng Elmah.ErrorSignal đã không đăng nhập khi POST trở lại chứa Html không an toàn cho Mvc4 .Net 4.5, trong ví dụ của tôi là POST trở lại từ Windows Access Control Services với SignInResponseMessage. Elmah.ErrorLog.GetDefault đã làm việc trong kịch bản đó
Adam

1
Tôi đã có vấn đề tương tự với Html không an toàn. ErrorLog.GetDefault đã thực hiện thủ thuật
hgirish

4
Một cảnh báo lớn khi sử dụng Elmah.ErrorLog.Log(): nó ném trong trường hợp bản thân cuộc gọi nhật ký thất bại, có thể làm sập toàn bộ ứng dụng web. Raise()thất bại âm thầm. Ví dụ: nếu có sự cố cấu hình sai ở phía máy chủ (ví dụ Elmah được định cấu hình để lưu lỗi vào đĩa, nhưng không có quyền truy cập chính xác vào thư mục nhật ký), .Log()phương thức sẽ ném. (Điều này tốt cho việc gỡ lỗi, ví dụ: tại sao không .Raise()đăng nhập bất cứ thứ gì?)
Cristian Diaconescu

91

Tôi khuyên bạn nên kết thúc cuộc gọi đến Elmah trong một lớp 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 phải đăng nhập một lỗi.

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

Điều này có những 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 Core từ mỗi một tệp - và chỉ cần đặt tệp này vào DLL 'Hệ thống' của riêng bạn.
  • Nếu bạn cần thực hiện bất kỳ xử lý đặc biệt nào hoặc chỉ muốn đặt một điểm dừng để gỡ lỗi, bạn có tất cả một nơi.
  • Nếu bạn rời khỏi Elmah, bạn có thể thay đổi một nơi.
  • Nếu bạn có bản ghi lỗi kế thừa mà bạn muốn giữ lại (tôi tình cờ có một cơ chế ghi nhật ký 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 ngay lập tức).

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 hủy bỏ các ngoại lệ để ngoại lệ cơ bản vẫn sẽ được báo cáo trong nhật ký nhưng ngữ cảnh sẽ được hiển thị khi bạn nhấp vào nó.


1
Câu trả lời chính xác. Có lẽ ELMAH nên thực hiện một cái gì đó tương tự ra khỏi hộp. Đôi khi rất khó để gỡ lỗi một 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 thứ cấp với // uh oh! just keep going. Nếu xử lý lỗi của tôi không thành công tôi muốn biết. Tôi muốn nó làm cho một số tiếng ồn.
Jeremy Cook

3
@JeremyCook Tôi đồng ý, nhưng với lời cảnh báo rằng nếu bạn không cẩn thận, các lỗi xử lý lỗi thường có xu hướng tự gọi và sau đó nổ tung (ồ và tôi thực sự đã gọi API của bên thứ ba ở đây để ghi lại lỗi). Có lẽ tôi không nên để lại câu trả lời này nhưng tôi đã có những trải nghiệm tồi tệ với điều tương tự xảy ra trước đây
Simon_Weaver

1
Nó sẽ còn tốt hơn imho như một phương pháp mở rộng.
Stephen Kennedy

1
Bạn có thể nghĩ: nah, tôi có thể cố gắng đăng nhập bao nhiêu lỗi thủ công? Tôi nghĩ rằng, khoảng một năm trước. Câu chuyện dài: sử dụng trình bao bọc này!
nmit026

29

Bạn có thể sử dụng phương thức Elmah.ErrorSignal () để ghi lại một vấn đề mà không đưa ra một ngoại lệ.

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

    // Continue
}


14

Vâng, nó là có thể. ELMAH được thiết kế để ngăn chặn các ngoại lệ chưa được xử lý. Tuy nhiên, bạn có thể báo hiệu một ngoại lệ đối với ELMAH thông qua lớp ErrorSignal. Những trường hợp ngoại lệ đó không bị ném (không nổi bong bóng), mà chỉ được gửi tới ELMAH (và cho những người đăng ký sự kiện Raise của lớp ErrorSignal).

Một ví dụ nhỏ:

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

13

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

Trong tệp 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 được cung cấp ở trên, nhưng không có HTTPContext), bạn có thể chuyển null thay vì một HTTPContext:

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

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 "bằng Elmah;" trong mã của tôi, nhưng nó không tồn tại trong bối cảnh hiện tại của tôi.
Táo khuyết

@Taersious Bạn packages.configtrông như thế nào? Bạn có thấy một cái gì đó như : <package id="elmah" version="1.2.2" targetFramework="net45" /> <package id="elmah.corelibrary" version="1.2.2" targetFramework="net45" /> <package id="elmah.sqlserver" version="1.2" targetFramework="net45" />'? Bạn đã cài đặt với NuGET?
Matthew

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 bằng tay từ tệp cấu hình mẫu trong dự án.
Taersious

@Taersious Nếu thực hiện thủ công, bạn đã thêm tham chiếu Elmah vào dự án trước khi gọi sử dụng ... Tôi sẽ hy vọng nó hoạt động theo cách nào đó, nhưng tôi biết rằng khi nuget thêm nó, các dòng trên được thêm vàopackages.config
Matthew

3

Đôi khi CurrentHttpContextcó thể không có sẵn.

Định nghĩa

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);
        }
    }
}

2

Tôi đang trên lõi ASP.NET và tôi sử dụng ElmahCore .

Để tự ghi nhật ký lỗi với HttpContext (trong bộ điều khiển), chỉ cần viết:

using ElmahCore;
...
HttpContext.RiseError(new Exception("Your Exception"));

Trong một phần khác của ứng dụng của bạn mà không có HTTPContext :

using ElmahCore;
...
ElmahExtensions.RiseError(new Exception("Your Exception"));

0

Tôi đã cố gắng viết các thông điệp tùy chỉnh vào nhật ký elmah bằng cách sử dụng Signal.FromCienContext (). Raise (ex); và thấy rằng những ngoại lệ này được nổi lên, ví dụ:

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

Ngoài ra, tôi không thấy elmah hỗ trợ các mức ghi nhật ký khác nhau như thế nào - có thể tắt ghi nhật ký chi tiết bằng cài đặt web.config không?


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

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

0

Đã sử dụng dòng này và nó hoạt động hoàn toàn tốt.

 try{
            //Code which may throw an error
    }
    catch(Exception ex){
            ErrorLog.GetDefault(HttpContext.Current).Log(new Elmah.Error(ex));
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.