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

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

logger.Log(" something");

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

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

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



답변

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 구독 기반이며 여러 로거에 하나의 예외를 기록 할 수 있습니다.

답변

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가 표시됩니다.


답변

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

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

    // Continue
}


답변

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


답변

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

작은 예 :

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


답변

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


답변

때로는 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);
        }
    }
}