ELMAH를 사용하여 수동으로 오류를 기록하는 방법


259

ELMAH를 사용하여 다음을 수행 할 수 있습니까?

logger.Log(" something");

나는 이런 식으로하고있다 :

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

이 예외는 처리 되었기 때문에 ELMAH에 의해 자동으로 기록되지 않습니다.


1
나중에 참조하기 위해 정확히 다음과 같은 게시물을 작성했습니다 . 프로그래밍 방식으로 오류 기록 . 내 ELMAH 튜토리얼 이에 대한 몇 가지 정보가 있습니다.
ThomasArdal

답변:


412

ELMAH 1.0부터 작동하는 직접 로그 작성 방법 :

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

ELMAH 1.2는보다 유연한 API를 도입했습니다.

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

두 솔루션 간에는 차이점이 있습니다.

  • Raise메소드는 ELMAH 필터링 규칙을 예외에 적용합니다. Log방법은하지 않습니다.
  • Raise 구독 기반이며 여러 로거에 하나의 예외를 기록 할 수 있습니다.

1
방법과 다른 방법의 차이점은 무엇입니까?
Omu

3
이들은 응용 프로그램의 작동을 중지시키지 않으면 서 Elmah에 오류를 기록합니다. 일반적인 예외를 잡아서 올바르게 처리 할 수는 있지만 여전히 기록 할 수 있습니다.
PCasagrande

7
POST back에 Mvc4 .Net 4.5에 대해 안전하지 않은 Html이 포함되어있을 때 Elmah.ErrorSignal이 로깅되지 않는 것으로 나타났습니다. Elmah.ErrorLog.GetDefault는이 시나리오에서 작동했습니다
Adam

1
안전하지 않은 HTML과 동일한 문제가있었습니다. ErrorLog.GetDefault가 트릭을 수행했습니다
22:44에

4
사용시 하나의 큰주의 사항 Elmah.ErrorLog.Log(): 로그 호출 자체가 실패하면 전체 웹 응용 프로그램을 중단시킬 수 있습니다. Raise()조용히 실패합니다. 예를 들어, 서버 측에 잘못된 구성 문제가있는 경우 (예 : Elmah가 디스크에 오류를 저장하도록 구성되어 있지만 logs 폴더에 대한 올바른 액세스 권한이없는 경우) .Log()메소드가 발생합니다. (이것은 디버깅에 좋습니다. 왜 .Raise()아무것도 기록 하지 않습니까?)
Cristian Diaconescu

91

Elmah에 대한 호출을 간단한 래퍼 클래스로 래핑하는 것이 좋습니다.

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

그런 다음 오류를 기록해야 할 때마다 호출하십시오.

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

다음과 같은 이점이 있습니다.

  • Elmah 호출의 약간 구식 구문을 기억할 필요는 없습니다.
  • 많은 DLL이있는 경우 모든 단일 DLL에서 Elmah Core를 참조 할 필요가 없으며이를 자신의 '시스템'DLL에 넣으십시오.
  • 특별한 처리가 필요하거나 오류를 디버그하기 위해 중단 점을 두려는 경우 한곳에 모두 있습니다.
  • Elmah에서 멀어지면 한 곳만 변경할 수 있습니다.
  • 레거시 오류 로깅이있는 경우 유지하려고합니다 (단순히 제거 할 시간이없는 일부 UI에 묶여있는 간단한 오류 로깅 메커니즘이 생겼습니다).

참고 : 컨텍스트 정보를 위해 'contextualMessage'속성을 추가했습니다. 원하는 경우 이것을 생략 할 수 있지만 매우 유용합니다. Elmah는 예외를 자동으로 풀기 때문에 기본 예외는 여전히 로그에보고되지만이를 클릭하면 contextualMessage가 표시됩니다.


1
좋은 대답입니다. ELMAH는 상자에서 비슷한 것을 구현해야 할 수도 있습니다. 때로는 컨텍스트없이 오류를 디버깅하기가 실제로 어렵습니다.
ra00l

2
와 함께 보조 오류를 삼키는 것을 제외하고는 모두 좋아합니다 // uh oh! just keep going. 내 오류 처리가 실패하면 알고 싶습니다. 나는 약간의 소음을 내고 싶다.
Jeremy Cook

