]> git.argeo.org Git - gpl/argeo-slc.git/blob - org.argeo.slc.support/src/org/argeo/slc/log4j/SlcExecutionAppender.java
190a0b69661863ec83a188177992dd76f95f9877
[gpl/argeo-slc.git] / org.argeo.slc.support / src / org / argeo / slc / log4j / SlcExecutionAppender.java
1 /*
2 * Copyright (C) 2007-2012 Argeo GmbH
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
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 /** Not meant to be used directly in standard log4j config */
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 /** Marker to prevent stack overflow */
39 private ThreadLocal<Boolean> dispatching = new ThreadLocal<Boolean>() {
40
41 @Override
42 protected Boolean initialValue() {
43 return false;
44 }
45 };
46
47 // private Layout layout = null;
48 // private String pattern = "%m - %c%n";
49 private Boolean onlyExecutionThread = false;
50
51 public void init() {
52 // if (layout != null)
53 // setLayout(layout);
54 // else
55 // setLayout(new PatternLayout(pattern));
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 // Check whether we are within an executing process
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 // FIXME understand why it block indefinitely: the queue
119 // should be emptied by the logging thread
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 // public void setLayout(Layout layout) {
141 // this.layout = layout;
142 // }
143
144 /** For development purpose, since using regular logging is not easy here */
145 static void stdOut(Object obj) {
146 System.out.println(obj);
147 }
148
149 // public void setPattern(String pattern) {
150 // this.pattern = pattern;
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 }