Hang on! Doesn't this have large performance impact? You're creating the ThrowableProxy, with all the reflection and stack trace walking etc in the critical path - in the application thread that calls Logger.log(msg, ex). So we're always paying the cost of constructing an (expensive) ThrowableProxy, but how often is it actually used?
Can't we create a ThrowableProxy only when it is needed? And for async loggers/appenders, do the construction in the consumer thread instead? The simplest way to do this would be to keep the instance variable a normal Throwable, and only construct and return a new ThrownProxy(thrown) when the event.getThrownProxy() method is called. That should be the implementation for all LogEvent implementation classes IMHO. Remko On Sat, May 10, 2014 at 4:16 AM, <ggreg...@apache.org> wrote: > Author: ggregory > Date: Fri May 9 19:16:53 2014 > New Revision: 1593598 > > URL: http://svn.apache.org/r1593598 > Log: > The RingBufferLogEvent should track a ThrowableProxy instead of a > Throwable. This relates to the application listening side of Log4j events > from a JSON or XML source (another app in another JVM). > > 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/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=1593598&r1=1593597&r2=1593598&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 9 19:16:53 2014 > @@ -30,6 +30,7 @@ import org.apache.logging.log4j.core.hel > import org.apache.logging.log4j.core.helpers.ClockFactory; > import org.apache.logging.log4j.core.helpers.Loader; > 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.message.Message; > import org.apache.logging.log4j.message.MessageFactory; > @@ -224,7 +225,7 @@ public class AsyncLogger extends Logger > } > > @Override > - public void logMessage(final String fqcn, final Level level, final > Marker marker, final Message message, final Throwable t) { > + public void logMessage(final String fqcn, final Level level, final > Marker marker, final Message message, final Throwable thrown) { > Info info = threadlocalInfo.get(); > if (info == null) { > info = new Info(new RingBufferLogEventTranslator(), > Thread.currentThread().getName(), false); > @@ -235,11 +236,13 @@ public class AsyncLogger extends Logger > // being logged calls Logger.log() from its toString() method > if (info.isAppenderThread && > disruptor.getRingBuffer().remainingCapacity() == 0) { > // bypass RingBuffer and invoke Appender directly > - config.loggerConfig.log(getName(), fqcn, marker, level, > message, t); > + config.loggerConfig.log(getName(), fqcn, marker, level, > message, thrown); > return; > } > final boolean includeLocation = > config.loggerConfig.isIncludeLocation(); > - info.translator.setValues(this, getName(), marker, fqcn, level, > message, t, // > + info.translator.setValues(this, getName(), marker, fqcn, level, > message, // > + // thrown proxy or null > + thrown == null ? null : new ThrowableProxy(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=1593598&r1=1593597&r2=1593598&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 9 19:16:53 2014 > @@ -59,8 +59,7 @@ public class RingBufferLogEvent implemen > private String fqcn; > private Level level; > private Message message; > - // TODO: Need to track a ThrowableProxy instead of a Throwable. > - private Throwable thrown; > + private ThrowableProxy thrownProxy; > private Map<String, String> contextMap; > private ContextStack contextStack; > private String threadName; > @@ -71,7 +70,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 > Throwable t, > + final Level level, final Message data, final > ThrowableProxy throwableProxy, > final Map<String, String> map, final ContextStack > contextStack, > final String threadName, final StackTraceElement > location, > final long currentTimeMillis) { > @@ -81,7 +80,7 @@ public class RingBufferLogEvent implemen > this.fqcn = fqcn; > this.level = level; > this.message = data; > - this.thrown = t; > + this.thrownProxy = throwableProxy; > this.contextMap = map; > this.contextStack = contextStack; > this.threadName = threadName; > @@ -162,12 +161,12 @@ public class RingBufferLogEvent implemen > > @Override > public Throwable getThrown() { > - return thrown; > + return thrownProxy == null ? null : > thrownProxy.getThrowable(); > } > > @Override > public ThrowableProxy getThrownProxy() { > - return new ThrowableProxy(this.thrown); > + return this.thrownProxy; > } > > @Override > > 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=1593598&r1=1593597&r2=1593598&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 9 19:16:53 2014 > @@ -21,6 +21,7 @@ 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; > @@ -40,7 +41,7 @@ public class RingBufferLogEventTranslato > private String fqcn; > private Level level; > private Message message; > - private Throwable thrown; > + private ThrowableProxy thrownProxy; > private Map<String, String> contextMap; > private ContextStack contextStack; > private String threadName; > @@ -51,7 +52,7 @@ public class RingBufferLogEventTranslato > @Override > public void translateTo(final RingBufferLogEvent event, final long > sequence) { > event.setValues(asyncLogger, loggerName, marker, fqcn, level, > message, > - thrown, contextMap, contextStack, threadName, location, > + thrownProxy, contextMap, contextStack, threadName, > location, > currentTimeMillis); > clear(); > } > @@ -78,7 +79,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 Throwable thrown, final Map<String, String> contextMap, > + final ThrowableProxy thrownProxy, final Map<String, String> > contextMap, > final ContextStack contextStack, final String threadName, > final StackTraceElement location, final long > currentTimeMillis) { > this.asyncLogger = asyncLogger; > @@ -87,7 +88,7 @@ public class RingBufferLogEventTranslato > this.fqcn = fqcn; > this.level = level; > this.message = message; > - this.thrown = thrown; > + this.thrownProxy = thrownProxy; > 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/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=1593598&r1=1593597&r2=1593598&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 9 19:16:53 2014 > @@ -24,6 +24,7 @@ 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 org.apache.logging.log4j.message.TimestampMessage; > import org.junit.Test; > @@ -41,7 +42,7 @@ public class RingBufferLogEventTest { > String fqcn = null; > Level level = null; > Message data = null; > - Throwable t = null; > + ThrowableProxy t = null; > Map<String, String> map = null; > ContextStack contextStack = null; > String threadName = null; > @@ -60,7 +61,7 @@ public class RingBufferLogEventTest { > String fqcn = null; > Level level = null; > Message data = null; > - Throwable t = null; > + ThrowableProxy t = null; > Map<String, String> map = null; > ContextStack contextStack = null; > String threadName = null; > @@ -79,7 +80,7 @@ public class RingBufferLogEventTest { > String fqcn = null; > Level level = null; > Message data = null; > - Throwable t = null; > + ThrowableProxy t = null; > Map<String, String> map = null; > ContextStack contextStack = null; > String threadName = null; > @@ -134,7 +135,7 @@ public class RingBufferLogEventTest { > String fqcn = null; > Level level = null; > Message data = new TimeMsg("", 567); > - Throwable t = null; > + ThrowableProxy t = null; > Map<String, String> map = null; > ContextStack contextStack = null; > String threadName = null; > > >