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