3
@JeremyCook 동의하지만, 조심하지 않으면 오류 처리 루틴이 실패하면 스스로 호출 한 다음 폭파하는 경향이 있습니다 (오, 실제로 오류를 기록하기 위해 제 3 자 API를 호출했습니다). 아마이 답변을 위해 이것을 남겨 두지 말았어야하지만 이전에 그런 일에 대해 나쁜 경험을했을 것입니다
Simon_Weaver

1
확장 방법으로 더 좋을 것입니다.
Stephen Kennedy

1
당신은 생각할 수 있습니다 : 아, 몇 번의 수동 오류를 기록하려고 할 수 있습니까? 나는 약 1 년 전에 그것을 생각했습니다. 간단히 말해 :이 래퍼를 사용하십시오!
nmit026

29

Elmah.ErrorSignal () 메서드를 사용하면 예외를 발생시키지 않고 문제를 기록 할 수 있습니다.

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

    // Continue
}


14

네 가능합니다. ELMAH는 처리되지 않은 예외를 차단하도록 설계되었습니다. 그러나 ErrorSignal 클래스를 통해 ELMAH에 예외 신호를 보낼 수 있습니다. 이러한 예외는 발생하지 않으며 (버블 링하지 않음) ELMAH (및 ErrorSignal 클래스의 Raise 이벤트 구독자)에게만 전송됩니다.

작은 예 :

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

13

MVC4 응용 프로그램 내에서 메일을 대기열에 넣기 시작한 스레드에서 이와 동일한 작업을 수행하려고했습니다. 예외가 발생할 때 HttpContext를 사용할 수 없었습니다. 이렇게하려면이 질문과 여기에있는 다른 대답을 기반으로 다음과 같은 결과를 얻었 습니다. elmah : HttpContext without exceptions?

구성 파일에서 응용 프로그램 이름을 지정했습니다.

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

그런 다음 코드에서 (위의 답변과 같지만 HttpContext가없는) HttpContext 대신 null을 전달할 수 있습니다.

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

나는 당신의 해결책을 좋아합니다; 그러나 "Elmah"를 해결할 수 없습니다. 내 프로젝트에서. "Elmah 사용"을 추가하려고했습니다. 내 코드에는 있지만 현재 컨텍스트에는 존재하지 않습니다.
Taersious

@Taersious 당신의 packages.config모습은 어떻습니까? 다음과 같은 것이 보 <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" />'입니까? NuGET으로 설치 했습니까?
Matthew

예라고 말하고 싶지만 현재 프로젝트가 소스 제어로 잠겨 있습니다. 프로젝트의 샘플 구성 파일에서 elmah를 수동으로 구현했습니다.
Taersious

@Taersious 수동으로 수행하는 경우, 사용하기 전에 Elmah 참조를 프로젝트에 추가 했습니까? 어느 쪽이든 작동 할 것으로 예상되지만, nuget이 추가 할 때 위의 행이packages.config
Matthew

3

때로는 CurrentHttpContext사용하지 못할 수 있습니다.

밝히다

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 { }
    }
}

사용하다

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

나는 오전 ASP.NET 코어 및 I 사용 ElmahCore을 .

컨트롤러에서 HttpContext로 오류를 수동으로 기록하려면 다음 과 같이 작성하십시오.

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

HttpContext가없는 응용 프로그램의 다른 부분 :

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

0

Signal.FromCurrentContext (). Raise (ex);를 사용하여 elmah 로그에 사용자 정의 메시지를 쓰려고했습니다. 다음과 같은 예외가 발생했음을 발견했습니다. 예 :

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

또한 elmah가 다양한 수준의 로깅을 지원하는 방법을 알 수 없습니다. web.config 설정으로 자세한 로깅을 해제 할 수 있습니까?


1
예외를 잡아서 다시 던지지 않으면 예외가 발생하지 않습니다. 어쩌면 내가 오해 할까? ELMAH는 다른 수준의 로깅을 지원하지 않습니다. 오류 전용입니다.
ThomasArdal

고마워 토마스 그것이 바로 내가 확인하려고 한 것입니다
Valery Gavrilov

0

이 줄을 사용하면 완벽하게 작동합니다.

 try{
            //Code which may throw an error
    }
    catch(Exception ex){
            ErrorLog.GetDefault(HttpContext.Current).Log(new Elmah.Error(ex));
    }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.