1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.argeo.slc.log4j;
17
18 import java.util.Date;
19 import java.util.concurrent.BlockingQueue;
20
21 import org.apache.log4j.AppenderSkeleton;
22 import org.apache.log4j.Level;
23 import org.apache.log4j.Logger;
24 import org.apache.log4j.spi.LoggingEvent;
25 import org.argeo.slc.core.execution.ExecutionThread;
26 import org.argeo.slc.core.execution.ProcessThreadGroup;
27 import org.argeo.slc.execution.ExecutionStep;
28
29
30 public class SlcExecutionAppender extends AppenderSkeleton {
31
32 private Boolean disabled = false;
33
34 private String level = null;
35
36 private Level log4jLevel = null;
37
38
39 private ThreadLocal<Boolean> dispatching = new ThreadLocal<Boolean>() {
40
41 @Override
42 protected Boolean initialValue() {
43 return false;
44 }
45 };
46
47
48
49 private Boolean onlyExecutionThread = false;
50
51 public void init() {
52
53
54
55
56 Logger.getRootLogger().addAppender(this);
57 }
58
59 @Override
60 protected void append(LoggingEvent event) {
61 if (disabled)
62 return;
63
64 if (dispatching.get())
65 return;
66
67 if (level != null && !level.trim().equals("")) {
68 if (log4jLevel == null || !log4jLevel.toString().equals(level))
69 try {
70 log4jLevel = Level.toLevel(level);
71 } catch (Exception e) {
72 System.err
73 .println("Log4j level could not be set for level '"
74 + level + "', resetting it to null.");
75 e.printStackTrace();
76 level = null;
77 }
78
79 if (log4jLevel != null
80 && !event.getLevel().isGreaterOrEqual(log4jLevel)) {
81 return;
82 }
83 }
84
85
86 Thread currentThread = Thread.currentThread();
87 if (currentThread.getThreadGroup() instanceof ProcessThreadGroup) {
88 if (onlyExecutionThread
89 && !(currentThread instanceof ExecutionThread))
90 return;
91
92 final String type;
93 if (event.getLevel().equals(Level.ERROR)
94 || event.getLevel().equals(Level.FATAL))
95 type = ExecutionStep.ERROR;
96 else if (event.getLevel().equals(Level.WARN))
97 type = ExecutionStep.WARNING;
98 else if (event.getLevel().equals(Level.INFO))
99 type = ExecutionStep.INFO;
100 else if (event.getLevel().equals(Level.DEBUG))
101 type = ExecutionStep.DEBUG;
102 else if (event.getLevel().equals(Level.TRACE))
103 type = ExecutionStep.TRACE;
104 else
105 type = ExecutionStep.INFO;
106
107 ExecutionStep step = new ExecutionStep(event.getLoggerName(),
108 new Date(event.getTimeStamp()), type, event.getMessage()
109 .toString());
110
111 try {
112 dispatching.set(true);
113 BlockingQueue<ExecutionStep> steps = ((ProcessThreadGroup) currentThread
114 .getThreadGroup()).getSteps();
115 if (steps.remainingCapacity() == 0) {
116 stdOut("WARNING: execution steps queue is full, skipping step: "
117 + step);
118
119
120 } else {
121 steps.add(step);
122 }
123 } finally {
124 dispatching.set(false);
125 }
126 }
127 }
128
129 public void destroy() throws Exception {
130 Logger.getRootLogger().removeAppender(this);
131 }
132
133 public void close() {
134 }
135
136 public boolean requiresLayout() {
137 return false;
138 }
139
140
141
142
143
144
145 static void stdOut(Object obj) {
146 System.out.println(obj);
147 }
148
149
150
151
152
153 public void setOnlyExecutionThread(Boolean onlyExecutionThread) {
154 this.onlyExecutionThread = onlyExecutionThread;
155 }
156
157 public void setDisabled(Boolean disabled) {
158 this.disabled = disabled;
159 }
160
161 public void setLevel(String level) {
162 this.level = level;
163 }
164
165 }