воскресенье, 21 декабря 2008 г.

Еще про log4net

В комментариях к прошлой статье про log4net задал мне товарищ следующий вопрос:

Вопрос: ты знаешь, как заставить log4net создавать лог-файлы для каждого экземпляра интерфейса ILog?
Т.е. есть у меня
static log4net.ILog log = log4net.LogManager.GetLogger("My_mega_logger");
Теперь я хочу, чтобы лог-файл назывался "log_My_mega_logger.log".

Я подумала-подумала, да и придумала решение. Заодно, кажется, разгадала секрет, зачем в конфиге нужен элемент logger. Итак, вот что получилось.

Для примера я создаю консольное приложение, и цепляю в References библиотеку log4net.

App.config

Добавляем в проект конфигурационный файл и пишем в нем, например, такое

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
  </configSections>
  <log4net debug="true">
    <appender name="SomeAppender" type="log4net.Appender.RollingFileAppender">
      <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
      <file value="Logs\some.log" />
      ...
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%-5p [%d] [%M] %m%n" />
      </layout>
    </appender>
    <appender name="OtherAppender" type="log4net.Appender.RollingFileAppender">
      <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
      <file value="Logs\other.log" />
      ...
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%-5p [%d] [%M] %m%n" />
      </layout>
    </appender>
    <root>
      <level value="ALL" />
    </root>
    <logger name="SomeLogger">
      <level value="ALL" />
      <appender-ref ref="SomeAppender" />
    </logger>
    <logger name="OtherLogger">
      <level value="ALL" />
      <appender-ref ref="OtherAppender" />
    </logger>
  </log4net>
  <appSettings>
    <add key="log4net.Internal.Quiet" value="true" />
  </appSettings>
</configuration>

Т.е. мы определили два Appender-а, которые завязаны на разные файлы, и два Logger-а, которые по-разному называются и завязаны на соответствующие Appender-ы.

В приложении

Класс нашего консольного приложения может выглядеть так:

class Program
{
  private static readonly ILog someLog = LogManager.GetLogger("SomeLogger");
  private static readonly ILog otherLog = LogManager.GetLogger("OtherLogger");

  static void Main(string[] args)
  {
    XmlConfigurator.Configure();

    someLog.Debug("Some message");
    otherLog.Debug("Other message");
  }
}

Немного по-индийски, но, в общем, работает. Когда программа отработает, одно сообщение запишется в один файл, другое - в другой.

8 комментариев:

pylnik комментирует...

Спасибо, Даша, попробую эту индейскую хитрость ;)

ckopn комментирует...

Ждём новых постов!

Владислав комментирует...

спасибо!
пиши еще!

Bonza комментирует...

А можно ли заставить один и тот же Logger разные уровни сообщений отправлять в разные Appender-ы?
Например, для того, чтобы в консоль выводились те, что с уровнем больше чем WARNING, а в лог-файл - все подряд?

darja комментирует...

2 Bonza:
Определить два аппендера, выставить в них соответствующие фильтры и добавить соответствующие ссылки в элемент root. Читайте внимательно самую первую статью, там все это рассматривается.

Damir комментирует...

Спасибо!

KT комментирует...

Спасибо !!! СУПЕР !!!

Kostya комментирует...

Дарья, спасибо Вам большое за Ваши статьи. Очень помогают.
У меня возник вопрос: Как сделать так, чтобы несколько приложений (приложения из одного комплекса) использовали один файл конфигурации log4net и писали свои логи в !разные файлы! ? При использовании этого метода одно приложение создает и использует сразу все указанные логгеры, а не только те, которые оно использует. Находил в Интернете решение http://www.gotdotnet.ru/blogs/raimon/4858/, у меня не работает. Надо чтобы в одной папке были файлы writer.log и reader.log. Конфигурация логгеров абсолютно одинакова. Надеюсь понятно объяснил и очень надеюсь на помощь :)