X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;ds=sidebyside;f=cms%2Forg.argeo.slc.support%2Fsrc%2Forg%2Fargeo%2Fslc%2Flog4j%2FSlcExecutionAppender.java;fp=cms%2Forg.argeo.slc.support%2Fsrc%2Forg%2Fargeo%2Fslc%2Flog4j%2FSlcExecutionAppender.java;h=2a9ea5f3d61b3eb4123cb4f35551c717d950c117;hb=ecc22e604e47533c79de9cecdcdeacbc752cbff1;hp=0000000000000000000000000000000000000000;hpb=e07ded4632e53f8b8869763bc1f1f4091361e76e;p=gpl%2Fargeo-slc.git diff --git a/cms/org.argeo.slc.support/src/org/argeo/slc/log4j/SlcExecutionAppender.java b/cms/org.argeo.slc.support/src/org/argeo/slc/log4j/SlcExecutionAppender.java new file mode 100644 index 000000000..2a9ea5f3d --- /dev/null +++ b/cms/org.argeo.slc.support/src/org/argeo/slc/log4j/SlcExecutionAppender.java @@ -0,0 +1,142 @@ +package org.argeo.slc.log4j; + +import java.util.Date; +import java.util.concurrent.BlockingQueue; + +import org.apache.log4j.AppenderSkeleton; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.apache.log4j.spi.LoggingEvent; +import org.argeo.slc.execution.ExecutionStep; +import org.argeo.slc.runtime.ExecutionThread; +import org.argeo.slc.runtime.ProcessThreadGroup; + +/** Not meant to be used directly in standard log4j config */ +public class SlcExecutionAppender extends AppenderSkeleton { + + private Boolean disabled = false; + + private String level = null; + + private Level log4jLevel = null; + + /** Marker to prevent stack overflow */ + private ThreadLocal dispatching = new ThreadLocal() { + + @Override + protected Boolean initialValue() { + return false; + } + }; + + // private Layout layout = null; + // private String pattern = "%m - %c%n"; + private Boolean onlyExecutionThread = false; + + public void init() { + // if (layout != null) + // setLayout(layout); + // else + // setLayout(new PatternLayout(pattern)); + Logger.getRootLogger().addAppender(this); + } + + @Override + protected void append(LoggingEvent event) { + if (disabled) + return; + + if (dispatching.get()) + return; + + if (level != null && !level.trim().equals("")) { + if (log4jLevel == null || !log4jLevel.toString().equals(level)) + try { + log4jLevel = Level.toLevel(level); + } catch (Exception e) { + System.err.println("Log4j level could not be set for level '" + level + "', resetting it to null."); + e.printStackTrace(); + level = null; + } + + if (log4jLevel != null && !event.getLevel().isGreaterOrEqual(log4jLevel)) { + return; + } + } + + // Check whether we are within an executing process + Thread currentThread = Thread.currentThread(); + if (currentThread.getThreadGroup() instanceof ProcessThreadGroup) { + if (onlyExecutionThread && !(currentThread instanceof ExecutionThread)) + return; + + final String type; + if (event.getLevel().equals(Level.ERROR) || event.getLevel().equals(Level.FATAL)) + type = ExecutionStep.ERROR; + else if (event.getLevel().equals(Level.WARN)) + type = ExecutionStep.WARNING; + else if (event.getLevel().equals(Level.INFO)) + type = ExecutionStep.INFO; + else if (event.getLevel().equals(Level.DEBUG)) + type = ExecutionStep.DEBUG; + else if (event.getLevel().equals(Level.TRACE)) + type = ExecutionStep.TRACE; + else + type = ExecutionStep.INFO; + + ExecutionStep step = new ExecutionStep(event.getLoggerName(), new Date(event.getTimeStamp()), type, + event.getMessage().toString()); + + try { + dispatching.set(true); + BlockingQueue steps = ((ProcessThreadGroup) currentThread.getThreadGroup()).getSteps(); + if (steps.remainingCapacity() == 0) { + stdOut("WARNING: execution steps queue is full, skipping step: " + step); + // FIXME understand why it block indefinitely: the queue + // should be emptied by the logging thread + } else { + steps.add(step); + } + } finally { + dispatching.set(false); + } + } + } + + public void destroy() throws Exception { + Logger.getRootLogger().removeAppender(this); + } + + public void close() { + } + + public boolean requiresLayout() { + return false; + } + + // public void setLayout(Layout layout) { + // this.layout = layout; + // } + + /** For development purpose, since using regular logging is not easy here */ + static void stdOut(Object obj) { + System.out.println(obj); + } + + // public void setPattern(String pattern) { + // this.pattern = pattern; + // } + + public void setOnlyExecutionThread(Boolean onlyExecutionThread) { + this.onlyExecutionThread = onlyExecutionThread; + } + + public void setDisabled(Boolean disabled) { + this.disabled = disabled; + } + + public void setLevel(String level) { + this.level = level; + } + +}