どういうこと?
log4netは内部で例外を握りつぶしているようで、アプリケーション側でtry-catchを使用してもログファイル出力エラーを補足できません。
カスタムエラーハンドラーを作成すればlog4net内で例外を補足することはできますが、そのエラーハンドラーから例外を再スローしても握りつぶされてしまうため、アプリケーション側では補足できません。
そこで、例外発生をアプリケーションにイベントで通知する方法を紹介します。
どうすれば?
ソースコード
カスタムエラーハンドラーを作成します。
using System; using log4net.Core; namespace ErrorHandling { public delegate void ErrorOccurredEventHandler(object sender, ErrorOccurredEventArgs e); public class CustomErrorHandler : IErrorHandler { public event ErrorOccurredEventHandler ErrorOccurred = null; protected virtual void OnErrorOccurred(ErrorOccurredEventArgs e) { if (this.ErrorOccurred == null) return; this.ErrorOccurred(this, e); } public void Error(string message) { this.OnErrorOccurred(new ErrorOccurredEventArgs(message)); } public void Error(string message, Exception e) { this.OnErrorOccurred(new ErrorOccurredEventArgs(message, e)); } public void Error(string message, Exception e, ErrorCode errorCode) { this.OnErrorOccurred(new ErrorOccurredEventArgs(message, e, errorCode)); } } public class ErrorOccurredEventArgs : EventArgs { public string Message { get; private set; } public Exception Exception { get; private set; } public bool HasErrorCode { get; private set; } public ErrorCode ErrorCode { get; private set; } public ErrorOccurredEventArgs(string message) : this(message, null) { } public ErrorOccurredEventArgs(string message, Exception exception) { this.Message = message; this.Exception = exception; this.HasErrorCode = false; } public ErrorOccurredEventArgs(string message, Exception exception, ErrorCode errorCode) { this.Message = message; this.Exception = exception; this.HasErrorCode = true; this.ErrorCode = ErrorCode; } } }
構成ファイル
作成したカスタムエラーハンドラーをハンドラーに設定します。
以下構成ファイルより抜粋。
<log4net> <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender"> <!-- 省略 --> <errorHandler type="ErrorHandling.CustomErrorHandler" /> </appender> <root> <level value="DEBUG" /> <appender-ref ref="RollingFileAppender" /> </root> </log4net>
ご注意
カスタムエラーハンドラーが検出できるのはログファイル出力エラーです。DBログ出力エラーを検出することはできません。log4netのAdoNetAppenderクラスにErrorHandlerプロパティがないためです。
その他のAppenderは試していませんが、ErrorHandlerプロパティがあれば、そのままこのカスタムエラーハンドラーを使用できると思います。