Вход в отдельный файл журнала для каждого отдельного потока - PullRequest
10 голосов
/ 05 августа 2011

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

В app.config services у меня есть настройки конфигурации log4net для использования XML-приложения, а файл указан как PatternString, как показано ниже:

<appender name="XmlAppender" type="log4net.Appender.FileAppender">
  <file type="log4net.Util.PatternString" value="D:\Temp\Logs\%property{LogName}.log" />
  <immediateFlush value="true"/>
  <appendToFile value="true" />
  <layout type="log4net.Layout.SimpleLayout" />
</appender>

В потоке заблокирован методдля каждого созданного экземпляра рабочего класса я получаю регистратор с помощью метода log4net.LogManager.GetLogger("MyLogger"), а затем устанавливаю текущее свойство ThreadStrings LogName с помощью ThreadContext.Properties["LogName"] = "Log name prefix".

Все файлы создаются, но когда вызывается регистратор, он просто записывает все сообщения в один, казалось бы, случайный файл.

Я довольно долго искал, пытаясь найти решение или какое-то другое.ответы на то, что я делаю неправильно, но мне не повезло.

У кого-нибудь есть идеи, почему это происходит?

Ответы [ 2 ]

13 голосов
/ 17 августа 2011

Я думаю, что я решил проблему. Следующие шаги:

  • Создайте отдельного человека с именем LoggerRepository в каждом потоке.
  • Установите свойство ThreadContexts для имени файла журнала.
  • Используйте XmlConfiguratior для настройки хранилища.
  • Используйте LogManager, чтобы получить именованный регистратор (в файле конфигурации XML), используя именованный LoggerRepository для этого потока.

В ответ я получаю новый сконфигурированный регистратор, указывающий на соответствующий файл для этого потока.

Конфигурация XML такая же, как была изначально и показана здесь для полноты:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>    
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
  </configSections>
  <log4net>
    <logger name="ProductionLogger">
      <appender-ref ref="XmlAppender"/>      
      <level value="ALL"/>
    </logger>
    <appender name="XmlAppender" type="log4net.Appender.FileAppender">
      <file type="log4net.Util.PatternString" value="D:\Temp\Logs\%property{LogName}.log" />
      <immediateFlush value="true"/>
      <appendToFile value="true" />
      <layout type="log4net.Layout.SimpleLayout" />
    </appender>
  </log4net>
</configuration>

Код для создания регистраторов приведен ниже. Каждый раз, когда этот код запускается, он запускается в своем собственном потоке.

ILoggerRepository loggerRepository = LogManager.CreateRepository(logFileName + "Repository");
ThreadContext.Properties["LogName"] = logFileName;
log4net.Config.XmlConfigurator.Configure(loggerRepository);
ILog logger = LogManager.GetLogger(logFileName + "Repository", "ProductionLogger");

Кажется, до сих пор это работает без проблем. На данный момент я буду двигаться вперед с этим решением, но я обновлю этот пост, если узнаю что-нибудь еще.

4 голосов
/ 12 сентября 2013

Ответ Адама сработал очень хорошо для меня, но есть один, который я хотел бы добавить.Если существует вероятность повторного использования вашего logFileName в вашем приложении, вам необходимо убедиться, что хранилище еще не существует.

string repoName = String.Format("{0}Repository", logFileName);

// Check for existing repository
ILoggerRepository[] allRepos = LogManager.GetAllRepositories();
ILoggerRepository repo = allRepos.Where(x => x.Name == repoName).FirstOrDefault();

// If repository does not exist, create one, set the logfile name, and configure it
if (repo == null)
{
    repo = LogManager.CreateRepository(repoName);
    ThreadContext.Properties[KEY_LOG_FILE] = logFileName;
    log4net.Config.XmlConfigurator.Configure(repo);
}

// Set logger
ILog logger = LogManager.GetLogger(repoName, logName);
...