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.Logger;
29 import org.apache.logging.log4j.core.config.AppenderRef;
30 import org.apache.logging.log4j.core.config.Configuration;
31 import org.apache.logging.log4j.core.config.LoggerConfig;
32 import org.apache.logging.log4j.core.config.Node;
33 import org.apache.logging.log4j.core.config.Property;
34 import org.apache.logging.log4j.core.config.plugins.Plugin;
35 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
36 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
37 import org.apache.logging.log4j.core.config.plugins.PluginElement;
38 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
39 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
40 import org.apache.logging.log4j.core.jmx.RingBufferAdmin;
41 import org.apache.logging.log4j.core.util.Booleans;
42 import org.apache.logging.log4j.message.Message;
43 import org.apache.logging.log4j.util.Strings;
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
73 @Plugin(name = "asyncLogger", category = Node.CATEGORY, printObject = true)
74 public class AsyncLoggerConfig extends LoggerConfig {
75
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
90
91
92
93 @Override
94 protected void callAppenders(final LogEvent event) {
95 populateLazilyInitializedFields(event);
96
97 if (!delegate.tryEnqueue(event, this)) {
98 handleQueueFull(event);
99 }
100 }
101
102 private void handleQueueFull(final LogEvent event) {
103 if (Logger.getRecursionDepth() > 1) {
104
105 final Message message = AsyncQueueFullMessageUtil.transform(event.getMessage());
106 callAppendersInCurrentThread(new Log4jLogEvent.Builder(event).setMessage(message).build());
107 } else {
108
109 final EventRoute eventRoute = delegate.getEventRoute(event.getLevel());
110 eventRoute.logMessage(this, event);
111 }
112 }
113
114 private void populateLazilyInitializedFields(final LogEvent event) {
115 event.getSource();
116 event.getThreadName();
117 }
118
119 void callAppendersInCurrentThread(final LogEvent event) {
120 super.callAppenders(event);
121 }
122
123 void callAppendersInBackgroundThread(final LogEvent event) {
124 delegate.enqueueEvent(event, this);
125 }
126
127
128 void asyncCallAppenders(final LogEvent event) {
129 super.callAppenders(event);
130 }
131
132 private String displayName() {
133 return LogManager.ROOT_LOGGER_NAME.equals(getName()) ? LoggerConfig.ROOT : getName();
134 }
135
136 @Override
137 public void start() {
138 LOGGER.trace("AsyncLoggerConfig[{}] starting...", displayName());
139 super.start();
140 }
141
142 @Override
143 public boolean stop(final long timeout, final TimeUnit timeUnit) {
144 setStopping();
145 super.stop(timeout, timeUnit, false);
146 LOGGER.trace("AsyncLoggerConfig[{}] stopping...", displayName());
147 setStopped();
148 return true;
149 }
150
151
152
153
154
155
156
157
158 public RingBufferAdmin createRingBufferAdmin(final String contextName) {
159 return delegate.createRingBufferAdmin(contextName, getName());
160 }
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175 @PluginFactory
176 public static LoggerConfig createLogger(
177 @PluginAttribute("additivity") final String additivity,
178 @PluginAttribute("level") final String levelName,
179 @PluginAttribute("name") final String loggerName,
180 @PluginAttribute("includeLocation") final String includeLocation,
181 @PluginElement("AppenderRef") final AppenderRef[] refs,
182 @PluginElement("Properties") final Property[] properties,
183 @PluginConfiguration final Configuration config,
184 @PluginElement("Filter") final Filter filter) {
185 if (loggerName == null) {
186 LOGGER.error("Loggers cannot be configured without a name");
187 return null;
188 }
189
190 final List<AppenderRef> appenderRefs = Arrays.asList(refs);
191 Level level;
192 try {
193 level = Level.toLevel(levelName, Level.ERROR);
194 } catch (final Exception ex) {
195 LOGGER.error(
196 "Invalid Log level specified: {}. Defaulting to Error",
197 levelName);
198 level = Level.ERROR;
199 }
200 final String name = loggerName.equals(LoggerConfig.ROOT) ? Strings.EMPTY : loggerName;
201 final boolean additive = Booleans.parseBoolean(additivity, true);
202
203 return new AsyncLoggerConfig(name, appenderRefs, filter, level,
204 additive, properties, config, includeLocation(includeLocation));
205 }
206
207
208 protected static boolean includeLocation(final String includeLocationConfigValue) {
209 return Boolean.parseBoolean(includeLocationConfigValue);
210 }
211
212
213
214
215 @Plugin(name = "asyncRoot", category = Core.CATEGORY_NAME, printObject = true)
216 public static class RootLogger extends LoggerConfig {
217
218 @PluginFactory
219 public static LoggerConfig createLogger(
220 @PluginAttribute("additivity") final String additivity,
221 @PluginAttribute("level") final String levelName,
222 @PluginAttribute("includeLocation") final String includeLocation,
223 @PluginElement("AppenderRef") final AppenderRef[] refs,
224 @PluginElement("Properties") final Property[] properties,
225 @PluginConfiguration final Configuration config,
226 @PluginElement("Filter") final Filter filter) {
227 final List<AppenderRef> appenderRefs = Arrays.asList(refs);
228 Level level;
229 try {
230 level = Level.toLevel(levelName, Level.ERROR);
231 } catch (final Exception ex) {
232 LOGGER.error(
233 "Invalid Log level specified: {}. Defaulting to Error",
234 levelName);
235 level = Level.ERROR;
236 }
237 final boolean additive = Booleans.parseBoolean(additivity, true);
238
239 return new AsyncLoggerConfig(LogManager.ROOT_LOGGER_NAME,
240 appenderRefs, filter, level, additive, properties, config,
241 AsyncLoggerConfig.includeLocation(includeLocation));
242 }
243 }
244 }