Как использовать ELMAH для ручного регистрации ошибок
можно ли сделать следующее С помощью ELMAH?
logger.Log(" something");
Я делаю что-то вроде этого:
try
{
// Code that might throw an exception
}
catch(Exception ex)
{
// I need to log error here...
}
это исключение не будет автоматически регистрироваться ELMAH, потому что оно было обработано.
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 }
Да, это возможно. 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 поддерживает разные уровни ведения журнала - можно ли отключить подробное ведение журнала с помощью интернета.настройка конфигурации?