1 package org
.argeo
.slc
.log4j
;
4 import java
.util
.concurrent
.BlockingQueue
;
6 import org
.apache
.log4j
.AppenderSkeleton
;
7 import org
.apache
.log4j
.Level
;
8 import org
.apache
.log4j
.Logger
;
9 import org
.apache
.log4j
.spi
.LoggingEvent
;
10 import org
.argeo
.slc
.execution
.ExecutionStep
;
11 import org
.argeo
.slc
.runtime
.ExecutionThread
;
12 import org
.argeo
.slc
.runtime
.ProcessThreadGroup
;
14 /** Not meant to be used directly in standard log4j config */
15 public class SlcExecutionAppender
extends AppenderSkeleton
{
17 private Boolean disabled
= false;
19 private String level
= null;
21 private Level log4jLevel
= null;
23 /** Marker to prevent stack overflow */
24 private ThreadLocal
<Boolean
> dispatching
= new ThreadLocal
<Boolean
>() {
27 protected Boolean
initialValue() {
32 // private Layout layout = null;
33 // private String pattern = "%m - %c%n";
34 private Boolean onlyExecutionThread
= false;
37 // if (layout != null)
40 // setLayout(new PatternLayout(pattern));
41 Logger
.getRootLogger().addAppender(this);
45 protected void append(LoggingEvent event
) {
49 if (dispatching
.get())
52 if (level
!= null && !level
.trim().equals("")) {
53 if (log4jLevel
== null || !log4jLevel
.toString().equals(level
))
55 log4jLevel
= Level
.toLevel(level
);
56 } catch (Exception e
) {
57 System
.err
.println("Log4j level could not be set for level '" + level
+ "', resetting it to null.");
62 if (log4jLevel
!= null && !event
.getLevel().isGreaterOrEqual(log4jLevel
)) {
67 // Check whether we are within an executing process
68 Thread currentThread
= Thread
.currentThread();
69 if (currentThread
.getThreadGroup() instanceof ProcessThreadGroup
) {
70 if (onlyExecutionThread
&& !(currentThread
instanceof ExecutionThread
))
74 if (event
.getLevel().equals(Level
.ERROR
) || event
.getLevel().equals(Level
.FATAL
))
75 type
= ExecutionStep
.ERROR
;
76 else if (event
.getLevel().equals(Level
.WARN
))
77 type
= ExecutionStep
.WARNING
;
78 else if (event
.getLevel().equals(Level
.INFO
))
79 type
= ExecutionStep
.INFO
;
80 else if (event
.getLevel().equals(Level
.DEBUG
))
81 type
= ExecutionStep
.DEBUG
;
82 else if (event
.getLevel().equals(Level
.TRACE
))
83 type
= ExecutionStep
.TRACE
;
85 type
= ExecutionStep
.INFO
;
87 ExecutionStep step
= new ExecutionStep(event
.getLoggerName(), new Date(event
.getTimeStamp()), type
,
88 event
.getMessage().toString());
91 dispatching
.set(true);
92 BlockingQueue
<ExecutionStep
> steps
= ((ProcessThreadGroup
) currentThread
.getThreadGroup()).getSteps();
93 if (steps
.remainingCapacity() == 0) {
94 stdOut("WARNING: execution steps queue is full, skipping step: " + step
);
95 // FIXME understand why it block indefinitely: the queue
96 // should be emptied by the logging thread
101 dispatching
.set(false);
106 public void destroy() throws Exception
{
107 Logger
.getRootLogger().removeAppender(this);
110 public void close() {
113 public boolean requiresLayout() {
117 // public void setLayout(Layout layout) {
118 // this.layout = layout;
121 /** For development purpose, since using regular logging is not easy here */
122 static void stdOut(Object obj
) {
123 System
.out
.println(obj
);
126 // public void setPattern(String pattern) {
127 // this.pattern = pattern;
130 public void setOnlyExecutionThread(Boolean onlyExecutionThread
) {
131 this.onlyExecutionThread
= onlyExecutionThread
;
134 public void setDisabled(Boolean disabled
) {
135 this.disabled
= disabled
;
138 public void setLevel(String level
) {