2017-06-06 144 views
0

我正在使用Log4net。我最近决定将一个跟踪侦听器添加到我的配置文件中,以捕获由Log4net本身产生的任何错误。 (该 Log4net FAQ包括一个这样的例子配置。)如何在Log4net调试关闭时捕获Log4net Appender错误

(我说的情况下,当Log4net产生它自己的错误消息,因为暂时无法完成其工作。我不是在谈论它配置登录应用错误。)

在测试这一点,我在一个测试项目我Log4net配置混乱的周围以迫使Log4netADO.Net Appender错误,以验证他们被跟踪监听器设置正确处理。

我发现的内容表明,即使Log4net调试关闭,也会将内部Log4net错误写入跟踪侦听器。 这就是我想要的

这是我通过在app.config调整一个Log4net.Layout的类型名称来指代不存在的类型产生的示例错误。这是Trace Listener文件中的唯一条目,这正是我想要的。

log4net:ERROR Failed to find type [log4net.Layout.RawTimeStampLayoutXX] 
System.TypeLoadException: Could not load type [log4net.Layout.RawTimeStampLayoutXX]. Tried assembly [log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a] and all loaded assemblies 
    at log4net.Util.SystemInfo.GetTypeFromString(Assembly relativeAssembly, String typeName, Boolean throwOnError, Boolean ignoreCase) 
    at log4net.Util.SystemInfo.GetTypeFromString(String typeName, Boolean throwOnError, Boolean ignoreCase) 
    at log4net.Repository.Hierarchy.XmlHierarchyConfigurator.CreateObjectFromXml(XmlElement element, Type defaultTargetType, Type typeConstraint) 
log4net:ERROR Failed to create object to set param: layout 

但是,我也发现,如果错误是在外部系统(如,在下面的例子中,SQL Server错误),错误将只有Log4net调试出现在跟踪监听器文件已打开。这意味着它被大量的内部管家信息所包围。

log4net:ERROR [AdoNetAppender] ErrorCode: GenericFailure. Exception while writing to database 
System.Data.SqlClient.SqlException (0x80131904): Must declare the scalar variable "@log_date". 
    at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) 
    at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) 
    at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) 
    at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) 
    at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString, Boolean isInternal, Boolean forDescribeParameterEncryption) 
    at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, Boolean inRetry, SqlDataReader ds, Boolean describeParameterEncryptionRequest) 
    at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry) 
    at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry) 
    at System.Data.SqlClient.SqlCommand.ExecuteNonQuery() 
    at log4net.Appender.AdoNetAppender.SendBuffer(IDbTransaction dbTran, LoggingEvent[] events) 
    at log4net.Appender.AdoNetAppender.SendBuffer(LoggingEvent[] events) 
ClientConnectionId:8ddb2758-4adc-495e-af8b-c16e0acc937a 
Error Number:137,State:2,Class:15 

我不想随时打开调试,只是为了赶上这种错误。这款应用程序每天运行70次,每次运行只产生25KB的调试跟踪监听器输出,仅从内部管理。我不想通过兆字节的噪音来找到一个信号。

所以,我的问题:

  1. 是否有可能捕获的错误是致命的,在跟踪监听器Appender,而不必Log4net调试打开?
  2. 这是行为设计​​吗?

回答

1

我找到了解决方案。一个不错,优雅的。

Log4net中的所有Appender类都有一个名为ErrorHandler的公共属性。默认情况下,它被设置为名为OnlyOnceErrorHandler的类的实例,该类将向调试馈送(如果启用)记录错误,然后停止报告错误。

但是你可以重写此,通过配置:

<log4net> 
    <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender"> 
     <file value="Logs\logfile.txt" /> 
     <rollingStyle value="Date" /> 
     <datePattern value="yyyyMMdd" /> 
     <maxSizeRollBackups value="-1" /> 
     <maximumFileSize value="50GB" /> 
     <errorHandler type="MyTraceLoggingErrorHandler, MyAssembly" /> 

ErrorHandler实现了非常简单的接口IErrorHandler,并且可以做任何你想做的事情。

在我的情况,我根本就写收到的TraceListener的消息和异常:

Trace.WriteLine(message); 
Trace.WriteLine(errorCode); 
Trace.WriteLine(e.Message); 
Trace.WriteLine(e.StackTrace); 

这解决了我的问题。