Как перехватить ошибки Log4net Appender при выключенной отладке Log4net
Я использую Log4net
, Недавно я решил добавить в мою конфигурацию прослушиватель трассировки, чтобы зафиксировать все ошибки, сгенерированные Log4net
сам. ( FAQ по Log4net включает пример конфигурации для этого.)
(Я говорю о случаях, когда Log4net
генерирует собственное сообщение об ошибке из-за невозможности выполнить свою работу. Я не говорю о настройке его для регистрации ошибок приложения.)
Тестируя это, я возился с моим Log4net
конфигурация в тестовом проекте, чтобы заставить Log4net
или же ADO.Net Appender
ошибки, чтобы убедиться, что они были правильно обработаны настройкой Trace Listener.
То, что я нашел, говорит о том, что Log4net
ошибки будут записаны в прослушиватель трассировки, даже если Log4net
отладка отключена. Это то, что я хочу.
Вот пример ошибки, которую я сгенерировал, подправив имя типа Log4net.Layout
в app.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), она появится в файле прослушивателя трассировки только в том случае, если 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 раз в день и генерирует 25 КБ выходных данных прослушивателя трассировки отладки за один прогон, только из внутренней подсистемы. Я не хочу пробираться сквозь мегабайты шума, чтобы найти один сигнал.
Итак, мои вопросы:
- Можно ли зафиксировать ошибки, которые являются фатальными для
Appender
в слушателе трассировки, не имеяLog4net
включена отладка? - Это поведение по замыслу?
1 ответ
Я нашел решение. Хороший, элегантный.
Все классы Appender в Log4net
иметь публичную собственность под названием 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);
И это решило мою проблему.