1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.async;
18
19 import java.util.Arrays;
20 import java.util.List;
21 import java.util.concurrent.TimeUnit;
22
23 import org.apache.logging.log4j.Level;
24 import org.apache.logging.log4j.LogManager;
25 import org.apache.logging.log4j.core.Core;
26 import org.apache.logging.log4j.core.Filter;
27 import org.apache.logging.log4j.core.LogEvent;
28 import org.apache.logging.log4j.core.config.AppenderRef;
29 import org.apache.logging.log4j.core.config.Configuration;
30 import org.apache.logging.log4j.core.config.LoggerConfig;
31 import org.apache.logging.log4j.core.config.Node;
32 import org.apache.logging.log4j.core.config.Property;
33 import org.apache.logging.log4j.core.config.plugins.Plugin;
34 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
35 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
36 import org.apache.logging.log4j.core.config.plugins.PluginElement;
37 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
38 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
39 import org.apache.logging.log4j.core.jmx.RingBufferAdmin;
40 import org.apache.logging.log4j.core.util.Booleans;
41 import org.apache.logging.log4j.spi.AbstractLogger;
42 import org.apache.logging.log4j.util.Strings;
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 @Plugin(name = "asyncLogger", category = Node.CATEGORY, printObject = true)
73 public class AsyncLoggerConfig extends LoggerConfig {
74
75 private static final ThreadLocal<Boolean> ASYNC_LOGGER_ENTERED = new ThreadLocal<Boolean>() {
76 @Override
77 protected Boolean initialValue() {
78 return Boolean.FALSE;
79 }
80 };
81
82 private final AsyncLoggerConfigDelegate delegate;
83
84 protected AsyncLoggerConfig(final String name,
85 final List<AppenderRef> appenders, final Filter filter,
86 final Level level, final boolean additive,
87 final Property[] properties, final Configuration config,
88 final boolean includeLocation) {
89 super(name, appenders, filter, level, additive, properties, config,
90 includeLocation);
91 delegate = config.getAsyncLoggerConfigDelegate();
92 delegate.setLogEventFactory(getLogEventFactory());
93 }
94
95 @Override
96 protected void log(final LogEvent event, final LoggerConfigPredicate predicate) {
97
98 if (predicate == LoggerConfigPredicate.ALL &&
99 ASYNC_LOGGER_ENTERED.get() == Boolean.FALSE &&
100
101
102
103
104 hasAppenders()) {
105
106 ASYNC_LOGGER_ENTERED.set(Boolean.TRUE);
107 try {
108
109
110 super.log(event, LoggerConfigPredicate.SYNCHRONOUS_ONLY);
111
112
113
114
115
116 logToAsyncDelegate(event);
117 } finally {
118 ASYNC_LOGGER_ENTERED.set(Boolean.FALSE);
119 }
120 } else {
121 super.log(event, predicate);
122 }
123 }
124
125 @Override
126 protected void callAppenders(final LogEvent event) {
127 super.callAppenders(event);
128 }
129
130 private void logToAsyncDelegate(final LogEvent event) {
131 if (!isFiltered(event)) {
132
133
134 populateLazilyInitializedFields(event);
135 if (!delegate.tryEnqueue(event, this)) {
136 handleQueueFull(event);
137 }
138 }
139 }
140
141 private void handleQueueFull(final LogEvent event) {
142 if (AbstractLogger.getRecursionDepth() > 1) {
143
144 AsyncQueueFullMessageUtil.logWarningToStatusLogger();
145 logToAsyncLoggerConfigsOnCurrentThread(event);
146 } else {
147
148 final EventRoute eventRoute = delegate.getEventRoute(event.getLevel());
149 eventRoute.logMessage(this, event);
150 }
151 }
152
153 private void populateLazilyInitializedFields(final LogEvent event) {
154 event.getSource();
155 event.getThreadName();
156 }
157
158 void logInBackgroundThread(final LogEvent event) {
159 delegate.enqueueEvent(event, this);
160 }
161
162
163
164
165
166
167
168 void logToAsyncLoggerConfigsOnCurrentThread(final LogEvent event) {
169 log(event, LoggerConfigPredicate.ASYNCHRONOUS_ONLY);
170 }
171
172 private String displayName() {
173 return LogManager.ROOT_LOGGER_NAME.equals(getName()) ? LoggerConfig.ROOT : getName();
174 }
175
176 @Override
177 public void start() {
178 LOGGER.trace("AsyncLoggerConfig[{}] starting...", displayName());
179 super.start();
180 }
181
182 @Override
183 public boolean stop(final long timeout, final TimeUnit timeUnit) {
184 setStopping();
185 super.stop(timeout, timeUnit, false);
186 LOGGER.trace("AsyncLoggerConfig[{}] stopping...", displayName());
187 setStopped();
188 return true;
189 }
190
191
192
193
194
195
196
197
198 public RingBufferAdmin createRingBufferAdmin(final String contextName) {
199 return delegate.createRingBufferAdmin(contextName, getName());
200 }
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216 @Deprecated
217 public static LoggerConfig createLogger(
218 final String additivity,
219 final String levelName,
220 final String loggerName,
221 final String includeLocation,
222 final AppenderRef[] refs,
223 final Property[] properties,
224 final Configuration config,
225 final Filter filter) {
226 if (loggerName == null) {
227 LOGGER.error("Loggers cannot be configured without a name");
228 return null;
229 }
230
231 final List<AppenderRef> appenderRefs = Arrays.asList(refs);
232 Level level;
233 try {
234 level = Level.toLevel(levelName, Level.ERROR);
235 } catch (final Exception ex) {
236 LOGGER.error(
237 "Invalid Log level specified: {}. Defaulting to Error",
238 levelName);
239 level = Level.ERROR;
240 }
241 final String name = loggerName.equals(LoggerConfig.ROOT) ? Strings.EMPTY : loggerName;
242 final boolean additive = Booleans.parseBoolean(additivity, true);
243
244 return new AsyncLoggerConfig(name, appenderRefs, filter, level,
245 additive, properties, config, includeLocation(includeLocation));
246 }
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262 @PluginFactory
263 public static LoggerConfig createLogger(
264 @PluginAttribute(value = "additivity", defaultBoolean = true) final boolean additivity,
265 @PluginAttribute("level") final Level level,
266 @Required(message = "Loggers cannot be configured without a name") @PluginAttribute("name") final String loggerName,
267 @PluginAttribute("includeLocation") final String includeLocation,
268 @PluginElement("AppenderRef") final AppenderRef[] refs,
269 @PluginElement("Properties") final Property[] properties,
270 @PluginConfiguration final Configuration config,
271 @PluginElement("Filter") final Filter filter) {
272 final String name = loggerName.equals(ROOT) ? Strings.EMPTY : loggerName;
273 return new AsyncLoggerConfig(name, Arrays.asList(refs), filter, level, additivity, properties, config,
274 includeLocation(includeLocation));
275 }
276
277
278 protected static boolean includeLocation(final String includeLocationConfigValue) {
279 return Boolean.parseBoolean(includeLocationConfigValue);
280 }
281
282
283
284
285 @Plugin(name = "asyncRoot", category = Core.CATEGORY_NAME, printObject = true)
286 public static class RootLogger extends LoggerConfig {
287
288
289
290
291 @Deprecated
292 public static LoggerConfig createLogger(
293 final String additivity,
294 final String levelName,
295 final String includeLocation,
296 final AppenderRef[] refs,
297 final Property[] properties,
298 final Configuration config,
299 final Filter filter) {
300 final List<AppenderRef> appenderRefs = Arrays.asList(refs);
301 Level level = null;
302 try {
303 level = Level.toLevel(levelName, Level.ERROR);
304 } catch (final Exception ex) {
305 LOGGER.error("Invalid Log level specified: {}. Defaulting to Error", levelName);
306 level = Level.ERROR;
307 }
308 final boolean additive = Booleans.parseBoolean(additivity, true);
309 return new AsyncLoggerConfig(LogManager.ROOT_LOGGER_NAME,
310 appenderRefs, filter, level, additive, properties, config,
311 AsyncLoggerConfig.includeLocation(includeLocation));
312 }
313
314
315
316
317 @PluginFactory
318 public static LoggerConfig createLogger(
319 @PluginAttribute("additivity") final String additivity,
320 @PluginAttribute("level") final Level level,
321 @PluginAttribute("includeLocation") final String includeLocation,
322 @PluginElement("AppenderRef") final AppenderRef[] refs,
323 @PluginElement("Properties") final Property[] properties,
324 @PluginConfiguration final Configuration config,
325 @PluginElement("Filter") final Filter filter) {
326 final List<AppenderRef> appenderRefs = Arrays.asList(refs);
327 final Level actualLevel = level == null ? Level.ERROR : level;
328 final boolean additive = Booleans.parseBoolean(additivity, true);
329 return new AsyncLoggerConfig(LogManager.ROOT_LOGGER_NAME, appenderRefs, filter, actualLevel, additive,
330 properties, config, AsyncLoggerConfig.includeLocation(includeLocation));
331 }
332 }
333 }