Как использовать ELMAH для ручного регистрации ошибок


можно ли сделать следующее С помощью ELMAH?

logger.Log(" something");

Я делаю что-то вроде этого:

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

это исключение не будет автоматически регистрироваться ELMAH, потому что оно было обработано.

8 250

8 ответов:

прямой метод записи журнала, работающий с 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, вам не нужно ссылаться на ядро Elmah из каждого из них - и просто поместите это в свою собственную DLL "System".
  • если вам когда-нибудь понадобится сделать какую-либо специальную обработку или просто хотите поставить точку останова для отладки ошибок у вас есть все это в одном месте.
  • если вы когда-нибудь отойдете от Elmah, вы можете просто изменить одно место.
  • если у вас есть устаревший журнал ошибок, который вы хотите сохранить (у меня просто есть простой механизм регистрации ошибок, который привязан к некоторым UIs, которые я не сразу успеваю удалить).

Примечание: я добавил свойство '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 был разработан для перехвата необработанных исключений. Однако вы можете сигнализировать об исключении для ELMAH через класс ErrorSignal. Эти исключения не выбрасываются (не всплывают), а только отправляются в ELMAH (и подписчикам события Raise класса ErrorSignal).

маленький пример:

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

Я искал, чтобы сделать то же самое в потоке я начал очередь почты из моего приложения MVC4, как таковой у меня не было HttpContext доступны при возникновении исключения. Для этого я получил следующее на основе этого вопроса и другого ответа, найденного здесь:elmah: исключения без HttpContext?

в конфигурационном файле я указал имя приложения:

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

затем в коде (как и ответ, приведенный выше, но без контекста HttpContext) можно передать значение null, а не объект HttpContext:

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

Я пытался писать пользовательские сообщения в журналы elmah с помощью сигнала.FromCurrentContext ().Raise (ex); и обнаружил, что эти исключения пузырятся, например:

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

кроме того, я не вижу, как elmah поддерживает разные уровни ведения журнала - можно ли отключить подробное ведение журнала с помощью интернета.настройка конфигурации?