Log4net调试关闭时如何捕获Log4net Appender错误

时间:2017-06-06 20:49:08

标签: .net log4net-configuration log4net-appender

我正在使用Log4net。我最近决定将跟踪侦听器添加到我的配置文件中,以捕获Log4net本身生成的任何错误。 (该 Log4net FAQ包含此示例配置。)

(我在谈论Log4net由于无法完成其工作而产生错误消息的情况。我不是在谈论配置它来记录应用程序错误。)

在测试时,我在测试项目中弄乱了Log4net配置,以强制Log4netADO.Net Appender错误,以验证Trace Listener设置是否正确处理了它们

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

这是我通过调整Log4net.Layoutapp.config的类型名称来生成的示例错误,以引用不存在的类型。这是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错误),则错误将仅出现在跟踪侦听器文件中{{1}调试已打开。这意味着它被大量的内部管家信息所包围。

Log4net

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

所以,我的问题:

  1. 是否可以在未启用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 调试的情况下捕获跟踪侦听器中Appender致命的错误?
  2. 这是设计的行为吗?

1 个答案:

答案 0 :(得分: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);

这解决了我的问题。