1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.impl;
18
19 import java.io.IOException;
20 import java.io.InvalidObjectException;
21 import java.io.ObjectInputStream;
22 import java.io.Serializable;
23 import java.rmi.MarshalledObject;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Objects;
27
28 import org.apache.logging.log4j.Level;
29 import org.apache.logging.log4j.Marker;
30 import org.apache.logging.log4j.ThreadContext;
31 import org.apache.logging.log4j.core.ContextDataInjector;
32 import org.apache.logging.log4j.core.util.*;
33 import org.apache.logging.log4j.core.time.Instant;
34 import org.apache.logging.log4j.core.time.MutableInstant;
35 import org.apache.logging.log4j.util.ReadOnlyStringMap;
36 import org.apache.logging.log4j.core.LogEvent;
37 import org.apache.logging.log4j.core.async.RingBufferLogEvent;
38 import org.apache.logging.log4j.core.config.LoggerConfig;
39 import org.apache.logging.log4j.core.config.Property;
40 import org.apache.logging.log4j.message.LoggerNameAwareMessage;
41 import org.apache.logging.log4j.message.Message;
42 import org.apache.logging.log4j.message.ReusableMessage;
43 import org.apache.logging.log4j.message.SimpleMessage;
44 import org.apache.logging.log4j.message.TimestampMessage;
45 import org.apache.logging.log4j.util.StackLocatorUtil;
46 import org.apache.logging.log4j.util.StringMap;
47 import org.apache.logging.log4j.status.StatusLogger;
48 import org.apache.logging.log4j.util.Strings;
49
50
51
52
53 public class Log4jLogEvent implements LogEvent {
54
55 private static final long serialVersionUID = -8393305700508709443L;
56 private static final Clock CLOCK = ClockFactory.getClock();
57 private static volatile NanoClock nanoClock = new DummyNanoClock();
58 private static final ContextDataInjector CONTEXT_DATA_INJECTOR = ContextDataInjectorFactory.createInjector();
59
60 private final String loggerFqcn;
61 private final Marker marker;
62 private final Level level;
63 private final String loggerName;
64 private Message message;
65 private final MutableInstant instant = new MutableInstant();
66 private final transient Throwable thrown;
67 private ThrowableProxy thrownProxy;
68 private final StringMap contextData;
69 private final ThreadContext.ContextStack contextStack;
70 private long threadId;
71 private String threadName;
72 private int threadPriority;
73 private StackTraceElement source;
74 private boolean includeLocation;
75 private boolean endOfBatch = false;
76
77 private final transient long nanoTime;
78
79
80 public static class Builder implements org.apache.logging.log4j.core.util.Builder<LogEvent> {
81
82 private String loggerFqcn;
83 private Marker marker;
84 private Level level;
85 private String loggerName;
86 private Message message;
87 private Throwable thrown;
88 private final MutableInstant instant = new MutableInstant();
89 private ThrowableProxy thrownProxy;
90 private StringMap contextData = createContextData((List<Property>) null);
91 private ThreadContext.ContextStack contextStack = ThreadContext.getImmutableStack();
92 private long threadId;
93 private String threadName;
94 private int threadPriority;
95 private StackTraceElement source;
96 private boolean includeLocation;
97 private boolean endOfBatch = false;
98 private long nanoTime;
99
100 public Builder() {
101 }
102
103 public Builder(final LogEvent other) {
104 Objects.requireNonNull(other);
105 if (other instanceof RingBufferLogEvent) {
106 ((RingBufferLogEvent) other).initializeBuilder(this);
107 return;
108 }
109 if (other instanceof MutableLogEvent) {
110 ((MutableLogEvent) other).initializeBuilder(this);
111 return;
112 }
113 this.loggerFqcn = other.getLoggerFqcn();
114 this.marker = other.getMarker();
115 this.level = other.getLevel();
116 this.loggerName = other.getLoggerName();
117 this.message = other.getMessage();
118 this.instant.initFrom(other.getInstant());
119 this.thrown = other.getThrown();
120 this.contextStack = other.getContextStack();
121 this.includeLocation = other.isIncludeLocation();
122 this.endOfBatch = other.isEndOfBatch();
123 this.nanoTime = other.getNanoTime();
124
125
126 if (other instanceof Log4jLogEvent) {
127 final Log4jLogEvent evt = (Log4jLogEvent) other;
128 this.contextData = evt.contextData;
129 this.thrownProxy = evt.thrownProxy;
130 this.source = evt.source;
131 this.threadId = evt.threadId;
132 this.threadName = evt.threadName;
133 this.threadPriority = evt.threadPriority;
134 } else {
135 if (other.getContextData() instanceof StringMap) {
136 this.contextData = (StringMap) other.getContextData();
137 } else {
138 if (this.contextData.isFrozen()) {
139 this.contextData = ContextDataFactory.createContextData();
140 } else {
141 this.contextData.clear();
142 }
143 this.contextData.putAll(other.getContextData());
144
145 }
146 this.thrownProxy = other.getThrownProxy();
147 this.source = other.getSource();
148 this.threadId = other.getThreadId();
149 this.threadName = other.getThreadName();
150 this.threadPriority = other.getThreadPriority();
151 }
152 }
153
154 public Builder setLevel(final Level level) {
155 this.level = level;
156 return this;
157 }
158
159 public Builder setLoggerFqcn(final String loggerFqcn) {
160 this.loggerFqcn = loggerFqcn;
161 return this;
162 }
163
164 public Builder setLoggerName(final String loggerName) {
165 this.loggerName = loggerName;
166 return this;
167 }
168
169 public Builder setMarker(final Marker marker) {
170 this.marker = marker;
171 return this;
172 }
173
174 public Builder setMessage(final Message message) {
175 this.message = message;
176 return this;
177 }
178
179 public Builder setThrown(final Throwable thrown) {
180 this.thrown = thrown;
181 return this;
182 }
183
184 public Builder setTimeMillis(final long timeMillis) {
185 this.instant.initFromEpochMilli(timeMillis, 0);
186 return this;
187 }
188
189 public Builder setInstant(final Instant instant) {
190 this.instant.initFrom(instant);
191 return this;
192 }
193
194 public Builder setThrownProxy(final ThrowableProxy thrownProxy) {
195 this.thrownProxy = thrownProxy;
196 return this;
197 }
198
199 @Deprecated
200 public Builder setContextMap(final Map<String, String> contextMap) {
201 contextData = ContextDataFactory.createContextData();
202 if (contextMap != null) {
203 for (final Map.Entry<String, String> entry : contextMap.entrySet()) {
204 contextData.putValue(entry.getKey(), entry.getValue());
205 }
206 }
207 return this;
208 }
209
210 public Builder setContextData(final StringMap contextData) {
211 this.contextData = contextData;
212 return this;
213 }
214
215 public Builder setContextStack(final ThreadContext.ContextStack contextStack) {
216 this.contextStack = contextStack;
217 return this;
218 }
219
220 public Builder setThreadId(final long threadId) {
221 this.threadId = threadId;
222 return this;
223 }
224
225 public Builder setThreadName(final String threadName) {
226 this.threadName = threadName;
227 return this;
228 }
229
230 public Builder setThreadPriority(final int threadPriority) {
231 this.threadPriority = threadPriority;
232 return this;
233 }
234
235 public Builder setSource(final StackTraceElement source) {
236 this.source = source;
237 return this;
238 }
239
240 public Builder setIncludeLocation(final boolean includeLocation) {
241 this.includeLocation = includeLocation;
242 return this;
243 }
244
245 public Builder setEndOfBatch(final boolean endOfBatch) {
246 this.endOfBatch = endOfBatch;
247 return this;
248 }
249
250
251
252
253
254
255
256 public Builder setNanoTime(final long nanoTime) {
257 this.nanoTime = nanoTime;
258 return this;
259 }
260
261 @Override
262 public Log4jLogEvent build() {
263 initTimeFields();
264 final Log4jLogEvent result = new Log4jLogEvent(loggerName, marker, loggerFqcn, level, message, thrown,
265 thrownProxy, contextData, contextStack, threadId, threadName, threadPriority, source,
266 instant.getEpochMillisecond(), instant.getNanoOfMillisecond(), nanoTime);
267 result.setIncludeLocation(includeLocation);
268 result.setEndOfBatch(endOfBatch);
269 return result;
270 }
271
272 private void initTimeFields() {
273 if (instant.getEpochMillisecond() == 0) {
274 instant.initFrom(CLOCK);
275 }
276 }
277 }
278
279
280
281
282
283 public static Builder newBuilder() {
284 return new Builder();
285 }
286
287 public Log4jLogEvent() {
288 this(Strings.EMPTY, null, Strings.EMPTY, null, null, (Throwable) null, null, null, null, 0, null,
289 0, null, CLOCK, nanoClock.nanoTime());
290 }
291
292
293
294
295
296 @Deprecated
297 public Log4jLogEvent(final long timestamp) {
298 this(Strings.EMPTY, null, Strings.EMPTY, null, null, (Throwable) null, null, null, null, 0, null,
299 0, null, timestamp, 0, nanoClock.nanoTime());
300 }
301
302
303
304
305
306
307
308
309
310
311
312 @Deprecated
313 public Log4jLogEvent(final String loggerName, final Marker marker, final String loggerFQCN, final Level level,
314 final Message message, final Throwable t) {
315 this(loggerName, marker, loggerFQCN, level, message, null, t);
316 }
317
318
319
320
321
322
323
324
325
326
327
328
329 public Log4jLogEvent(final String loggerName, final Marker marker, final String loggerFQCN, final Level level,
330 final Message message, final List<Property> properties, final Throwable t) {
331 this(loggerName, marker, loggerFQCN, level, message, t, null, createContextData(properties),
332 ThreadContext.getDepth() == 0 ? null : ThreadContext.cloneStack(),
333 0,
334 null,
335 0,
336 null,
337 CLOCK,
338 nanoClock.nanoTime());
339 }
340
341
342
343
344
345
346
347
348
349
350
351
352 public Log4jLogEvent(final String loggerName, final Marker marker, final String loggerFQCN,
353 final StackTraceElement source, final Level level, final Message message, final List<Property> properties,
354 final Throwable t) {
355 this(loggerName, marker, loggerFQCN, level, message, t, null, createContextData(properties),
356 ThreadContext.getDepth() == 0 ? null : ThreadContext.cloneStack(),
357 0,
358 null,
359 0,
360 source,
361 CLOCK,
362 nanoClock.nanoTime());
363 }
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380 @Deprecated
381 public Log4jLogEvent(final String loggerName, final Marker marker, final String loggerFQCN, final Level level,
382 final Message message, final Throwable t, final Map<String, String> mdc,
383 final ThreadContext.ContextStack ndc, final String threadName,
384 final StackTraceElement location, final long timestampMillis) {
385 this(loggerName, marker, loggerFQCN, level, message, t, null, createContextData(mdc), ndc, 0,
386 threadName, 0, location, timestampMillis, 0, nanoClock.nanoTime());
387 }
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406 @Deprecated
407 public static Log4jLogEvent createEvent(final String loggerName, final Marker marker, final String loggerFQCN,
408 final Level level, final Message message, final Throwable thrown,
409 final ThrowableProxy thrownProxy,
410 final Map<String, String> mdc, final ThreadContext.ContextStack ndc,
411 final String threadName, final StackTraceElement location,
412 final long timestamp) {
413 final Log4jLogEvent result = new Log4jLogEvent(loggerName, marker, loggerFQCN, level, message, thrown,
414 thrownProxy, createContextData(mdc), ndc, 0, threadName, 0, location, timestamp, 0, nanoClock.nanoTime());
415 return result;
416 }
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438 private Log4jLogEvent(final String loggerName, final Marker marker, final String loggerFQCN, final Level level,
439 final Message message, final Throwable thrown, final ThrowableProxy thrownProxy,
440 final StringMap contextData, final ThreadContext.ContextStack contextStack, final long threadId,
441 final String threadName, final int threadPriority, final StackTraceElement source,
442 final long timestampMillis, final int nanoOfMillisecond, final long nanoTime) {
443 this(loggerName, marker, loggerFQCN, level, message, thrown, thrownProxy, contextData, contextStack, threadId, threadName, threadPriority, source, nanoTime);
444 final long millis = message instanceof TimestampMessage
445 ? ((TimestampMessage) message).getTimestamp()
446 : timestampMillis;
447 instant.initFromEpochMilli(millis, nanoOfMillisecond);
448 }
449 private Log4jLogEvent(final String loggerName, final Marker marker, final String loggerFQCN, final Level level,
450 final Message message, final Throwable thrown, final ThrowableProxy thrownProxy,
451 final StringMap contextData, final ThreadContext.ContextStack contextStack, final long threadId,
452 final String threadName, final int threadPriority, final StackTraceElement source,
453 final Clock clock, final long nanoTime) {
454 this(loggerName, marker, loggerFQCN, level, message, thrown, thrownProxy, contextData, contextStack, threadId, threadName, threadPriority, source, nanoTime);
455 if (message instanceof TimestampMessage) {
456 instant.initFromEpochMilli(((TimestampMessage) message).getTimestamp(), 0);
457 } else {
458 instant.initFrom(clock);
459 }
460 }
461 private Log4jLogEvent(final String loggerName, final Marker marker, final String loggerFQCN, final Level level,
462 final Message message, final Throwable thrown, final ThrowableProxy thrownProxy,
463 final StringMap contextData, final ThreadContext.ContextStack contextStack, final long threadId,
464 final String threadName, final int threadPriority, final StackTraceElement source,
465 final long nanoTime) {
466 this.loggerName = loggerName;
467 this.marker = marker;
468 this.loggerFqcn = loggerFQCN;
469 this.level = level == null ? Level.OFF : level;
470 this.message = message;
471 this.thrown = thrown;
472 this.thrownProxy = thrownProxy;
473 this.contextData = contextData == null ? ContextDataFactory.createContextData() : contextData;
474 this.contextStack = contextStack == null ? ThreadContext.EMPTY_STACK : contextStack;
475 this.threadId = threadId;
476 this.threadName = threadName;
477 this.threadPriority = threadPriority;
478 this.source = source;
479 if (message instanceof LoggerNameAwareMessage) {
480 ((LoggerNameAwareMessage) message).setLoggerName(loggerName);
481 }
482 this.nanoTime = nanoTime;
483 }
484
485 private static StringMap createContextData(final Map<String, String> contextMap) {
486 final StringMap result = ContextDataFactory.createContextData();
487 if (contextMap != null) {
488 for (final Map.Entry<String, String> entry : contextMap.entrySet()) {
489 result.putValue(entry.getKey(), entry.getValue());
490 }
491 }
492 return result;
493 }
494
495 private static StringMap createContextData(final List<Property> properties) {
496 final StringMap reusable = ContextDataFactory.createContextData();
497 return CONTEXT_DATA_INJECTOR.injectContextData(properties, reusable);
498 }
499
500
501
502
503
504 public static NanoClock getNanoClock() {
505 return nanoClock;
506 }
507
508
509
510
511
512
513
514
515
516 public static void setNanoClock(final NanoClock nanoClock) {
517 Log4jLogEvent.nanoClock = Objects.requireNonNull(nanoClock, "NanoClock must be non-null");
518 StatusLogger.getLogger().trace("Using {} for nanosecond timestamps.", nanoClock.getClass().getSimpleName());
519 }
520
521
522
523
524
525 public Builder asBuilder() {
526 return new Builder(this);
527 }
528
529 @Override
530 public Log4jLogEvent toImmutable() {
531 if (getMessage() instanceof ReusableMessage) {
532 makeMessageImmutable();
533 }
534 return this;
535 }
536
537
538
539
540
541 @Override
542 public Level getLevel() {
543 return level;
544 }
545
546
547
548
549
550 @Override
551 public String getLoggerName() {
552 return loggerName;
553 }
554
555
556
557
558
559 @Override
560 public Message getMessage() {
561 return message;
562 }
563
564 public void makeMessageImmutable() {
565 message = new MementoMessage(message.getFormattedMessage(), message.getFormat(), message.getParameters());
566 }
567
568 @Override
569 public long getThreadId() {
570 if (threadId == 0) {
571 threadId = Thread.currentThread().getId();
572 }
573 return threadId;
574 }
575
576
577
578
579
580 @Override
581 public String getThreadName() {
582 if (threadName == null) {
583 threadName = Thread.currentThread().getName();
584 }
585 return threadName;
586 }
587
588 @Override
589 public int getThreadPriority() {
590 if (threadPriority == 0) {
591 threadPriority = Thread.currentThread().getPriority();
592 }
593 return threadPriority;
594 }
595
596
597
598
599 @Override
600 public long getTimeMillis() {
601 return instant.getEpochMillisecond();
602 }
603
604
605
606
607
608 @Override
609 public Instant getInstant() {
610 return instant;
611 }
612
613
614
615
616
617 @Override
618 public Throwable getThrown() {
619 return thrown;
620 }
621
622
623
624
625
626 @Override
627 public ThrowableProxy getThrownProxy() {
628 if (thrownProxy == null && thrown != null) {
629 thrownProxy = new ThrowableProxy(thrown);
630 }
631 return thrownProxy;
632 }
633
634
635
636
637
638
639 @Override
640 public Marker getMarker() {
641 return marker;
642 }
643
644
645
646
647
648 @Override
649 public String getLoggerFqcn() {
650 return loggerFqcn;
651 }
652
653
654
655
656
657
658 @Override
659 public ReadOnlyStringMap getContextData() {
660 return contextData;
661 }
662
663
664
665
666 @Override
667 public Map<String, String> getContextMap() {
668 return contextData.toMap();
669 }
670
671
672
673
674
675 @Override
676 public ThreadContext.ContextStack getContextStack() {
677 return contextStack;
678 }
679
680
681
682
683
684
685 @Override
686 public StackTraceElement getSource() {
687 if (source != null) {
688 return source;
689 }
690 if (loggerFqcn == null || !includeLocation) {
691 return null;
692 }
693 source = StackLocatorUtil.calcLocation(loggerFqcn);
694 return source;
695 }
696
697 @Override
698 public boolean isIncludeLocation() {
699 return includeLocation;
700 }
701
702 @Override
703 public void setIncludeLocation(final boolean includeLocation) {
704 this.includeLocation = includeLocation;
705 }
706
707 @Override
708 public boolean isEndOfBatch() {
709 return endOfBatch;
710 }
711
712 @Override
713 public void setEndOfBatch(final boolean endOfBatch) {
714 this.endOfBatch = endOfBatch;
715 }
716
717 @Override
718 public long getNanoTime() {
719 return nanoTime;
720 }
721
722
723
724
725
726 protected Object writeReplace() {
727 getThrownProxy();
728 return new LogEventProxy(this, this.includeLocation);
729 }
730
731
732
733
734
735
736
737
738
739
740 public static Serializable serialize(final LogEvent event, final boolean includeLocation) {
741 if (event instanceof Log4jLogEvent) {
742 event.getThrownProxy();
743 return new LogEventProxy((Log4jLogEvent) event, includeLocation);
744 }
745 return new LogEventProxy(event, includeLocation);
746 }
747
748
749
750
751
752
753
754
755
756
757 public static Serializable serialize(final Log4jLogEvent event, final boolean includeLocation) {
758 event.getThrownProxy();
759 return new LogEventProxy(event, includeLocation);
760 }
761
762 public static boolean canDeserialize(final Serializable event) {
763 return event instanceof LogEventProxy;
764 }
765
766 public static Log4jLogEvent deserialize(final Serializable event) {
767 Objects.requireNonNull(event, "Event cannot be null");
768 if (event instanceof LogEventProxy) {
769 final LogEventProxy proxy = (LogEventProxy) event;
770 final Log4jLogEvent result = new Log4jLogEvent(proxy.loggerName, proxy.marker,
771 proxy.loggerFQCN, proxy.level, proxy.message,
772 proxy.thrown, proxy.thrownProxy, proxy.contextData, proxy.contextStack, proxy.threadId,
773 proxy.threadName, proxy.threadPriority, proxy.source, proxy.timeMillis, proxy.nanoOfMillisecond,
774 proxy.nanoTime);
775 result.setEndOfBatch(proxy.isEndOfBatch);
776 result.setIncludeLocation(proxy.isLocationRequired);
777 return result;
778 }
779 throw new IllegalArgumentException("Event is not a serialized LogEvent: " + event.toString());
780 }
781
782 private void readObject(final ObjectInputStream stream) throws InvalidObjectException {
783 throw new InvalidObjectException("Proxy required");
784 }
785
786 public static LogEvent createMemento(final LogEvent logEvent) {
787 return new Log4jLogEvent.Builder(logEvent).build();
788 }
789
790
791
792
793
794
795 public static Log4jLogEvent createMemento(final LogEvent event, final boolean includeLocation) {
796 return deserialize(serialize(event, includeLocation));
797 }
798
799 @Override
800 public String toString() {
801 final StringBuilder sb = new StringBuilder();
802 final String n = loggerName.isEmpty() ? LoggerConfig.ROOT : loggerName;
803 sb.append("Logger=").append(n);
804 sb.append(" Level=").append(level.name());
805 sb.append(" Message=").append(message == null ? null : message.getFormattedMessage());
806 return sb.toString();
807 }
808
809 @Override
810 public boolean equals(final Object o) {
811 if (this == o) {
812 return true;
813 }
814 if (o == null || getClass() != o.getClass()) {
815 return false;
816 }
817
818 final Log4jLogEvent that = (Log4jLogEvent) o;
819
820 if (endOfBatch != that.endOfBatch) {
821 return false;
822 }
823 if (includeLocation != that.includeLocation) {
824 return false;
825 }
826 if (!instant.equals(that.instant)) {
827 return false;
828 }
829 if (nanoTime != that.nanoTime) {
830 return false;
831 }
832 if (loggerFqcn != null ? !loggerFqcn.equals(that.loggerFqcn) : that.loggerFqcn != null) {
833 return false;
834 }
835 if (level != null ? !level.equals(that.level) : that.level != null) {
836 return false;
837 }
838 if (source != null ? !source.equals(that.source) : that.source != null) {
839 return false;
840 }
841 if (marker != null ? !marker.equals(that.marker) : that.marker != null) {
842 return false;
843 }
844 if (contextData != null ? !contextData.equals(that.contextData) : that.contextData != null) {
845 return false;
846 }
847 if (!message.equals(that.message)) {
848 return false;
849 }
850 if (!loggerName.equals(that.loggerName)) {
851 return false;
852 }
853 if (contextStack != null ? !contextStack.equals(that.contextStack) : that.contextStack != null) {
854 return false;
855 }
856 if (threadId != that.threadId) {
857 return false;
858 }
859 if (threadName != null ? !threadName.equals(that.threadName) : that.threadName != null) {
860 return false;
861 }
862 if (threadPriority != that.threadPriority) {
863 return false;
864 }
865 if (thrown != null ? !thrown.equals(that.thrown) : that.thrown != null) {
866 return false;
867 }
868 if (thrownProxy != null ? !thrownProxy.equals(that.thrownProxy) : that.thrownProxy != null) {
869 return false;
870 }
871
872 return true;
873 }
874
875 @Override
876 public int hashCode() {
877
878 int result = loggerFqcn != null ? loggerFqcn.hashCode() : 0;
879 result = 31 * result + (marker != null ? marker.hashCode() : 0);
880 result = 31 * result + (level != null ? level.hashCode() : 0);
881 result = 31 * result + loggerName.hashCode();
882 result = 31 * result + message.hashCode();
883 result = 31 * result + instant.hashCode();
884 result = 31 * result + (int) (nanoTime ^ (nanoTime >>> 32));
885 result = 31 * result + (thrown != null ? thrown.hashCode() : 0);
886 result = 31 * result + (thrownProxy != null ? thrownProxy.hashCode() : 0);
887 result = 31 * result + (contextData != null ? contextData.hashCode() : 0);
888 result = 31 * result + (contextStack != null ? contextStack.hashCode() : 0);
889 result = 31 * result + (int) (threadId ^ (threadId >>> 32));
890 result = 31 * result + (threadName != null ? threadName.hashCode() : 0);
891 result = 31 * result + (threadPriority ^ (threadPriority >>> 32));
892 result = 31 * result + (source != null ? source.hashCode() : 0);
893 result = 31 * result + (includeLocation ? 1 : 0);
894 result = 31 * result + (endOfBatch ? 1 : 0);
895
896 return result;
897 }
898
899
900
901
902 static class LogEventProxy implements Serializable {
903
904 private static final long serialVersionUID = -8634075037355293699L;
905 private final String loggerFQCN;
906 private final Marker marker;
907 private final Level level;
908 private final String loggerName;
909
910 private final transient Message message;
911
912 private MarshalledObject<Message> marshalledMessage;
913
914 private String messageString;
915 private final long timeMillis;
916
917 private final int nanoOfMillisecond;
918 private final transient Throwable thrown;
919 private final ThrowableProxy thrownProxy;
920
921 private final StringMap contextData;
922 private final ThreadContext.ContextStack contextStack;
923
924 private final long threadId;
925 private final String threadName;
926
927 private final int threadPriority;
928 private final StackTraceElement source;
929 private final boolean isLocationRequired;
930 private final boolean isEndOfBatch;
931
932 private final transient long nanoTime;
933
934 public LogEventProxy(final Log4jLogEvent event, final boolean includeLocation) {
935 this.loggerFQCN = event.loggerFqcn;
936 this.marker = event.marker;
937 this.level = event.level;
938 this.loggerName = event.loggerName;
939 this.message = event.message instanceof ReusableMessage
940 ? memento((ReusableMessage) event.message)
941 : event.message;
942 this.timeMillis = event.instant.getEpochMillisecond();
943 this.nanoOfMillisecond = event.instant.getNanoOfMillisecond();
944 this.thrown = event.thrown;
945 this.thrownProxy = event.thrownProxy;
946 this.contextData = event.contextData;
947 this.contextStack = event.contextStack;
948 this.source = includeLocation ? event.getSource() : null;
949 this.threadId = event.getThreadId();
950 this.threadName = event.getThreadName();
951 this.threadPriority = event.getThreadPriority();
952 this.isLocationRequired = includeLocation;
953 this.isEndOfBatch = event.endOfBatch;
954 this.nanoTime = event.nanoTime;
955 }
956
957 public LogEventProxy(final LogEvent event, final boolean includeLocation) {
958 this.loggerFQCN = event.getLoggerFqcn();
959 this.marker = event.getMarker();
960 this.level = event.getLevel();
961 this.loggerName = event.getLoggerName();
962
963 final Message temp = event.getMessage();
964 message = temp instanceof ReusableMessage
965 ? memento((ReusableMessage) temp)
966 : temp;
967 this.timeMillis = event.getInstant().getEpochMillisecond();
968 this.nanoOfMillisecond = event.getInstant().getNanoOfMillisecond();
969 this.thrown = event.getThrown();
970 this.thrownProxy = event.getThrownProxy();
971 this.contextData = memento(event.getContextData());
972 this.contextStack = event.getContextStack();
973 this.source = includeLocation ? event.getSource() : null;
974 this.threadId = event.getThreadId();
975 this.threadName = event.getThreadName();
976 this.threadPriority = event.getThreadPriority();
977 this.isLocationRequired = includeLocation;
978 this.isEndOfBatch = event.isEndOfBatch();
979 this.nanoTime = event.getNanoTime();
980 }
981
982 private static Message memento(final ReusableMessage message) {
983 return message.memento();
984 }
985
986 private static StringMap memento(final ReadOnlyStringMap data) {
987 final StringMap result = ContextDataFactory.createContextData();
988 result.putAll(data);
989 return result;
990 }
991
992 private static MarshalledObject<Message> marshall(final Message msg) {
993 try {
994 return new MarshalledObject<>(msg);
995 } catch (final Exception ex) {
996 return null;
997 }
998 }
999
1000 private void writeObject(final java.io.ObjectOutputStream s) throws IOException {
1001 this.messageString = message.getFormattedMessage();
1002 this.marshalledMessage = marshall(message);
1003 s.defaultWriteObject();
1004 }
1005
1006
1007
1008
1009
1010 protected Object readResolve() {
1011 final Log4jLogEvent result = new Log4jLogEvent(loggerName, marker, loggerFQCN, level, message(), thrown,
1012 thrownProxy, contextData, contextStack, threadId, threadName, threadPriority, source, timeMillis,
1013 nanoOfMillisecond, nanoTime);
1014 result.setEndOfBatch(isEndOfBatch);
1015 result.setIncludeLocation(isLocationRequired);
1016 return result;
1017 }
1018
1019 private Message message() {
1020 if (marshalledMessage != null) {
1021 try {
1022 return marshalledMessage.get();
1023 } catch (final Exception ex) {
1024
1025 }
1026 }
1027 return new SimpleMessage(messageString);
1028 }
1029 }
1030 }