技術開発日記

技術やら日々思ったことを綴ってます。

Log4jのエラーハンドリング

log4jってファイルIO系のエラーが発生したときは内部でエラーハンドリングしてまうため、
書き込みが失敗した場合とかはそのことを呼び出し側に知らせてくれない。
ということを最近知りました。。。

これはlog4jの思想というか考え方らしく、log4jを使っている側にそういった
ファイルI/O系の心配をさせないという考慮らしい。

でも、実際には権限とか容量の関係でログが書けない場合も発生するから、
そういう場合はどうやってログの書き込みを保証すればいいのかという問題が出てくる。

一つの案のとしては、別途スクリプトか何かを書いて、随時対象のログファイル
に書き込みがされているかを確認する方法があるけど、
実は無理やりlog4jにファイルI/Oが失敗した場合に例外を発生するようにする
方法があるみたい。

方法としては、以下のエラーハンドラクラスとそれ用の例外を作成して
log4jの設定ファイルにその設定を書けばいいだけ。
ちなみに独自例外をわざわざ作っているのは、implemntしているErrorHandlerが
チェック例外をthrowしていないため、無理やりRuntimeExceptionを継承して例外を
発生させるため。

ただ、個人的には「絶対アプリ側でファイルが失敗したことを知りたい!」という以外は
やっぱり本来のlog4jのデフォルトの仕様で実装をするべきかなと思う。

public class Log4jException extends RuntimeException {
    
    private static final long serialVersionUID = 1L;
    
    private int errorCodeField = -1;
    
    private LoggingEvent eventField = null;
    
    public Log4jException(String message) {
        super(message);
    }
    
    public Log4jException(Throwable e) {
        super(e);
    }
    
    public Log4jException(String message, Throwable e) {
        super(message, e);
    }

    public Log4jException(String message, Throwable e, int errorCode, LoggingEvent event) {
        super(message, e);
        errorCodeField = errorCode;
        eventField = event;
    }
    
    public int getErrorCode() {
        return errorCodeField;
    }
    
    public LoggingEvent getLoggingEvent() {
        return eventField;
    }
}
public class Log4jExceptionErrorHandler implements ErrorHandler {
    
    @Override
    public void error(String message) {
        error(message, null, 0);
    }
    
    @Override
    public void error(String message, Exception e, int errorCode) {
        error(message, e, errorCode, null);
    }
    
    @Override
    public void error(String message, Exception e, int errorCode, LoggingEvent event) {
        LogLog.error(message, e);
        throw new Log4jException(message, e, errorCode, event);
    }
    
    @Override
    public void activateOptions() {}
    
    @Override
    public void setAppender(Appender appender) {}
    
    @Override
    public void setBackupAppender(Appender appender) {}
    
    @Override
    public void setLogger(Logger logger) {}
}
    <appender name="SAMPLE" class="org.apache.log4j.DailyRollingFileAppender">
        <errorHandler class="Log4jExceptionErrorHandler"/>
    </appender>

参考:http://mericleclerin.blogspot.jp/2011/03/log4j.html