Подключаем log4net. Пошаговая инструкция

Как ни странно, но оказалось, что пошаговой инструкции для такой популярной библиотеки, как log4net, еще нет на Хабре. Исправляю эту недоработку.

Подключаем Nuget-пакет


Правой клавишей на References и выбираем Manage Nuget Packages:

image

В поисковой строке набираем log4net и находим пакет (в выдаче на первом месте):

image

Жмём кнопку «Install» и после установки пакета закрываем окно.

Создаем класс — обработчик.


Добавляем новый класс:

image

И называем его Logger:

image

Добавляем следующий код:

public static class Logger
    {
        private static ILog log = LogManager.GetLogger("LOGGER");


        public static ILog Log
        {
            get { return log; }
        }

        public static void InitLogger()
        {
            XmlConfigurator.Configure();
        }
    }

Не забудьте поставить ссылку на сборки в начале файла:

using log4net;
using log4net.Config;

Настраиваем конфиг


Теперь переходим к конфигу. В файле конфигурации App.config (или Web.config — если у вас это веб приложение) нужно внутри секции configuration добавить секцию log4net со следующим содержимым:

 <log4net>
    <appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
      <param name="File" value="Logs\Example.log"/>
      <param name="AppendToFile" value="true"/>
      <maxSizeRollBackups value="10"/>
      <maximumFileSize value="5MB"/>
      <lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
      <layout type="log4net.Layout.PatternLayout">
        <param name="ConversionPattern" value="%d  %-5p %m%n"/>
      </layout>

    </appender>

    <logger name="LOGGER">
      <appender-ref ref="LogFileAppender"/>
    </logger>
  </log4net>

И сразу же после секции configuration должна стоять секция configSections, если её нет — добавьте (она должна быть первой) и внутри неё добавьте код для log4net. Если она одна — то выглядеть должно так:

   <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net, Version=1.2.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a" />
  </configSections>   

Полностью конфиг у меня выглядит так:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
   <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net, Version=1.2.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a" />
  </configSections>   
  <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>

  <log4net>
    <appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
      <param name="File" value="Logs\Example.log"/>
      <param name="AppendToFile" value="true"/>
      <maxSizeRollBackups value="10"/>
      <maximumFileSize value="5MB"/>
      <lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
      <layout type="log4net.Layout.PatternLayout">
        <param name="ConversionPattern" value="%d  %-5p %m%n"/>
      </layout>

    </appender>

    <logger name="LOGGER">
      <appender-ref ref="LogFileAppender"/>
    </logger>
  </log4net>
</configuration>

Как видите имя логгера:

<logger name="LOGGER">

Совпадает с именем которое мы задали в классе Logger:

private static ILog log = LogManager.GetLogger("LOGGER");

По этому имени связывается конфиг с кодом класса-обработчика. Уже сейчас наш логгер готов к работе, просто добавьте следующий код:

Logger.InitLogger();//инициализация - требуется один раз в начале

Logger.Log.Info("Ура заработало!");

После запуска будет создана папка Logs и внутри будет файл Example.log с записью лога:

2016-09-21 10:59:41,104  INFO  Ура заработало!

Использование


Давайте немного изменим логику логирования. Выделим записи уровня Error и выше в отдельный файл (например отладочных записей у нас достаточно много и спам читать неудобно). Для этого добавим в конфиг следующее:

<appender name="ErrorFile" type="log4net.Appender.RollingFileAppender">
      <file value="Logs\Equifax_SenderError.log"/>
      <appendToFile value="true"/>
      <maximumFileSize value="5MB"/>
      <maxSizeRollBackups value="10"/>
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%level %thread %logger - %message%newline"/>
      </layout>
      <filter type="log4net.Filter.LevelRangeFilter">
        <levelMin value="ERROR"/>
        <levelMax value="FATAL"/>
      </filter>
    </appender>

B добавим ссылку на аппендер:

    <logger name="LOGGER">
      <appender-ref ref="LogFileAppender"/>
      <appender-ref ref="ErrorFile"/>
    </logger>

Теперь секция log4net выглядит так:

