最近為了加快寫log速度於是使用了log4net中的BufferingForwarder:她可以將log訊息寫入Buffer,等到Buffer滿到指定數目或是Process結束後再將log輸出到到檔案!
這兩天又有需求想在執行過程即時看到log訊息,於是在log4net訂了第兩組輸出媒體: ConsoleAppender。
加上Console 這組設定後,BufferingForwarder繼續正確的寫出log,但程式執行時,在ConsoleAppender吐出以下的訊息:
log4net:ERROR [ConsoleAppender] Failed in DoAppend
System.NullReferenceException: 並未將物件參考設定為物件的執行個體。
神奇的是,如果停用BufferingForwarder,ConsoleAppender就可以正常運作,兩個人好像不能和平共處,就像磁鐵的同性互斥。
模擬程式碼
1.程式碼先參考這篇引用log4net BufferForwarder
新增Console專案,然後在program.cs加入以下程式碼
private static readonly ILog Logger = LogManager.GetLogger("Test");
static void Main(string[] args)
{
XmlConfigurator.Configure(new FileInfo(string.Format(@"{0}\{1}",
Directory.GetParent(Directory.GetParent(Environment.CurrentDirectory).FullName),
"log4net.config")));
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 10; i++)
{
Logger.Debug(string.Format("this is no{0} log", i + 1));
}
sw.Stop();
Console.WriteLine($"總耗時(ElapsedMilliseconds) = {sw.ElapsedMilliseconds}");
}
2.log4net.config輸入以下內容
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<root>
<level value="All"/>
<appender-ref ref="BufferingForwarder" />
<appender-ref ref="ConsoleAppender"/>
</root>
<appender name="BufferingForwarder" type="log4net.Appender.BufferingForwardingAppender">
<bufferSize value="512" />
<lossy value="false" />
<Fix value="8" />
<appender-ref ref="RollingFile" />
</appender>
<appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString" value="Log/Log-%date{yyyyMMdd}/Debug.log" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<appendToFile value="true"/>
<rollingStyle value="Composite"/>
<maxSizeRollBackups value="-1"/>
<maximumFileSize value="50MB"/>
<staticLogFileName value="true"/>
<datePattern value="yyyy-MM-dd"/>
<countDirection value="1"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date{ISO8601} [%2thread] - %message%newline%exception"/>
</layout>
</appender>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy/MM/dd HH:mm:ss.fff} %m %C %l %exception %n" />
</layout>
</appender>
</log4net>
專案檔結構:
3.執行結果:
檔案輸出的部分:
但console就沒有把log輸出了!而且出現了Failed in DoAppend
System.NullReferenceException: 並未將物件參考設定為物件的執行個體。
Try了幾種組合,找到臨時解決的辦法1:
改變config順序
把ConsoleAppender往前移到第一組config,兩個輸出Appender都正常寫出了!
<root>
<level value="All"/>
<appender-ref ref="BufferingForwarder" />
<appender-ref ref="ConsoleAppender"/>
</root>
<root>
<level value="All"/>
<appender-ref ref="ConsoleAppender"/>
<appender-ref ref="BufferingForwarder" />
</root>
重新執行測試!log就有寫出到console了
conversionPattern value
仔細比較兩組config發現conversionPattern value 不太相同!
config | conversionPattern |
BufferingForwarder |
%date{ISO8601} [%2thread] - %message%newline%exception |
ConsoleAppender |
%d{yyyy/MM/dd HH:mm:ss.fff} %m %C %l %exception %n |
臨時解決辦法2:
試著把ConsoleAppender改成與BufferingForwarder相同的conversionPattern value,問題也可以排除。
小結:
- 猜測log4net載入第一組BufferingForwarder的conversionPattern可能有出現問題或是這組太客製,因此就跳過ConsoleAppender的conversionPattern,當log4net要輸出log到console時就出現了NullReferenceException。
- 之後再來深入研究
參考: