Подключение
Web Application
- Добавить log4net.dll в References приложения
- Добавить в
AssemblyInfo.cs
строку[assembly: log4net.Config.XmlConfigurator(Watch = true)]
Web Site
Просто переписать log4net.dll в каталог Bin
Настройка
Логгер настраивается в web.Config. Вначале в раздел configSections следует добавить строчку:
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net">
Затем, нужно добавить раздел:
<log4net debug="true"> ... </log4net>
В этом разделе идет основная настройка логгера. В разделе могут быть потомки типа appender, logger и root. Назначение элемента logger пока что осталось для меня загадкой, так что рассмотрим остальные.
Appender
Для того, чтобы заставить log4net что-то куда-то писать, нужно определить Appender. Подходящее русское обозначение мне придумать не удалось, но суть в том, что он хранит настройки одного логгера. Типов appender-ов существует много (см. документацию), но мне довелось работать только с RollingFileAppender
, который определяет логгер, пишущий в файл. Другие типы appender-ов позволяют писать в базу данных(AdoNetAppender
), Windows EventLog (EventLogAppender
) и т.д. Рассмотрим пример:
<appender name="ERRORFileAppender" type="log4net.Appender.RollingFileAppender"> <lockingmodel type="log4net.Appender.FileAppender+MinimalLock"/> <file value="\Logs\errors.log" /> <appendtofile value="true" /> <rollingstyle value="Size" /> <maxsizerollbackups value="10" /> <maximumfilesize value="200MB" /> <staticlogfilename value="true" /> <filter> ... </filter> <layout> ... </layout> </appender>
Назначение перечисленных Appender-а, в принципе, понятно. Следует отметить параметр lockingModel
и его значение MinimalLock
. Дело в том, что log4net во время работы приложения жестко лочит файл с логом, его нельзя ни открыть (разве что редактором Far-а), ни удалить. Поэтому, если очень хочется удалить лог web-приложения, нужно перезапускать IIS, что не есть хорошо. Данная настройка "разлочивает" лог, его свободно можно удалять и открывать хоть для записи.
Ключевыми настройками Appender-а являются Filter и Layout.
Filter
Данная настройка позволяет отфильтровывать сообщения по некоторому признаку. Для фильтра обязательно указывается тип. Существует несколько типов фильтров, можно также писать свои. Наиболее часто используемые фильтры - по типу сообщения (LevelRangeFilter
и LevelMatchFilter
) и по тексту сообщения (StringMatchFilter
). Для начала, остановимся на типах (уровнях) сообщений. Сообщения в log4net делятся на несколько уровней:
- ALL
- DEBUG
- INFO
- WARN
- ERROR
- FATAL
- OFF
Разработчик выбирает, какой тип сообщений в каком случае ему использовать. Логгер же можно настроить таким образом, чтобы, к примеру, ошибки выводились отдельно, а отладочные данные - отдельно. Для это и пишутся фильтры. Рассмотрим на примерах.
Фильтр, выбирающий только ошибочные и фатальные сообщения:
<filter type="log4net.Filter.LevelRangeFilter"> <levelMin value="ERROR"/> <levelMax value="FATAL"/> </filter>
Фильтр, выбирающий только отладочные сообщения
<filter type="log4net.Filter.LevelMatchFilter"> <levelToMatch value="DEBUG"/> <acceptOnMatch value="true"/> </filter>
Layout
В разделе Layout определяется формат вывода сообщений в файл. Как ранее было сказано, log4net, помимо самого сообщения, может выводить кучу полезной информации. Layout может выглядеть, например, таким образом:
<layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%-5p [%d] [%C.%M] %m%n"/> </layout>
В conversionPattern указано, какие значения и в каком формате будут выводиться в лог. Выходной лог с таким Layout-ом получится примерно таким:
DEBUG [2008-04-08 17:45:14,662] [TableTemplates.GetTemplate] Is visible: [visible]
DEBUG [2008-04-08 17:45:14,662] [TableTemplates.GetTemplate] Report Footer (rows:1)
DEBUG [2008-04-08 17:45:14,662] [TableTemplates.GetTemplate] Number of cells in row [2]
INFO [2008-04-08 17:45:14,663] [ClientDataObjects.get_ClientObjects] Client object found in session
Значения ключей conversionPattern:
%p
— Тип события лога (DEBUG, ERROR и т.д.)%d
— Дата и время, когда логгирующая функция была вызвана. Можно задавать различные форматы вывода даты и времени. К примеру,%d{HH:mm:ss,SSS}
отображает только время%C
— Имя класса, в котором была вызвана какая-либо функция лога%M
— Имя метода%m
— Собственно, сообщение в лог%F
— Имя файла%l
— Номер строки%r
— Количество миллисекунд, прошедших с начала работы программы%t
— Имя потока%n
— Переход на новую строку%%
— Символ"%"
Root
Написать Appender-ы недостаточно для того, чтобы log4net начал писать логи. Нужно еще зарегистрировать их в корне лога, вот таким вот образом:
<root> <level value="WARN" /> <appender-ref ref="ERRORFileAppender" /> <appender-ref ref="DEBUGFileAppender" /> </root>
level
- уровень, сообщения ниже которого не выводятся ни в один лог. Приведенная запись значит, что в логи не будут выводиться сообщения типа DEBUG и INFO.
Использование
Я делаю так. Пишу класс:
using log4net; using log4net.Config; using System; /// /// Logger - shell for log4net logger /// public static class Logger { private static readonly ILog log = LogManager.GetLogger(typeof(Logger)); public static ILog Log { get { return log; } } public static void InitLogger() { XmlConfigurator.Configure(); } }
Потом в Global.asax в метод Application_Start добавляю строчку:
Logger.InitLogger();
И подключение лога в код готово. После этого в любом месте кода можно написать что-то вроде:
Logger.Log.Debug("Some message");
ILog
представляет различные методы для вывода сообщений различных типов. Рассмотрим некоторые методы:
Функции | Описание | Пример |
---|---|---|
Info(String message) Debug(String message) Warn(String message) Error(String message) Fatal(String message) |
Вывод в лог сообщения message
|
Logger.Log.Info("Sample log message"); |
InfoFormat(String format, params object[] args) DebugFormat(String format, params object[] args) WarnFormat(String format, params object[] args) ErrorFormat(String format, params object[] args) FatalFormat(String format, params object[] args) |
Вывод в лог сообщения c параметрами. Аналогично выводу сообщения String.Format(format, args) .
|
Logger.Log.DebugFormat("Key={0}, Value={1}", key, value); |
Info(String message, Exception e) Debug(String message, Exception e) Warn(String message, Exception e) Error(String message, Exception e) Fatal(String message, Exception e) |
Вывод в лог сообщения с исключением. В лог помещается целиком текст исключения и stack trace. |
try { a = b / c; } catch (Exception e) { Logger.Log.Error("Exception catched while calculation.", e); } |
42 комментария:
спасибо хорошая статья для быстрого старта )
Рада, что Вам она оказалось полезной
Спасибо Даша!
Привет, Даша. Хорошая статья для начала, мне понравилось.
Вопрос: ты знаешь, как заставить log4net создавать лог-файлы для каждого экземпляра интерфейса ILog?
Т.е. есть у меня
static log4net.ILog log = log4net.LogManager.GetLogger("My_mega_logger");
Теперь я хочу, чтобы лог-файл назывался "log_My_mega_logger.log".
Отлично написала, легонькие повествование, мне понравилось.
Тебе нужно книжки писать!
Ой, ссылка на документацию поломалась. Вот и пример, почему вредны ссылки типа "тут" и "здесь".
2 pylnik:
Леша, ты ли это? :) Я тебе развернутый ответ написала отдельным постом
2 Paul D.
Спасибо :) Может, когда и возьмусь
Возмись) Я вот второй раз твоим блог пользуюсь) с первого раза не запомнил)
Привет!
Есть вопрос по теме. Я писал обычно на C++, поэтому многое в C# в новинку, особенно обилие пространств. Хочу использовать log4net в своём .NET 3.5-приложении, но не понимаю, как подключить эту библиотеку. И ещё не понял какие пространства нужны интерфейсы ILog. Подскажи, пожалуйста :)
2 andrej-b
В любом проекте на .NET есть такая штука References (Видна в иерархии проекта). Туда заносятся ссылки на используемые в проекте сборки. Так вот, чтобы использовать log4net, нужно сначала подключить соответствующую библиотеку к проекту. Для этого нужно сделать Add Reference -> Browse и указать dll-ку с log4net. После этого станет можно подключать пространства имен из этой сборки и использовать классы.
ILog находится в пространстве имен log4net. Кстати, using-и для пространств имен Студия умеет генерить сама.
Я ответила на Ваш вопрос?
darja, спасибо! В принципе это понимаю, просто думал, что log4net.dll это какая-то стандартная библиотека. Но насколько я понял, она не стандартная и её надо надыбать где-то.
Извиняюсь за нозойливость :) но где найти описание тэгов конфигурационного файла log4net? Покопался, нашёл log4net SDK Reference, но не нашёл там ответ на свой вопрос. Не подскажешь?
2 andrej-b
тут можно скачать log4net
документация по конфигу
Надо сказать, документация так себе, так что кое-что приходилось узнавать по блогам и исходникам самого log4net
Спасибо, прикрутила себе.
Единственный комментарий - инициализацию можно сделать прямо в статическом конструкторе класса Logger, а не в Global.asax
Спасибо.
Хорошая заметка.
Отличная статья!!! Спасибо большое!
Хорошая статья.
Скажите, Дарья, а есть возможность писать лог каждый день в новый файл?
Что бы частью имени файла была дата?
При больших количествах сообщений найти что-то в одном файле за пару месяцев просто не реально.
Хорошая статья. Русcкоязычных материалов по log4net не так уж и много...
Всем спасибо за отзывы!
2 Анонимный (который предпоследний)
Наконец-то руки дошли Вам написать ответ. Вот он: http://megadarja.blogspot.com/2009/08/log4net.html
Большое спасибо!
А читать и парсить он может из своих файлов?
2 Roman:
А вот это вряд ли. Разбирать текст - это уже не задача логгера. Для этого есть Perl.
Добрый день, Дарья. Спасибо за статью. А как можно логгировать все исключения(даже те, которые не перехватываются)?
Премного благодарен за такой труд.
С вашего блога быстренько удалось разобраться с log4net. Детали смотрел в мануалах родных, но было уже значительно проще. Спасибо :)
Спасибо большое за статью, все просто и понятно
О спасибо вам, вы спасли мои нервы
Дашуля - умничко! :)
спасибо большое за заметку
Замечательная и полезная статья!
Спасибо, как раз появилась необходимость логи писать в очередной раз, решил вместо своих велосипедов что-то попробовать из имеющегося.
добавлю про полезную (imho) возможность, вести отдельные секции логгирования (в добавок к root):
‹logger name="Какая-то-Секция"›
‹level value="WARNING" /›
‹appender-ref ref="Какой-то Appender /›
‹/logger›
в коде, соответственно, создаем отдельный экземпляр
private static readonly ILog log = LogManager.GetLogger("Какая-то-Секция");
У меня вопрос: не подскажете, почему у меня с ошибками создается файл логов. Но не один, а несколько! причем изменяться могут все одновременно, могут по разному... в чем прикол?
2Vera.
Думаю, что без текста ошибки говорить о чём-то конкретном сложно.
Однажды мне пришлось долго повозиться с тем, что Lucene временами не могла создавать/удалять свои lock-файлы. Выяснилось, что файлы блокировал антивирус.
Я неправильно расставила акценты в своем вопросе. Ошибки - да, без них никак. Они обычные.. То доступа в базу нет, то запись не найдена, то еще что-то. Не в этом суть.
А в том, что сначала он создает один файл с именем errors_2010_10_12.log,
затем в какой-то момент начинает писать в файл errors_2010_10_12.log.log.
Потом пишеть одновременно и там, и там...
я думала сначала, что идет ограничение на размер лога, но нет... один файл - около 1,5 мб, второй - перевалил за 20...
сделал все как описано в статье, но почему-то у меня не получилось сделать так чтобы лог файл сохранялся по пути который указан в примере. Сделал так что пишет в файл в корневой папке.
И еще вылезла следующая проблема - в лог файле вместо текста собщений -- "??"
подскажите где искать ошибку..
Добрый день. Мне очень помогла Ваша статья когда я начал создавать логгер для моей аппликации.
Но у меня возникло ряд проблем.
1. Не могу программно задать maximumFileSize, обшарил весь инет. Сделал по аналогии с установкой "LogName" но это не работает.
XML
C#
log4net.GlobalContext.Properties["MSize"] = max_size;
XmlConfigurator.Configure();
2. Можно ли задать фильтр в котором вывод сообщений осуществляется свободным списком (например DEBUG, WARN и FATAL) а не через levelMin и levelMin?
1. Посмотрела в исходники -- вроде есть у RollingFileAppender-а такое свойство MaxFileSize. Другое дело, зачем его задавать программно.
2. Можно свой написать, это несложно. У меня даже где-то статья про это есть.
1 Ну здесь довольно просто. Необходимо дать возможность менять размер и количество файлов конечному пользователю в зависимости от возможностей его компа (дисковое пространство например).
2. Как сделать свободный список я разобрался но опять проблема. Как его менять динамически. Нет надобности забивать лог до того как произойдет сбой. А вот когда он произошел хорошо бы потом протестировать машину с полным логом включая нажатие всех кнопок на форме и всех других действий пользователя..
Короче хотелось бы понять как можно программно менять любой из описных в статье параметров.
у меня, почему-то форматирование не проходит вообще. сконфигурировал форматирование как показано в статье(а потом пошарил по документации и сконфигил по ней), а формат один и тот жэ, думаю. дефолтовый.
можете, пожалуста помочь?
если кому понадобится:
в конфиге был прописан копипаст с нераспознаными символами перед началом тэгов, никакого странного поведения логгер не проявлял, просто писал в дефолтовом фомрате. проверив в другом текстовом редакторе (не в VS) заметил подвох, стёр символы, начало работать отлично.
Спасибо за статью, все просто и понятно.
У меня вопрос.
Можно ли в conversionPattern задать ключ имени файла без полного пути? %F, %file - выводит полный путь.
У меня тоже проблема с "??". Помогите, пожалуйста.
Максим Т комментирует...
И еще вылезла следующая проблема - в лог файле вместо текста собщений -- "??"
подскажите где искать ошибку..
Отправить комментарий