Как использовать 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);
}
Это имеет следующие преимущества:
- Вам не нужно помнить этот слегка архаичный синтаксис вызова Эльмы
- Если у вас много DLL, вам не нужно ссылаться на Elmah Core из каждой отдельной библиотеки - и просто поместите это в свою собственную "Системную" DLL.
- Если вам когда-либо понадобится выполнить какую-либо специальную обработку или просто захотите поставить точку останова для отладки ошибок, у вас все это в одном месте.
- Если вы когда-нибудь отойдете от Эльмы, вы можете просто поменять одно место.
- Если у вас есть устаревшая регистрация ошибок, которую вы хотите сохранить (у меня просто есть простой механизм регистрации ошибок, связанный с некоторыми пользовательскими интерфейсами, которые я не могу сразу удалить).
Примечание. Я добавил свойство 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);
}
Я использую ядро ASP.NET и использую ElmahCore.
Чтобы вручную регистрировать ошибки с помощью HttpContext (в контроллере), просто напишите:
using ElmahCore;
...
HttpContext.RiseError(new Exception("Your Exception"));
В другой части вашего приложения без HttpContext:
using ElmahCore;
...
ElmahExtensions.RiseError(new Exception("Your Exception"));
Да, это возможно. 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);
}
}
}
Использовал эту строку, и она отлично работает.
try{
//Code which may throw an error
}
catch(Exception ex){
ErrorLog.GetDefault(HttpContext.Current).Log(new Elmah.Error(ex));
}
Я пытался записать пользовательские сообщения в журналы elmah, используя Signal.FromCurrentContext().Raise(ex); и обнаружил, что эти исключения всплывают, например:
try
{
...
}
catch (Exception ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
// this will write to the log AND throw the exception
}
Кроме того, я не понимаю, как elmah поддерживает разные уровни ведения журнала - возможно ли отключить подробное ведение журнала настройкой web.config?