我正在开发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 本身在多个并发线程中运行。
感谢您的建议
同一应用程序中的多个线程应该不会产生任何问题,因为它们只会写入异步队列(而不是文件(。但是,如果您有多个应用程序写入同一个文件,则可能会出现问题。
如果您有外部应用程序可以监视日志文件并尝试将内容复制到其他地方(例如 SPLUNK(,您也可能遇到此问题。
如果没有多个应用程序写入同一个文件,则只需将这些选项添加到文件目标:
<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" />