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