Elmah — это очень полезный инструмент протоколирования ошибок веб-приложения ASP.NET. Часто можно услышать вопрос: что лучше использовать — Elmah или библиотеку логгинга (например, log4net)? Чтобы ответить на этот вопрос, нужно понять какие функции выполняет каждый из эти инструментов. Основные функции Elmah:
- logging (протоколирование) — логгирование ошибок со всей сопутствующей информацией;
- reporting (отчетность) — предоставление информации об ошибках пользователю в удобном для чтения виде;
- notification (уведомление) — уведомление пользователя о случившейся ошибке.
В качестве примера библиотеки логгинга в этом вопросе используется log4net, так что в дальнейшем повествовании понятия «log4net» и «библиотека логгинга» употребляются как синонимы. Итак, основная функция log4net только одна:
- logging — протоколирование событий, происходящих в приложении;
Из приведенных списков видно, что log4net не обладает многими возможностями Elmah:
- log4net не решает задачу reporting`а. Библиотека логгинга просто сохраняет протокол событий в определенном хранилище и не заботится об удобном представлении этого протокола пользователю. Доступные средства просмотра логов также не обеспечивают требуемого удобства, потому что они не предназначены для представления веб-специфичных параметров.
- log4net не решает задачу уведомления пользователя об ошибке. Можно, конечно, использовать appender, отсылающий UDP пакеты или написать свой, но изначально log4net не предназначен для решения таких задач.
Кажется, что log4net отстает по всем пунктам. Но, с другой стороны, Elmah покрывает задачу логгинга не полностью. Ведь в протокол попадают только ошибки
, в то время как в приложении может понадобиться следить за логикой последовательной работы нескольких систем и протоколировать множество дополнительной информации. log4net же поддерживает сообщения разных уровней — DEBUG, INFO, WARN, ERROR, FATAL. Покрытие задач протоколирования разными инструментами можно представить таким рисунком:
Из рисунка видно, что и Elmah и log4net выполняют определенные, важные для приложения функции. Отсюда следует что эти инструменты не должны конкурировать, а должны использоваться совместно. При этом каждый из инструментов будет выполнять свои специфические функции. Однако, в их функциональности есть перекрытие — это «протоколирование ошибок». Именно в рамках этой функциональности должно происходить взаимодействие Elmah и log4net.
Elmah отслеживает все необработанные исключения, в то время как log4net протоколирует только исключения, указанные пользователем. Для log4net характерны конструкции вида
try
{
// ...
}
catch(Exception ex)
{
log.Error("Error message", ex)
}
Как сделать так, чтобы все ошибки, переданные в log4net автоматически сохранялись в логах Elmah? Как известно, Elmah предоставляет возможность ручного указания ошибки для логгирования:
var context = ErrorSignal.FromCurrentContext();
context.Raise(anyExceptionObject);
Можно написать свой appender, который будет использовать эту возможность:
public class ElmahAppender : IAppender
{
public string Name { get; set; }
public void Close()
{
}
public void DoAppend(LoggingEvent loggingEvent)
{
if (loggingEvent.ExceptionObject != null)
{
var context = ErrorSignal.FromCurrentContext();
if (context != null)
{
context.Raise(loggingEvent.ExceptionObject);
}
}
}
}
Теперь если в конфигурации log4net объявить этот appender, то все исключения, передаваемые в методы логгеров будут автоматически записываться в протоколы Elmah. А значит оба инструмента будут работать совмместно и каждый будет выполнять только свои специфические задачи.
большое спасибо за статью. Есть только один комментарий: ваша подход с аппендером, в общем то, неплох, но я бы написал свой класс логирования, внутри которого бы уже использовал log4net и elmah - чтобы в случае, если придется отказаться от log4net - это не повлияло на код использования elmach и наоборот.
Да, вполне разумно. Но я обычно использую
Common.Logging
как обертку над конкретным инструментом логгинга (типа log4net).Common.Logging
— это такая абстракция, которая позволяет не привязываться к какой-то определенной библиотеке и легко переключаться между скажем log4net, NLog и простым выводом на консоль. Функционально это тоже что собственный класс логгирования, только его не нужно в каждом проекте писать заново).Вот о нем (Common.Logging) бы следующую статью написать, не знал.
log4net иcпользую достаточно давно - очень динамичный инструмент. с недавних пор пробую elmah (в проекте вместе с log4net). долго думал какой из них лучше, но вы ясно дали ответ на этот вопрос.
спасибо.