<log4net>
    <appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
      <param name="File" value="Logs\Example.log"/>
      <param name="AppendToFile" value="true"/>
      <maxSizeRollBackups value="10"/>
      <maximumFileSize value="5MB"/>
      <lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
      <layout type="log4net.Layout.PatternLayout">
        <param name="ConversionPattern" value="%d  %-5p %m%n"/>
      </layout>

    </appender>
    <appender name="ErrorFile" type="log4net.Appender.RollingFileAppender">
      <file value="Logs\ExampleError.log"/>
      <appendToFile value="true"/>
      <maximumFileSize value="5MB"/>
      <maxSizeRollBackups value="10"/>
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%d %level %thread %logger - %message%newline"/>
      </layout>
      <filter type="log4net.Filter.LevelRangeFilter">
        <levelMin value="ERROR"/>
        <levelMax value="FATAL"/>
      </filter>
    </appender>
    <logger name="LOGGER">
      <appender-ref ref="LogFileAppender"/>
      <appender-ref ref="ErrorFile"/>
    </logger>
  </log4net>

И если мы изменим код программы на:

            Logger.InitLogger();//инициализация - требуется один раз в начале
            Logger.Log.Info("Ура заработало!");
            Logger.Log.Error("Ошибочка вышла!");

То увидим что появился еще один файл ExampleError.log — в него будут выводиться только ошибки:

2016-09-21 11:14:58,933 ERROR 8 LOGGER - Ошибочка вышла!

