Ошибка прерывания журнала log4net для RollingFileAppender

Мы наблюдаем периодическую проблему на машинах разработки и производства, при которых наши файлы журналов не регистрируются.

При работе в разработке и отладке с помощью Visual Studio мы получаем следующие сообщения об ошибках log4net в окне вывода VS:

log4net:ERROR [RollingFileAppender] Unable to acquire lock on file C:\folder\file.log.

Процесс не может получить доступ к файлу 'C:\folder\file.log', потому что он используется другим процессом.

log4net:ERROR XmlConfigurator: Failed to find configuration section 'log4net' in the application .config file.
Check your .config file for the <log4net> and <configSections> elements.

Раздел конфигурации должен выглядеть так:

<section
  name="log4net"
  type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />

Нашим текущим решением проблемы является переименование последнего файла журнала. Разумеется, мы ожидаем, что это провалится (из-за вышеупомянутой блокировки файлов), но обычно этого не происходит. Один или два раза переименование завершилось неудачно из-за блокировки процесса aspnet_wp.exe.

Ниже приведен раздел конфигурации log4net:

<log4net>
  <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
    <file value="C:\folder\file.log"/>
    <appendToFile value="true" />
    <datePattern value="yyyyMMdd" />
    <rollingStyle value="Date" />
    <maximumFileSize value="10MB" />
    <maxSizeRollBackups value="100" />
    <layout type="log4net.Layout.PatternLayout">
      <header value="[Header]&#xA;"/>
      <footer value="[Footer]&#xA;"/>
      <conversionPattern value="%date %-5level %logger ${COMPUTERNAME} %property{UserHostAddress} [%property{SessionID}] - %message%newline"/>
    </layout>
  </appender>
  <root>
    <level value="INFO"/>
    <appender-ref ref="RollingLogFileAppender"/>
  </root>
</log4net>

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

Ответ 1

Попробуйте добавить

<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />

к вашему элементу <appender />. Это влияет на производительность, поскольку это означает, что log4net блокирует файл, записывает его и разблокирует его для каждой операции записи (в отличие от поведения по умолчанию, которое долгое время хранится и удерживается на блокировке).

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

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

Удачи!

Ответ 2

Также обратите внимание на log4net FAQ:

Как мне заставить несколько процессов регистрироваться в одном файле?

Прежде чем вы начнете использовать какие-либо альтернативы, спросите независимо от того, действительно ли вам нужно иметь несколько журналов процессов для тот же файл, затем не делайте этого; -).

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

По умолчанию FileAppender имеет исключительную блокировку записи в журнале файл во время регистрации. Это предотвращает запись других процессов к файлу. Известно, что эта модель разрушается (по крайней мере, на некоторых версии) Mono на Linux, и файлы журналов могут быть повреждены, как только другой процесс пытается получить доступ к файлу журнала.

MinimalLock получает только блокировку записи во время записи журнала. Это позволяет нескольким процессам перемежать записи в один и тот же файл, хотя и со значительной потерей производительности.

InterProcessLock не блокирует файл вообще, но синхронизирует его с помощью System Mutex. Это будет работать, только если все процессы будут взаимодействовать (и используйте ту же модель блокировки). Приобретение и выпуск Mutex для каждой записи в журнале, которая будет написана, приведет к потере но Mutex предпочтительнее использования MinimalLock.

Если вы используете RollingFileAppender, все становится еще хуже, поскольку несколько процесс может попытаться одновременно запустить файл журнала. RollingFileAppender полностью игнорирует блокирующую модель при прокатке файлы, скользящие файлы просто несовместимы с этим сценарием.

Лучшая альтернатива заключается в том, чтобы ваши процессы регистрировались в RemotingAppenders. Использование RemoteLoggingServerPlugin (или IRemoteLoggingSink) процесс может принимать все события и регистрировать их к одному файлу журнала. Один из примеров показывает, как использовать RemoteLoggingServerPlugin.

Ответ 3

Если у вас

<staticLogFileName value="true" />
<rollingStyle value="Date" />
<datePattern value="yyyyMMdd" />

и добавьте

<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />

тогда произойдет ошибка при прокатке. Первый процесс создаст новый файл и переименует текущий файл. Затем последующие процессы будут делать то же самое и взять вновь созданный файл и перезаписать недавно переименованный файл. Результат в logfiel для того, чтобы последний день был пустым.