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<>();
76 private final AsyncLoggerConfigDelegate delegate;
77
78 protected AsyncLoggerConfig(final String name,
79 final List<AppenderRef> appenders, final Filter filter,
80 final Level level, final boolean additive,
81 final Property[] properties, final Configuration config,
82 final boolean includeLocation) {
83 super(name, appenders, filter, level, additive, properties, config,
84 includeLocation);
85 delegate = config.getAsyncLoggerConfigDelegate();
86 delegate.setLogEventFactory(getLogEventFactory());
87 }
88
89 protected void log(final LogEvent event, final LoggerConfigPredicate predicate) {
90
91 if (predicate == LoggerConfigPredicate.ALL &&
92 ASYNC_LOGGER_ENTERED.get() == null &&
93
94
95
96
97 hasAppenders()) {
98
99 ASYNC_LOGGER_ENTERED.set(Boolean.TRUE);
100 try {
101
102
103 super.log(event, LoggerConfigPredicate.SYNCHRONOUS_ONLY);
104
105
106
107
108
109 logToAsyncDelegate(event);
110 } finally {
111 ASYNC_LOGGER_ENTERED.remove();
112 }
113 } else {
114 super.log(event, predicate);
115 }
116 }
117
118 @Override
119 protected void callAppenders(final LogEvent event) {
120 super.callAppenders(event);
121 }
122
123 private void logToAsyncDelegate(LogEvent event) {
124 if (!isFiltered(event)) {
125
126
127 populateLazilyInitializedFields(event);
128 if (!delegate.tryEnqueue(event, this)) {
129 handleQueueFull(event);
130 }
131 }
132 }
133
134 private void handleQueueFull(final LogEvent event) {
135 if (AbstractLogger.getRecursionDepth() > 1) {
136
137 AsyncQueueFullMessageUtil.logWarningToStatusLogger();
138 logToAsyncLoggerConfigsOnCurrentThread(event);
139 } else {
140
141 final EventRoute eventRoute = delegate.getEventRoute(event.getLevel());
142 eventRoute.logMessage(this, event);
143 }
144 }
145
146 private void populateLazilyInitializedFields(final LogEvent event) {
147 event.getSource();
148 event.getThreadName();
149 }
150
151 void logInBackgroundThread(final LogEvent event) {
152 delegate.enqueueEvent(event, this);
153 }
154
155
156
157
158
159
160
161 void logToAsyncLoggerConfigsOnCurrentThread(final LogEvent event) {
162 log(event, LoggerConfigPredicate.ASYNCHRONOUS_ONLY);
163 }
164
165 private String displayName() {
166 return LogManager.ROOT_LOGGER_NAME.equals(getName()) ? LoggerConfig.ROOT : getName();
167 }
168
169 @Override
170 public void start() {
171 LOGGER.trace("AsyncLoggerConfig[{}] starting...", displayName());
172 super.start();
173 }
174
175 @Override
176 public boolean stop(final long timeout, final TimeUnit timeUnit) {
177 setStopping();
178 super.stop(timeout, timeUnit, false);
179 LOGGER.trace("AsyncLoggerConfig[{}] stopping...", displayName());
180 setStopped();
181 return true;
182 }
183
184
185
186
187
188
189
190
191 public RingBufferAdmin createRingBufferAdmin(final String contextName) {
192 return delegate.createRingBufferAdmin(contextName, getName());
193 }
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209 @Deprecated
210 public static LoggerConfig createLogger(
211 final String additivity,
212 final String levelName,
213 final String loggerName,
214 final String includeLocation,
215 final AppenderRef[] refs,
216 final Property[] properties,
217 final Configuration config,
218 final Filter filter) {
219 if (loggerName == null) {
220 LOGGER.error("Loggers cannot be configured without a name");
221 return null;
222 }
223
224 final List<AppenderRef> appenderRefs = Arrays.asList(refs);
225 Level level;
226 try {
227 level = Level.toLevel(levelName, Level.ERROR);
228 } catch (final Exception ex) {
229 LOGGER.error(
230 "Invalid Log level specified: {}. Defaulting to Error",
231 levelName);
232 level = Level.ERROR;
233 }
234 final String name = loggerName.equals(LoggerConfig.ROOT) ? Strings.EMPTY : loggerName;
235 final boolean additive = Booleans.parseBoolean(additivity, true);
236
237 return new AsyncLoggerConfig(name, appenderRefs, filter, level,
238 additive, properties, config, includeLocation(includeLocation));
239 }
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255 @PluginFactory
256 public static LoggerConfig createLogger(
257 @PluginAttribute(value = "additivity", defaultBoolean = true) final boolean additivity,
258 @PluginAttribute("level") final Level level,
259 @Required(message = "Loggers cannot be configured without a name") @PluginAttribute("name") final String loggerName,
260 @PluginAttribute("includeLocation") final String includeLocation,
261 @PluginElement("AppenderRef") final AppenderRef[] refs,
262 @PluginElement("Properties") final Property[] properties,
263 @PluginConfiguration final Configuration config,
264 @PluginElement("Filter") final Filter filter) {
265 final String name = loggerName.equals(ROOT) ? Strings.EMPTY : loggerName;
266 return new AsyncLoggerConfig(name, Arrays.asList(refs), filter, level, additivity, properties, config,
267 includeLocation(includeLocation));
268 }
269
270
271 protected static boolean includeLocation(final String includeLocationConfigValue) {
272 return Boolean.parseBoolean(includeLocationConfigValue);
273 }
274
275
276
277
278 @Plugin(name = "asyncRoot", category = Core.CATEGORY_NAME, printObject = true)
279 public static class RootLogger extends LoggerConfig {
280
281
282
283
284 @Deprecated
285 public static LoggerConfig createLogger(
286 final String additivity,
287 final String levelName,
288 final String includeLocation,
289 final AppenderRef[] refs,
290 final Property[] properties,
291 final Configuration config,
292 final Filter filter) {
293 final List<AppenderRef> appenderRefs = Arrays.asList(refs);
294 Level level = null;
295 try {
296 level = Level.toLevel(levelName, Level.ERROR);
297 } catch (final Exception ex) {
298 LOGGER.error("Invalid Log level specified: {}. Defaulting to Error", levelName);
299 level = Level.ERROR;
300 }
301 final boolean additive = Booleans.parseBoolean(additivity, true);
302 return new AsyncLoggerConfig(LogManager.ROOT_LOGGER_NAME,
303 appenderRefs, filter, level, additive, properties, config,
304 AsyncLoggerConfig.includeLocation(includeLocation));
305 }
306
307
308
309
310 @PluginFactory
311 public static LoggerConfig createLogger(
312 @PluginAttribute("additivity") final String additivity,
313 @PluginAttribute("level") final Level level,
314 @PluginAttribute("includeLocation") final String includeLocation,
315 @PluginElement("AppenderRef") final AppenderRef[] refs,
316 @PluginElement("Properties") final Property[] properties,
317 @PluginConfiguration final Configuration config,
318 @PluginElement("Filter") final Filter filter) {
319 final List<AppenderRef> appenderRefs = Arrays.asList(refs);
320 final Level actualLevel = level == null ? Level.ERROR : level;
321 final boolean additive = Booleans.parseBoolean(additivity, true);
322 return new AsyncLoggerConfig(LogManager.ROOT_LOGGER_NAME, appenderRefs, filter, actualLevel, additive,
323 properties, config, AsyncLoggerConfig.includeLocation(includeLocation));
324 }
325 }
326 }