Ну а за подробностями стоит обратиться к официальной документации. Спасибо за внимание!
Share post
AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 32

    +7
    Как ни странно, но оказалось, что пошаговой инструкции для такой популярной библиотеки, как log4net, еще нет на Хабре.

    На Хабре нужны пошаговые инструкции ко всем библиотекам? ;)
      0
      На самом деле для меня причиной был комментарий
      "… Уже давно собираюсь продвинуться на новую систему логирования, посмотрю в эту сторону, однако я люблю такие простенькие вещи писать полностью без дополнительных библиотек, в сложном проекте — конечно же буду ..."
      — поэтому и написал инструкцию для быстрого внедрения, для случая когда вдумываться особо некогда. да и не хочется…
        0
        Ну тут хоть объяснили как добавить логгер. Мне надо было добавить два разных логгера в программе, методом «тыка» полчаса разбирался :)

        В обычных статьях «Вот смотрите пишем в лог» и код типа
        private static ILog log = LogManager.GetLogger(«LogManager»);

        Думаешь «Агааа. Значит надо имя типа». А тут объяснили что имя логгера нужно указать.
        Когда поймешь различия в логерах и аппендерах все понятно, а поначалу не все так явно.

        p.s. Не, документацию не читал в тот момент.
          0
          Да нужны, как раз разбюираюсь в проекте в котором и log4net и Common.Logging и все заверчено и переверчено.
          В статье у автора все просто и понятно, с исложением от простого к сложному.
          Автору однозначно спасибо.
          0
          оно uwp умеет?
            0
            Врать не буду, не пробовал. Но интуитивно мне кажется что никаких сложностей быть не должно.
              0
              первая ссылка гугла говорит что нет
              http://stackoverflow.com/questions/32886613/logger-for-windows-10-uwp-app
                0
                как только столкнусь с uwp — обязательно попробую и напишу
              +4

              Слабоватая статья. Было бы интересней, например, читать о достоинствах и недостатках логгеров под .NET (log4net, NLog, Serilog и т.д.), а не об очередной реализации "Hello world" для логгера.

                0
                Порой программист начинает именно с реализации «Hello world» — кто знает, может для кого-то это станет первым шагом в использовании логгеров…
                  0
                  Ну основное преимущество NLog для обычного человека в том, что он все нужные файлы добавляет сам.
                  Включая сниппет для студии для более удобного использования, «nlogger».
                  –1
                  Вроде как весь прогрессивный мир использует Common.Logging как API логгирования.
                    0
                    Простите, но чем ваша статья отличается от документации по log4net на оф.сайте кроме картинок из VS?
                    Вот если бы вы описали методы решения проблем при работе с log4net, тогда статье не было цены. Особенно описание решения проблем с некорректным конфигом или нежелания библиотеки читать конфиг были бы очень полезны.
                      0
                      Частично я уже ответил на данный вопрос чуть выше, а отличие в том что можно по шагам воспроизвести инструкцию и пользоваться логом «здесь и сейчас».
                      Но за пожелания спасибо, я обязательно учту их в будущем.
                        +1

                        И зачем при живом serilog нужно это старье?

                          0
                          Вы можете озвучить преимущества serilog перед log4net?
                            +2

                            Структурное логирование.
                            Результат сразу имеет вид кортежа с именованными полями без дополнительных усилий, логировать можно напрямую в какой-нибудь Elastic Search без дорогого и косячного парсинга.
                            Это реально небо и земля.

                              –1
                              Вы имели в виду этот формат?

                              Ну да — он выводит данные в Json. Возможно это удобнее во многих случаях, но тот же log4net умеет писать напрямую во многие СУБД (MS SQL Server, Oracle, IBM DB2, SQLite), поддерживает протоколы tcp, smtp — кому-то это будет ближе.

                              А кому-то больше ничего и не надо — дело вкуса…
                                0

                                Вопрос не в конкретном формате вывода, а в том, что сообщение в serilog — это не просто строка, но строка плюс кортеж с именованными полями. Выходные данные структурированы сразу, а не после парсинга.
                                Это позволяет легко писать в любые базы данных.
                                Текстовые логи на этом фоне скорее вредны чем бесполезны.

                                  –1
                                  Это позволяет легко писать в любые базы данных.

                                  Да — конечно, особенно легко в NoSql.
                                  Но — вам все равно придется для этого писать код!

                                  Выходные данные структурированы сразу, а не после парсинга.

                                  В случае СУБД — отнюдь, там все прекрасно стурктуировано, и в конфиге вы сами определяете структуру.

                                  Текстовые логи на этом фоне скорее вредны чем бесполезны.

                                  Как я уже писал — это дело вкуса и конкретной ситуации…
                                    +1
                                    В случае СУБД — отнюдь, там все прекрасно стурктуировано, и в конфиге вы сами определяете структуру.

                                    И как вы будете поддерживать более одной структуры на весь лог?
                                    В serilog структура определяется самим сообщением плюс можно централизованно навесить дополнительные поля. В "старой школе" сообщение — всего лишь строка. Из serilog разные сообщения можно естественным сохранять в разные структуры, получая готовую базу для анализа. После log4net сообщения для извлечения информации надо парсить.

                                      0
                                      И как вы будете поддерживать более одной структуры на весь лог?

                                      Да — тут преимущества NoSql раскрываются во всей красе. Тут согласен целиком и полностью.
                                        0

                                        Наличие готовой структуры в сообщениях поможет и при сохранении в реляционную базу — ценой потери универсальности алгоритма записи. Но экономия по сравнению с вариантом "отформатировали в строку-распарсили" все равно колоссальная.

                                          0
                                          Но экономия по сравнению с вариантом «отформатировали в строку-распарсили» все равно колоссальная.

                                          При записи напрямую в СУБД никакого парсинга не происходит
                                            +1
                                            При записи напрямую в СУБД никакого парсинга не происходит

                                            И после log4net в базе оказывается строка вида "Куплено 6 единиц товара Бритва по цене 75 рублей за штуку". Для анализа по логам эту строку надо парсить.
                                            После serilog в таблице покупок добавится запись с полями:


                                            1. Count = 6
                                            2. Product = Бритва
                                            3. Price = 75

                                            Исходные данные для анализа в уже готовом виде, парсинг не нужен.

                                              0
                                              И после log4net в базе оказывается строка вида «Куплено 6 единиц товара Бритва по цене 75 рублей за штуку». Для анализа по логам эту строку надо парсить.

                                              Легко
                                              Logger.Log.Info($"Куплено {Count} единиц товара {Product} по цене {Price} рублей за штуку");
                                              
                                                0

                                                Это не парсинг, а форматирование строки. При парсинге нужно будет наоборот извлечь свойства Count, Product и Price из этой строки.

                                                  0
                                                  Да — конечно, после того как лог сформирован — однозначно.
                                                0
                                                Но в одном вы правы — после того как лог создан — для его анализа нужен парсинг. И для этой цели (анализа) намного удобнее serilog.
                                                  0

                                                  А учитывая, что лог нужен ТОЛЬКО для анализа...

                                                    0
                                                    Судя по вашей долгой дискуссии — вы по разному понимаете анализ. Грамотно сформированный лог в анализе не нуждается сам по себе, анализируют результаты записанные в лог. Что вам автор и пытается донести. Вы же пытаетесь доказать что лог впоследствии надо «анализировать» — а это не всегда так…
                            0
                            Мне инструкция понравилась — четко и по полочкам. Взял на вооружение.

                            Only users with full accounts can post comments. Log in, please.