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 org.apache.logging.log4j.Level;
20 import org.apache.logging.log4j.ThreadContext;
21 import org.apache.logging.log4j.Marker;
22 import org.apache.logging.log4j.core.LogEvent;
23 import org.apache.logging.log4j.core.config.Property;
24 import org.apache.logging.log4j.message.LoggerNameAwareMessage;
25 import org.apache.logging.log4j.message.Message;
26 import org.apache.logging.log4j.message.TimestampMessage;
27
28 import java.io.InvalidObjectException;
29 import java.io.ObjectInputStream;
30 import java.io.Serializable;
31 import java.util.List;
32 import java.util.Map;
33
34
35
36
37 public class Log4jLogEvent implements LogEvent, Serializable {
38
39 private static final long serialVersionUID = -1351367343806656055L;
40 private static final String NOT_AVAIL = "?";
41 private final String fqcnOfLogger;
42 private final Marker marker;
43 private final Level level;
44 private final String name;
45 private final Message message;
46 private final long timestamp;
47 private final ThrowableProxy throwable;
48 private final Map<String, String> mdc;
49 private ThreadContext.ContextStack ndc;
50 private String threadName = null;
51 private StackTraceElement location;
52
53
54
55
56
57
58
59
60
61
62 public Log4jLogEvent(String loggerName, Marker marker, String fqcn, Level level, Message message, Throwable t) {
63 this(loggerName, marker, fqcn, level, message, null, t);
64 }
65
66
67
68
69
70
71
72
73
74
75 public Log4jLogEvent(String loggerName, Marker marker, String fqcn, Level level, Message message,
76 List<Property> properties, Throwable t) {
77 this(loggerName, marker, fqcn, level, message, t,
78 createMap(properties),
79 ThreadContext.getDepth() == 0 ? null : ThreadContext.cloneStack(), null,
80 null, System.currentTimeMillis());
81 }
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97 public Log4jLogEvent(String loggerName, Marker marker, String fqcn, Level level, Message message, Throwable t,
98 Map<String, String> mdc, ThreadContext.ContextStack ndc, String threadName,
99 StackTraceElement location, long timestamp) {
100 name = loggerName;
101 this.marker = marker;
102 this.fqcnOfLogger = fqcn;
103 this.level = level;
104 this.message = message;
105 this.throwable = (t == null ? null : (t instanceof ThrowableProxy ? (ThrowableProxy)t : new ThrowableProxy(t)));
106 this.mdc = mdc;
107 this.ndc = ndc;
108 this.timestamp = message instanceof TimestampMessage ? ((TimestampMessage) message).getTimestamp() : timestamp;
109 this.threadName = threadName;
110 this.location = location;
111 if (message != null && message instanceof LoggerNameAwareMessage) {
112 ((LoggerNameAwareMessage) message).setLoggerName(name);
113 }
114 }
115
116 private static Map<String, String> createMap(List<Property> properties) {
117 if (ThreadContext.isEmpty() && (properties == null || properties.size() == 0)) {
118 return null;
119 }
120 if (properties == null || properties.size() == 0) {
121 return ThreadContext.getImmutableContext();
122 }
123 Map<String, String> map = ThreadContext.getContext();
124
125 for (Property prop : properties) {
126 if (!map.containsKey(prop.getName())) {
127 map.put(prop.getName(), prop.getValue());
128 }
129 }
130 return new ThreadContext.ImmutableMap(map);
131 }
132
133
134
135
136
137 public Level getLevel() {
138 return level;
139 }
140
141
142
143
144
145 public String getLoggerName() {
146 return name;
147 }
148
149
150
151
152
153 public Message getMessage() {
154 return message;
155 }
156
157
158
159
160
161 public String getThreadName() {
162 if (threadName == null) {
163 threadName = Thread.currentThread().getName();
164 }
165 return threadName;
166 }
167
168
169
170
171
172 public long getMillis() {
173 return timestamp;
174 }
175
176
177
178
179
180 public Throwable getThrown() {
181 return throwable;
182 }
183
184
185
186
187
188 public Marker getMarker() {
189 return marker;
190 }
191
192
193
194
195
196 public String getFQCN() {
197 return fqcnOfLogger;
198 }
199
200
201
202
203
204 public Map<String, String> getContextMap() {
205 return mdc == null ? ThreadContext.EMPTY_MAP : mdc;
206 }
207
208
209
210
211
212 public ThreadContext.ContextStack getContextStack() {
213 return ndc == null ? ThreadContext.EMPTY_STACK : ndc;
214 }
215
216
217
218
219
220
221 public StackTraceElement getSource() {
222 if (fqcnOfLogger == null) {
223 return null;
224 }
225 if (location == null) {
226 StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
227 boolean next = false;
228 for (StackTraceElement element : stackTrace) {
229 String className = element.getClassName();
230 if (next) {
231 if (fqcnOfLogger.equals(className)) {
232 continue;
233 }
234 location = element;
235 break;
236 }
237
238 if (fqcnOfLogger.equals(className)) {
239 next = true;
240 } else if (NOT_AVAIL.equals(className)) {
241 break;
242 }
243 }
244 }
245
246 return location;
247 }
248
249
250
251
252
253 protected Object writeReplace() {
254 return new LogEventProxy(this);
255 }
256
257 public static Serializable serialize(Log4jLogEvent event) {
258 return new LogEventProxy(event);
259 }
260
261 public static Log4jLogEvent deserialize(Serializable event) {
262 if (event == null) {
263 throw new NullPointerException("Event cannot be null");
264 }
265 if (event instanceof LogEventProxy) {
266 LogEventProxy proxy = (LogEventProxy) event;
267 return new Log4jLogEvent(proxy.name, proxy.marker, proxy.fqcnOfLogger, proxy.level, proxy.message,
268 proxy.throwable, proxy.mdc, proxy.ndc, proxy.threadName, proxy.location, proxy.timestamp);
269 }
270 throw new IllegalArgumentException("Event is not a serialized LogEvent: " + event.toString());
271 }
272
273 private void readObject(ObjectInputStream stream) throws InvalidObjectException {
274 throw new InvalidObjectException("Proxy required");
275 }
276
277 @Override
278 public String toString() {
279 StringBuilder sb = new StringBuilder();
280 String n = name.length() == 0 ? "root" : name;
281 sb.append("Logger=").append(n);
282 sb.append(" Level=").append(level.name());
283 sb.append(" Message").append(message.getFormattedMessage());
284 return sb.toString();
285 }
286
287
288
289
290 private static class LogEventProxy implements Serializable {
291
292 private static final long serialVersionUID = -7139032940312647146L;
293 private final String fqcnOfLogger;
294 private final Marker marker;
295 private final Level level;
296 private final String name;
297 private final Message message;
298 private final long timestamp;
299 private final Throwable throwable;
300 private final Map<String, String> mdc;
301 private ThreadContext.ContextStack ndc;
302 private String threadName;
303 private StackTraceElement location;
304
305 public LogEventProxy(Log4jLogEvent event) {
306 this.fqcnOfLogger = event.fqcnOfLogger;
307 this.marker = event.marker;
308 this.level = event.level;
309 this.name = event.name;
310 this.message = event.message;
311 this.timestamp = event.timestamp;
312 this.throwable = event.throwable;
313 this.mdc = event.mdc;
314 this.ndc = event.ndc;
315 this.location = event.getSource();
316 this.threadName = event.getThreadName();
317 }
318
319
320
321
322
323 protected Object readResolve() {
324 return new Log4jLogEvent(name, marker, fqcnOfLogger, level, message, throwable, mdc, ndc, threadName,
325 location, timestamp);
326 }
327
328 }
329
330 }