package test; import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.apache.log4j.DailyRollingFileAppender; import org.apache.log4j.Layout; /** * 既能設置buffer大小,也能定時刷新(不管是否達到設定的buffer大小)的appender;適用於既想使用buffer的IO提升性能,又想定時強制輸出以不影響某些依賴日誌輸出的後續流程的場景 * * @author pf-miles * @since 2015-4-7 */ public class TimedBufferedDailyRollingFileAppender extends DailyRollingFileAppender { private static final int CHECK_INTERVAL = 5; private static final Object appendersLock = new Object(); private static final List<TimedBufferedDailyRollingFileAppender> appenders = new ArrayList<TimedBufferedDailyRollingFileAppender>(); static { new Thread(new Runnable() { public void run() { while (true) { try { synchronized (appendersLock) { for (TimedBufferedDailyRollingFileAppender appender : appenders) appender.flush(); } Thread.sleep(CHECK_INTERVAL * 1000); } catch (Throwable t) { // ignore... } } } }, "TimedBufferedDailyRollingFileAppender-timed-flush").start(); } private static final int DEFAULT_BUFFER_SIZE = 1024 * 1024; // 默認1MB的buffer protected int flushInterval = 60; // 默認的定時刷新間隔(秒) private Date flushTime = new Date(); // 下一次刷新的時間點 public TimedBufferedDailyRollingFileAppender(){ super(); this.setBufferedIO(true); this.setBufferSize(DEFAULT_BUFFER_SIZE);// 默認1MB的buffer this.setImmediateFlush(false); synchronized (appendersLock) { appenders.add(this); } } public TimedBufferedDailyRollingFileAppender(Layout layout, String filename, String datePattern) throws IOException{ super(layout, filename, datePattern); this.setBufferedIO(true); this.setBufferSize(DEFAULT_BUFFER_SIZE);// 默認1MB的buffer this.setImmediateFlush(false); synchronized (appendersLock) { appenders.add(this); } } private void flush() { if (!(new Date()).after(flushTime)) return; if (!checkEntryConditions()) return; qw.flush(); this.flushTime = new Date(System.currentTimeMillis() + this.flushInterval * 1000); } public void setFlushInterval(int flushInterval) { if (flushInterval < CHECK_INTERVAL) flushInterval = CHECK_INTERVAL;// 至少CHECK_INTERVAL秒 this.flushInterval = flushInterval; } // 本appender必須是bufferedIO, 不然沒意義 @Override public boolean getBufferedIO() { return true; } @Override public void setBufferedIO(boolean bufferedIO) { super.setBufferedIO(true); } @Override public void setImmediateFlush(boolean value) { super.setImmediateFlush(false); } @Override public boolean getImmediateFlush() { return false; } }
配置使用樣例:java
<appender name="xxx" class="test.TimedBufferedDailyRollingFileAppender"> <param name="file" value="/tmp/xxx.log"/> <param name="datePattern" value="'.'yyyy-MM-dd-HH"/> <param name="append" value="true"/> <param name="encoding" value="UTF-8"/> <param name="flushInterval" value="10"/> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss}|%p|%X{hostIp}||%m%n"/> </layout> </appender>