這是本文件的舊版!


FileWatchDog for Configuration

在軟體開發與debug的時候,使用log去記錄一些執行過程,可以幫助了解程式做到什麼地方、發生問題在哪或狀態如何。但每次修改完log4j property file就要重新啟動應用程式讓它reload,這樣不是很煩嗎?為了解決這樣問題,我們可以透過Log4J提供的PropertyWatchdog去polling config是否有做過修改,使用也只要透過PropertyConfigurator的configureAndWatch就可以了,預設是60秒check一次。

org.apache.log4j.PropertyConfigurator.configureAndWatch(aLogPropertyFilePath);
但如果你是使用1.2版本的,可能會遇到和我一樣的情況。在我將package名稱如以下更動後(增加.internal),就收到了log4j:ERROR Attempted to append to closed appender named的訊息,還狂跳不停。這是怎麼一回事?
log4j.additivity.org.tonylin.facebook=false
log4j.logger.org.tonylin.facebook=INFO, CONSOLE, LOGFILE
->
log4j.additivity.org.tonylin.facebook.internal=false
log4j.logger.org.tonylin.facebook.internal=INFO, CONSOLE, LOGFILE

我先告訴大家我最後的解法,細部內容待我最後說明。一看訊息就可以猜應該是狀態不正常造成的,在trace code後發現原先在每次檔案有改變後,也僅做了下面的動作。

new PropertyConfigurator().doConfigure(filename, LogManager.getLoggerRepository())
於是我直接寫了一個class去繼承Log4j既有的FileWatchdog,並於發生改變時,初始化之前做Configuration的reset,這個問題就這樣解決了。
public class Log4jPropertyWatcher extends FileWatchdog {
 
	private static Logger mLogger = LoggerFactory.getLogger(Log4jPropertyWatcher.class);
	private static long mDefaultInterval = 1000l;
 
	Log4jPropertyWatcher(String filename){
		super(filename);
	}
 
	@Override
	protected void doOnChange() {
		mLogger.debug("Log4j config is changed.");
		LogManager.getLoggerRepository().resetConfiguration();
		new PropertyConfigurator().doConfigure(filename, LogManager.getLoggerRepository());
	}
 
	public static void configureAndWatch(String filename){
		Log4jPropertyWatcher fileWatcher = new Log4jPropertyWatcher(filename);
		fileWatcher.setDelay(mDefaultInterval);
		fileWatcher.start();
	}
 
	public static void setWatchInterval(long aInterval){
		mDefaultInterval = aInterval;
	}
}