package com.alvazan.play.logging; import java.util.Iterator; import java.util.concurrent.ExecutorService; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.Appender; import ch.qos.logback.core.AppenderBase; import ch.qos.logback.core.spi.AppenderAttachable; import ch.qos.logback.core.spi.AppenderAttachableImpl; public class AsyncAppender extends AppenderBase<ILoggingEvent> implements AppenderAttachable<ILoggingEvent> { private AppenderAttachableImpl<ILoggingEvent> aai = new AppenderAttachableImpl<ILoggingEvent>(); private int appenderCount; private int backupLength = 5000; private ExecutorService exec; public void addAppender(Appender<ILoggingEvent> newAppender) { if (appenderCount == 0) { appenderCount++; addInfo("Attaching appender named [" + newAppender.getName() + "] to appender ["+getName()+"]."); aai.addAppender(newAppender); } else { addWarn("One and only one appender may be attached to AsyncAppender name=["+getName()+"]."); addWarn("Ignoring additional appender named [" + newAppender.getName() + "]"); } } public void setBackupLength(int queueSize) { this.backupLength = queueSize; } @Override public void start() { if (appenderCount == 0) { addError("No attached appenders found."); return; } if (backupLength < 1) { addError("Invalid backupLength size [" + backupLength + "]"); return; } RejectedExecutionHandler handler = new MyRejectHandler(this); LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(backupLength); exec = new ThreadPoolExecutor(1,1,0, TimeUnit.MILLISECONDS, queue, handler); super.start(); } @Override public void stop() { super.stop(); exec.shutdownNow(); aai.detachAndStopAllAppenders(); } @Override protected void append(ILoggingEvent evt) { Runnable r = new AsyncRun(evt); exec.execute(r); } private class AsyncRun implements Runnable { private ILoggingEvent evt; public AsyncRun(ILoggingEvent evt) { this.evt = evt; } @Override public void run() { try { aai.appendLoopOnAppenders(evt); } catch(Exception e) { addError("Exception trying to log", e); } } } public Iterator<Appender<ILoggingEvent>> iteratorForAppenders() { return aai.iteratorForAppenders(); } public Appender<ILoggingEvent> getAppender(String name) { return aai.getAppender(name); } public boolean isAttached(Appender<ILoggingEvent> appender) { return aai.isAttached(appender); } public void detachAndStopAllAppenders() { aai.detachAndStopAllAppenders(); } public boolean detachAppender(Appender<ILoggingEvent> appender) { return aai.detachAppender(appender); } public boolean detachAppender(String name) { return aai.detachAppender(name); } }