![](/img/trans.png)
[英]LogManager.GetLogger and xmlconfigurator.configure sequence
[英]log4net's LogManager.GetLogger() throws NullReferenceException when used in custom TraceListener
我正在嘗試將大型應用程序從使用Trace
類過渡到通過log4net
輸出通知。 這樣,我編寫了一個自定義的TraceListener
以將輸出重定向到log4net的消息傳遞中(受本文章的啟發)。
public class Log4netTraceListener : TraceListener
{
private static readonly ILog logger = LogManager.GetLogger("Log4netTraceListener"); // Line 19
public Log4netTraceListener() { /* nothing special */ }
public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message)
{
// some switching based on the TraceLevel, but eventually something like:
logger.Error(message);
}
}
控制台應用程序解決方案是三個項目:
在RunShipOrder
項目中,我可以調用LogManager.GetLogger("Log4netTraceListener")
,它可以按預期工作。 但是,如果我嘗試在Trace
上調用方法,則會引發異常。 我已將其追溯到Log4netTraceListener
類內部對LogManager.GetLogger("Log4netTraceListener")
的初始調用。
引發的異常是ConfigurationErrorsException
,內部異常是TypeInitializationException
,內部異常是NullReferenceException
。 最里面的異常的堆棧跟蹤是:
at log4net.Core.LoggerManager.GetLogger(Assembly repositoryAssembly, String name)
at log4net.LogManager.GetLogger(Assembly repositoryAssembly, String name)
at log4net.LogManager.GetLogger(String name)
at CodeLibrary.Diagnostics.Log4netTraceListener..cctor() in Log4netTraceListener.cs:line 19
關於在log4net代碼庫中可能引發此異常的任何想法?
@drovani-出色的描述。 我看到了同樣的症狀。 在我的案例中,問題在於app.config中的System.Diagnostics.Trace輸出配置為自定義System.Diagnostics.TraceListener實現,該實現將跟蹤轉發到log4net,同時通過log4net.Internal啟用了log4net的內部調試。在app.config中Debug = True(或在通過log4net.Util.LogLog.InternalDebugging = true的代碼中)。
可能發生的情況是,您在靜態初始化期間或在登錄之前在自定義System.Diagnostics.TraceListener實現中調用LoggerManager.GetLogger()。這會產生靜態初始化排序問題。 log4net在初始化時但在LoggerManager初始化之前嘗試記錄某些內容。 因此,LoggerManager.GetLogger()引發空引用異常。
在您的自定義TraceListener中,可以通過使用靜態屬性在首次使用時而不是在字段中初始化ILogger來對此加以防范,但是您在這里需要小心。 最好的做法是不記錄日志,或者如果log4net.Util.LogLog.InternalDebugging為true,則使用其他機制記錄日志。 這將是首選的解決方案。
看一下log4net.Util.LogLog類的源代碼。 默認情況下,這會記錄到跟蹤中,如果由此記錄任何內容(例如追加器錯誤),您最終將陷入僵局。 在您的TraceListener的實現中,我將確保在實現的構造函數中設置log4net.Util.LogLog.EmitInternalMessages = false,並可能處理LogLog.LogReceived事件並以其他方式記錄這些消息。 可悲的是,由於此設置,某些追加器錯誤將不會被記錄。 log4net源是您的朋友。
如果您真的很棘手,會對性能產生巨大影響,則需要在記錄消息和創建記錄器之前檢查log4net.Util.LogLog.InternalDebugging的設置。 如果啟用,您可以獲取堆棧跟蹤並遍歷它,以確保在調用log4net之前log4net不在堆棧中。 如果log4net在堆棧跟蹤中,則可以釘住OutputDebugString()或使用其他日志記錄機制來跟蹤log4net內部日志輸出。 您絕對不希望將內部log4net調試消息重定向到log4net,否則會冒一個與該出色站點類似命名的異常。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.