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.io.IOException;
20 import java.util.Arrays;
21 import java.util.HashMap;
22 import java.util.Map;
23
24 import org.apache.logging.log4j.Level;
25 import org.apache.logging.log4j.Marker;
26 import org.apache.logging.log4j.ThreadContext.ContextStack;
27 import org.apache.logging.log4j.core.LogEvent;
28 import org.apache.logging.log4j.core.config.Property;
29 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
30 import org.apache.logging.log4j.core.impl.ThrowableProxy;
31 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
32 import org.apache.logging.log4j.core.util.Constants;
33 import org.apache.logging.log4j.message.Message;
34 import org.apache.logging.log4j.message.ParameterizedMessage;
35 import org.apache.logging.log4j.message.ReusableMessage;
36 import org.apache.logging.log4j.message.SimpleMessage;
37 import org.apache.logging.log4j.message.TimestampMessage;
38 import org.apache.logging.log4j.util.Strings;
39
40 import com.lmax.disruptor.EventFactory;
41
42
43
44
45
46 public class RingBufferLogEvent implements LogEvent, ReusableMessage, CharSequence {
47
48
49 public static final Factory FACTORY = new Factory();
50
51 private static final long serialVersionUID = 8462119088943934758L;
52 private static final Message EMPTY = new SimpleMessage(Strings.EMPTY);
53
54
55
56
57 private static class Factory implements EventFactory<RingBufferLogEvent> {
58
59 @Override
60 public RingBufferLogEvent newInstance() {
61 final RingBufferLogEvent result = new RingBufferLogEvent();
62 if (Constants.ENABLE_THREADLOCALS) {
63 result.messageText = new StringBuilder(Constants.INITIAL_REUSABLE_MESSAGE_SIZE);
64 result.parameters = new Object[10];
65 }
66 return result;
67 }
68 }
69
70 private int threadPriority;
71 private long threadId;
72 private long currentTimeMillis;
73 private long nanoTime;
74 private short parameterCount;
75 private boolean includeLocation;
76 private boolean endOfBatch = false;
77 private Level level;
78 private String threadName;
79 private String loggerName;
80 private Message message;
81 private StringBuilder messageText;
82 private Object[] parameters;
83 private transient Throwable thrown;
84 private ThrowableProxy thrownProxy;
85 private Map<String, String> contextMap;
86 private Marker marker;
87 private String fqcn;
88 private StackTraceElement location;
89 private ContextStack contextStack;
90
91 private transient AsyncLogger asyncLogger;
92
93 public void setValues(final AsyncLogger anAsyncLogger, final String aLoggerName, final Marker aMarker,
94 final String theFqcn, final Level aLevel, final Message msg, final Throwable aThrowable,
95 final Map<String, String> aMap, final ContextStack aContextStack, final long threadId,
96 final String threadName, final int threadPriority, final StackTraceElement aLocation, final long aCurrentTimeMillis, final long aNanoTime) {
97 this.threadPriority = threadPriority;
98 this.threadId = threadId;
99 this.currentTimeMillis = aCurrentTimeMillis;
100 this.nanoTime = aNanoTime;
101 this.level = aLevel;
102 this.threadName = threadName;
103 this.loggerName = aLoggerName;
104 setMessage(msg);
105 this.thrown = aThrowable;
106 this.thrownProxy = null;
107 this.contextMap = aMap;
108 this.marker = aMarker;
109 this.fqcn = theFqcn;
110 this.location = aLocation;
111 this.contextStack = aContextStack;
112 this.asyncLogger = anAsyncLogger;
113 }
114
115 private void setMessage(final Message msg) {
116 if (msg instanceof ReusableMessage) {
117 final ReusableMessage reusable = (ReusableMessage) msg;
118 reusable.formatTo(getMessageTextForWriting());
119 if (parameters != null) {
120 parameters = reusable.swapParameters(parameters);
121 parameterCount = reusable.getParameterCount();
122 }
123 } else {
124
125 if (!Constants.FORMAT_MESSAGES_IN_BACKGROUND && msg != null) {
126 msg.getFormattedMessage();
127 }
128 this.message = msg;
129 }
130 }
131
132 private StringBuilder getMessageTextForWriting() {
133 if (messageText == null) {
134
135
136 messageText = new StringBuilder(Constants.INITIAL_REUSABLE_MESSAGE_SIZE);
137 }
138 messageText.setLength(0);
139 return messageText;
140 }
141
142
143
144
145
146
147 public void execute(final boolean endOfBatch) {
148 this.endOfBatch = endOfBatch;
149 asyncLogger.actualAsyncLog(this);
150 }
151
152
153
154
155
156
157 @Override
158 public boolean isEndOfBatch() {
159 return endOfBatch;
160 }
161
162 @Override
163 public void setEndOfBatch(final boolean endOfBatch) {
164 this.endOfBatch = endOfBatch;
165 }
166
167 @Override
168 public boolean isIncludeLocation() {
169 return includeLocation;
170 }
171
172 @Override
173 public void setIncludeLocation(final boolean includeLocation) {
174 this.includeLocation = includeLocation;
175 }
176
177 @Override
178 public String getLoggerName() {
179 return loggerName;
180 }
181
182 @Override
183 public Marker getMarker() {
184 return marker;
185 }
186
187 @Override
188 public String getLoggerFqcn() {
189 return fqcn;
190 }
191
192 @Override
193 public Level getLevel() {
194 if (level == null) {
195 level = Level.OFF;
196 }
197 return level;
198 }
199
200 @Override
201 public Message getMessage() {
202 if (message == null) {
203 return (messageText == null) ? EMPTY : this;
204 }
205 return message;
206 }
207
208
209
210
211 @Override
212 public String getFormattedMessage() {
213 return messageText.toString();
214 }
215
216
217
218
219 @Override
220 public String getFormat() {
221 return null;
222 }
223
224
225
226
227 @Override
228 public Object[] getParameters() {
229 return parameters == null ? null : Arrays.copyOf(parameters, parameterCount);
230 }
231
232
233
234
235 @Override
236 public Throwable getThrowable() {
237 return getThrown();
238 }
239
240
241
242
243 @Override
244 public void formatTo(final StringBuilder buffer) {
245 buffer.append(messageText);
246 }
247
248
249
250
251
252
253
254 @Override
255 public Object[] swapParameters(final Object[] emptyReplacement) {
256 final Object[] result = this.parameters;
257 this.parameters = emptyReplacement;
258 return result;
259 }
260
261
262
263
264 @Override
265 public short getParameterCount() {
266 return parameterCount;
267 }
268
269 @Override
270 public Message memento() {
271 if (message != null) {
272 return message;
273 }
274 final Object[] params = parameters == null ? new Object[0] : Arrays.copyOf(parameters, parameterCount);
275 return new ParameterizedMessage(messageText.toString(), params);
276 }
277
278
279
280 @Override
281 public int length() {
282 return messageText.length();
283 }
284
285 @Override
286 public char charAt(final int index) {
287 return messageText.charAt(index);
288 }
289
290 @Override
291 public CharSequence subSequence(final int start, final int end) {
292 return messageText.subSequence(start, end);
293 }
294
295
296 private Message getNonNullImmutableMessage() {
297 return message != null ? message : new SimpleMessage(String.valueOf(messageText));
298 }
299
300 @Override
301 public Throwable getThrown() {
302
303 if (thrown == null) {
304 if (thrownProxy != null) {
305 thrown = thrownProxy.getThrowable();
306 }
307 }
308 return thrown;
309 }
310
311 @Override
312 public ThrowableProxy getThrownProxy() {
313
314 if (thrownProxy == null) {
315 if (thrown != null) {
316 thrownProxy = new ThrowableProxy(thrown);
317 }
318 }
319 return this.thrownProxy;
320 }
321
322 @Override
323 public Map<String, String> getContextMap() {
324 return contextMap;
325 }
326
327 @Override
328 public ContextStack getContextStack() {
329 return contextStack;
330 }
331
332 @Override
333 public long getThreadId() {
334 return threadId;
335 }
336
337 @Override
338 public String getThreadName() {
339 return threadName;
340 }
341
342 @Override
343 public int getThreadPriority() {
344 return threadPriority;
345 }
346
347 @Override
348 public StackTraceElement getSource() {
349 return location;
350 }
351
352 @Override
353 public long getTimeMillis() {
354 return message instanceof TimestampMessage ? ((TimestampMessage) message).getTimestamp() :currentTimeMillis;
355 }
356
357 @Override
358 public long getNanoTime() {
359 return nanoTime;
360 }
361
362
363
364
365
366
367
368
369 public void mergePropertiesIntoContextMap(final Map<Property, Boolean> properties,
370 final StrSubstitutor strSubstitutor) {
371 if (properties == null) {
372 return;
373 }
374
375 final Map<String, String> map = contextMap == null ? new HashMap<String, String>()
376 : new HashMap<>(contextMap);
377
378 for (final Map.Entry<Property, Boolean> entry : properties.entrySet()) {
379 final Property prop = entry.getKey();
380 if (map.containsKey(prop.getName())) {
381 continue;
382 }
383 final String value = entry.getValue().booleanValue() ? strSubstitutor.replace(prop.getValue()) : prop
384 .getValue();
385 map.put(prop.getName(), value);
386 }
387 contextMap = map;
388 }
389
390
391
392
393 public void clear() {
394 this.asyncLogger = null;
395 this.loggerName = null;
396 this.marker = null;
397 this.fqcn = null;
398 this.level = null;
399 this.message = null;
400 this.thrown = null;
401 this.thrownProxy = null;
402 this.contextMap = null;
403 this.contextStack = null;
404 this.location = null;
405
406 trimMessageText();
407
408 if (parameters != null) {
409 for (int i = 0; i < parameters.length; i++) {
410 parameters[i] = null;
411 }
412 }
413 }
414
415
416 private void trimMessageText() {
417 if (messageText != null && messageText.length() > Constants.MAX_REUSABLE_MESSAGE_SIZE) {
418 messageText.setLength(Constants.MAX_REUSABLE_MESSAGE_SIZE);
419 messageText.trimToSize();
420 }
421 }
422
423 private void writeObject(final java.io.ObjectOutputStream out) throws IOException {
424 getThrownProxy();
425 out.defaultWriteObject();
426 }
427
428
429
430
431
432
433 public LogEvent createMemento() {
434 final LogEvent result = new Log4jLogEvent.Builder(this).build();
435 return result;
436 }
437
438
439
440
441
442 public void initializeBuilder(final Log4jLogEvent.Builder builder) {
443 builder.setContextMap(contextMap)
444 .setContextStack(contextStack)
445 .setEndOfBatch(endOfBatch)
446 .setIncludeLocation(includeLocation)
447 .setLevel(getLevel())
448 .setLoggerFqcn(fqcn)
449 .setLoggerName(loggerName)
450 .setMarker(marker)
451 .setMessage(getNonNullImmutableMessage())
452 .setNanoTime(nanoTime)
453 .setSource(location)
454 .setThreadId(threadId)
455 .setThreadName(threadName)
456 .setThreadPriority(threadPriority)
457 .setThrown(getThrown())
458 .setThrownProxy(thrownProxy)
459 .setTimeMillis(currentTimeMillis);
460 }
461
462 }