Author: rpopma
Date: Fri May 16 15:31:02 2014
New Revision: 1595233
URL: http://svn.apache.org/r1595233
Log:
Avoid paying the cost of constructing a ThrowableProxy until it is requested
because (a) the event is serialized or (b) someone explicitly called
#getThrowableProxy. (TBD: make similar changes to Log4jLogEvent?)
Modified:
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLogger.java
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventTranslator.java
logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerTest.java
logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/async/RingBufferLogEventTest.java
Modified:
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLogger.java
URL:
http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLogger.java?rev=1595233&r1=1595232&r2=1595233&view=diff
==============================================================================
---
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLogger.java
(original)
+++
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLogger.java
Fri May 16 15:31:02 2014
@@ -27,7 +27,6 @@ import org.apache.logging.log4j.core.Log
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Property;
import org.apache.logging.log4j.core.impl.Log4jLogEvent;
-import org.apache.logging.log4j.core.impl.ThrowableProxy;
import org.apache.logging.log4j.core.jmx.RingBufferAdmin;
import org.apache.logging.log4j.core.util.Clock;
import org.apache.logging.log4j.core.util.ClockFactory;
@@ -241,8 +240,8 @@ public class AsyncLogger extends Logger
}
final boolean includeLocation =
config.loggerConfig.isIncludeLocation();
info.translator.setValues(this, getName(), marker, fqcn, level,
message, //
- // thrown proxy or null
- thrown == null ? null : new ThrowableProxy(thrown), //
+ // don't construct ThrowableProxy until required
+ thrown, //
// config properties are taken care of in the EventHandler
// thread in the #actualAsyncLog method
Modified:
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
URL:
http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java?rev=1595233&r1=1595232&r2=1595233&view=diff
==============================================================================
---
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
(original)
+++
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
Fri May 16 15:31:02 2014
@@ -16,6 +16,7 @@
*/
package org.apache.logging.log4j.core.async;
+import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@@ -60,7 +61,8 @@ public class RingBufferLogEvent implemen
private String fqcn;
private Level level;
private Message message;
- private ThrowableProxy thrownProxy;
+ private transient Throwable thrown;
+ private ThrowableProxy thrownProxy;
private Map<String, String> contextMap;
private ContextStack contextStack;
private String threadName;
@@ -71,7 +73,7 @@ public class RingBufferLogEvent implemen
public void setValues(final AsyncLogger asyncLogger,
final String loggerName, final Marker marker, final
String fqcn,
- final Level level, final Message data, final
ThrowableProxy throwableProxy,
+ final Level level, final Message data, final Throwable
throwable,
final Map<String, String> map, final ContextStack
contextStack,
final String threadName, final StackTraceElement
location,
final long currentTimeMillis) {
@@ -81,7 +83,8 @@ public class RingBufferLogEvent implemen
this.fqcn = fqcn;
this.level = level;
this.message = data;
- this.thrownProxy = throwableProxy;
+ this.thrown = throwable;
+ this.thrownProxy = null;
this.contextMap = map;
this.contextStack = contextStack;
this.threadName = threadName;
@@ -162,11 +165,23 @@ public class RingBufferLogEvent implemen
@Override
public Throwable getThrown() {
- return thrownProxy == null ? null : thrownProxy.getThrowable();
+ // after deserialization, thrown is null but thrownProxy may be
non-null
+ if (thrown == null) {
+ if (thrownProxy != null) {
+ thrown = thrownProxy.getThrowable();
+ }
+ }
+ return thrown;
}
@Override
public ThrowableProxy getThrownProxy() {
+ // lazily instantiate the (expensive) ThrowableProxy
+ if (thrownProxy == null) {
+ if (thrown != null) {
+ thrownProxy = new ThrowableProxy(thrown);
+ }
+ }
return this.thrownProxy;
}
@@ -250,4 +265,9 @@ public class RingBufferLogEvent implemen
0 // currentTimeMillis
);
}
+
+ private void writeObject(java.io.ObjectOutputStream out) throws
IOException {
+ getThrownProxy(); // initialize the ThrowableProxy before
serializing
+ out.defaultWriteObject();
+ }
}
Modified:
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventTranslator.java
URL:
http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventTranslator.java?rev=1595233&r1=1595232&r2=1595233&view=diff
==============================================================================
---
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventTranslator.java
(original)
+++
logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventTranslator.java
Fri May 16 15:31:02 2014
@@ -21,7 +21,6 @@ import java.util.Map;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.ThreadContext.ContextStack;
-import org.apache.logging.log4j.core.impl.ThrowableProxy;
import org.apache.logging.log4j.message.Message;
import com.lmax.disruptor.EventTranslator;
@@ -41,7 +40,7 @@ public class RingBufferLogEventTranslato
private String fqcn;
private Level level;
private Message message;
- private ThrowableProxy thrownProxy;
+ private Throwable thrown;
private Map<String, String> contextMap;
private ContextStack contextStack;
private String threadName;
@@ -52,7 +51,7 @@ public class RingBufferLogEventTranslato
@Override
public void translateTo(final RingBufferLogEvent event, final long
sequence) {
event.setValues(asyncLogger, loggerName, marker, fqcn, level, message,
- thrownProxy, contextMap, contextStack, threadName, location,
+ thrown, contextMap, contextStack, threadName, location,
currentTimeMillis);
clear();
}
@@ -79,7 +78,7 @@ public class RingBufferLogEventTranslato
public void setValues(final AsyncLogger asyncLogger, final String
loggerName,
final Marker marker, final String fqcn, final Level level, final
Message message,
- final ThrowableProxy thrownProxy, final Map<String, String>
contextMap,
+ final Throwable thrown, final Map<String, String> contextMap,
final ContextStack contextStack, final String threadName,
final StackTraceElement location, final long currentTimeMillis) {
this.asyncLogger = asyncLogger;
@@ -88,7 +87,7 @@ public class RingBufferLogEventTranslato
this.fqcn = fqcn;
this.level = level;
this.message = message;
- this.thrownProxy = thrownProxy;
+ this.thrown = thrown;
this.contextMap = contextMap;
this.contextStack = contextStack;
this.threadName = threadName;
Modified:
logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerTest.java
URL:
http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerTest.java?rev=1595233&r1=1595232&r2=1595233&view=diff
==============================================================================
---
logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerTest.java
(original)
+++
logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerTest.java
Fri May 16 15:31:02 2014
@@ -55,7 +55,7 @@ public class AsyncLoggerTest {
f.delete();
final Logger log = LogManager.getLogger("com.foo.Bar");
final String msg = "Async logger msg";
- log.info(msg);
+ log.info(msg, new InternalError("this is not a real error"));
((LifeCycle) LogManager.getContext()).stop(); // stop async thread
final BufferedReader reader = new BufferedReader(new FileReader(f));
Modified:
logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/async/RingBufferLogEventTest.java
URL:
http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/async/RingBufferLogEventTest.java?rev=1595233&r1=1595232&r2=1595233&view=diff
==============================================================================
---
logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/async/RingBufferLogEventTest.java
(original)
+++
logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/async/RingBufferLogEventTest.java
Fri May 16 15:31:02 2014
@@ -17,9 +17,13 @@
package org.apache.logging.log4j.core.async;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.*;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
import java.util.Map;
import org.apache.logging.log4j.Level;
@@ -27,6 +31,7 @@ import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.ThreadContext.ContextStack;
import org.apache.logging.log4j.core.impl.ThrowableProxy;
import org.apache.logging.log4j.message.Message;
+import org.apache.logging.log4j.message.SimpleMessage;
import org.apache.logging.log4j.message.TimestampMessage;
import org.junit.Test;
@@ -43,7 +48,7 @@ public class RingBufferLogEventTest {
String fqcn = null;
Level level = null;
Message data = null;
- ThrowableProxy t = null;
+ Throwable t = null;
Map<String, String> map = null;
ContextStack contextStack = null;
String threadName = null;
@@ -62,7 +67,7 @@ public class RingBufferLogEventTest {
String fqcn = null;
Level level = null;
Message data = null;
- ThrowableProxy t = null;
+ Throwable t = null;
Map<String, String> map = null;
ContextStack contextStack = null;
String threadName = null;
@@ -81,7 +86,7 @@ public class RingBufferLogEventTest {
String fqcn = null;
Level level = null;
Message data = null;
- ThrowableProxy t = null;
+ Throwable t = null;
Map<String, String> map = null;
ContextStack contextStack = null;
String threadName = null;
@@ -136,7 +141,7 @@ public class RingBufferLogEventTest {
String fqcn = null;
Level level = null;
Message data = new TimeMsg("", 567);
- ThrowableProxy t = null;
+ Throwable t = null;
Map<String, String> map = null;
ContextStack contextStack = null;
String threadName = null;
@@ -147,4 +152,40 @@ public class RingBufferLogEventTest {
assertEquals(567, evt.getTimeMillis());
}
+ @Test
+ public void testSerializationDeserialization() throws IOException,
ClassNotFoundException {
+ RingBufferLogEvent evt = new RingBufferLogEvent();
+ String loggerName = "logger.name";
+ Marker marker = null;
+ String fqcn = "f.q.c.n";
+ Level level = Level.TRACE;
+ Message data = new SimpleMessage("message");
+ Throwable t = new InternalError("not a real error");
+ Map<String, String> map = null;
+ ContextStack contextStack = null;
+ String threadName = "main";
+ StackTraceElement location = null;
+ long currentTimeMillis = 12345;
+ evt.setValues(null, loggerName, marker, fqcn, level, data, t, map,
+ contextStack, threadName, location, currentTimeMillis);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream out = new ObjectOutputStream(baos);
+ out.writeObject(evt);
+
+ ObjectInputStream in = new ObjectInputStream(new
ByteArrayInputStream(baos.toByteArray()));
+ RingBufferLogEvent other = (RingBufferLogEvent) in.readObject();
+ assertEquals(loggerName, other.getLoggerName());
+ assertEquals(marker, other.getMarker());
+ assertEquals(fqcn, other.getLoggerFQCN());
+ assertEquals(level, other.getLevel());
+ assertEquals(data, other.getMessage());
+ assertNull("null after serialization", other.getThrown());
+ assertEquals(new ThrowableProxy(t), other.getThrownProxy());
+ assertEquals(map, other.getContextMap());
+ assertEquals(contextStack, other.getContextStack());
+ assertEquals(threadName, other.getThreadName());
+ assertEquals(location, other.getSource());
+ assertEquals(currentTimeMillis, other.getTimeMillis());
+ }
}