FileLoadException при использовании NLog

Я разрабатываю API, где я использую NLog для регистрации входящих запросов и их ответов. Иногда я получаю следующую ошибку на моем сервере

Application: w3wp.exe  
Framework Version: v4.0.30319   
Description: The process was terminated due to an unhandled exception.  
Exception Info: System.IO.FileLoadException    
 at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32, IntPtr)    
 at NLog.Internal.FileAppenders.BaseFileAppender.WindowsCreateFile(System.String, Boolean)     
 at NLog.Internal.FileAppenders.BaseFileAppender.TryCreateFileStream(Boolean)  
 at NLog.Internal.FileAppenders.BaseFileAppender.CreateFileStream(Boolean)  
 at NLog.Internal.FileAppenders.RetryingMultiProcessFileAppender.Write(Byte[])  
 at NLog.Targets.FileTarget.WriteToFile(System.String, NLog.LogEventInfo, Byte[], Boolean)    
 at NLog.Targets.FileTarget.ProcessLogEvent(NLog.LogEventInfo, System.String, Byte[])    
 at NLog.Targets.FileTarget.FlushCurrentFileWrites(System.String, NLog.LogEventInfo, System.IO.MemoryStream, System.Collections.Generic.List`1<NLog.Common.AsyncContinuation>)   
 at NLog.Targets.FileTarget.Write(NLog.Common.AsyncLogEventInfo[])  
 at NLog.Targets.Target.WriteAsyncLogEvents(NLog.Common.AsyncLogEventInfo[])  
 at NLog.Targets.Wrappers.AsyncTargetWrapper.ProcessPendingEvents(System.Object)
 at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)     
 at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)    
 at System.Threading.TimerQueueTimer.CallCallback()    
 at System.Threading.TimerQueueTimer.Fire()    
 at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()  
 at System.Threading.ThreadPoolWorkQueue.Dispatch()

мой nlog.config выглядит так

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true" throwExceptions="true">

  <variable name="logPath" value="${basedir}/App_Data/Logs"/>
  <variable name="rowFormatInfo" value="${longdate} | ${level:uppercase=true} | ${message} | Thread: ${threadid}" />

  <targets async="true">
    <target name="traceFile" xsi:type="AsyncWrapper" overflowAction="Grow">
      <target xsi:type="File" fileName="${logPath}/${shortdate}.trace.log" layout="${rowFormatInfo}" />
    </target>
  </targets>

  <rules>
    <logger name="*" minlevel="Trace" maxlevel="Debug" writeTo="traceFile" />
  </rules>
</nlog>

На мой взгляд, проблема заключается в том, что я использую асинхронную оболочку, которая может привести к смешению нескольких потоков, пытающихся получить доступ к файлу журнала. Есть ли обходной путь, чтобы предотвратить такие ошибки, возникающие в периоды пиковой нагрузки, когда моему API приходится иметь дело с десятками запросов в секунду? Я не думаю, что переключение на синхронизацию журналов помогает, так как API работает в нескольких параллельных потоках сам.

Спасибо за предложения

1 ответ

Решение

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

Вы также можете получить эту проблему, если у вас есть внешнее приложение, которое может контролировать файл журнала и пытается скопировать содержимое в другое место (например, SPLUNK).

Если у вас нет нескольких приложений, пишущих в один и тот же файл, просто добавьте эти опции в file-target:

<target xsi:type="File" 
        fileName="${logPath}/${shortdate}.trace.log" 
        layout="${rowFormatInfo}" 
        keepFileOpen="true" 
        concurrentWrites="false" />

Если у вас есть несколько приложений / доменов приложений, записывающих в один и тот же файл, обновитесь до последней версии NLog (в настоящее время 4.4.10) и используйте эти параметры для файла-цели:

<target xsi:type="File" 
        fileName="${logPath}/${shortdate}.trace.log" 
        layout="${rowFormatInfo}" 
        keepFileOpen="true" 
        concurrentWrites="true" />
Другие вопросы по тегам