You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rp...@apache.org on 2016/04/14 16:51:10 UTC

[2/2] logging-log4j2 git commit: LOG4J2-1334 added MutableLogEvent.clear() and initFrom() methods to prepare for this class being used in the AsyncLoggerConfigDisruptor ring buffer

LOG4J2-1334 added MutableLogEvent.clear() and initFrom() methods to prepare for this class being used in the AsyncLoggerConfigDisruptor ring buffer


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/35d06895
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/35d06895
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/35d06895

Branch: refs/heads/master
Commit: 35d06895f9251e149d3a82066750a619699e5c7f
Parents: d2a79e0
Author: rpopma <rp...@apache.org>
Authored: Thu Apr 14 23:51:08 2016 +0900
Committer: rpopma <rp...@apache.org>
Committed: Thu Apr 14 23:51:08 2016 +0900

----------------------------------------------------------------------
 .../log4j/core/impl/MutableLogEvent.java        | 171 +++++++++++++++++--
 1 file changed, 155 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/35d06895/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java
index 876ce58..5330c34 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java
@@ -4,7 +4,12 @@ import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.Marker;
 import org.apache.logging.log4j.ThreadContext;
 import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.util.Constants;
 import org.apache.logging.log4j.message.Message;
+import org.apache.logging.log4j.message.ReusableMessage;
+import org.apache.logging.log4j.message.SimpleMessage;
+import org.apache.logging.log4j.util.PropertiesUtil;
+import org.apache.logging.log4j.util.Strings;
 
 import java.io.InvalidObjectException;
 import java.io.ObjectInputStream;
@@ -13,7 +18,12 @@ import java.util.Map;
 /**
  * Mutable implementation of the {@code LogEvent} interface.
  */
-public class MutableLogEvent implements LogEvent {
+public class MutableLogEvent implements LogEvent, ReusableMessage {
+    private static final int INITIAL_REUSABLE_MESSAGE_SIZE = size("log4j.initialReusableMsgSize", 128);
+    private static final int MAX_REUSABLE_MESSAGE_SIZE = size("log4j.maxReusableMsgSize", (128 * 2 + 2) * 2 + 2);
+    private static final Object[] PARAMS = new Object[0];
+    private static final Message EMPTY = new SimpleMessage(Strings.EMPTY);
+
     private String loggerFqcn;
     private Marker marker;
     private Level level;
@@ -29,8 +39,63 @@ public class MutableLogEvent implements LogEvent {
     private boolean includeLocation;
     private boolean endOfBatch = false;
     private long nanoTime;
-    // private ThrowableProxy thrownProxy;
-    // private StackTraceElement source;
+    private ThrowableProxy thrownProxy;
+    private StackTraceElement source;
+    private StringBuilder messageText;
+
+    private static int size(final String property, final int defaultValue) {
+        return PropertiesUtil.getProperties().getIntegerProperty(property, defaultValue);
+    }
+
+    /**
+     * Initialize the fields of this {@code MutableLogEvent} from another event.
+     * Similar in purpose and usage as {@link org.apache.logging.log4j.core.impl.Log4jLogEvent.LogEventProxy},
+     * but a mutable version.
+     * <p>
+     * This method is used on async logger ringbuffer slots holding MutableLogEvent objects in each slot.
+     * </p>
+     *
+     * @param event the event to copy data from
+     */
+    public void initFrom(final LogEvent event) {
+        this.loggerFqcn = event.getLoggerFqcn();
+        this.marker = event.getMarker();
+        this.level = event.getLevel();
+        this.loggerName = event.getLoggerName();
+        this.timeMillis = event.getTimeMillis();
+        this.thrown = event.getThrown();
+        this.thrownProxy = event.getThrownProxy();
+        this.contextMap = event.getContextMap();
+        this.contextStack = event.getContextStack();
+        this.source = event.isIncludeLocation() ? event.getSource() : null;
+        this.threadId = event.getThreadId();
+        this.threadName = event.getThreadName();
+        this.threadPriority = event.getThreadPriority();
+        this.endOfBatch = event.isEndOfBatch();
+        this.nanoTime = event.getNanoTime();
+        setMessage(event.getMessage());
+    }
+
+    public void clear() {
+        loggerFqcn = null;
+        marker = null;
+        level = null;
+        loggerName = null;
+        message = null;
+        thrown = null;
+        thrownProxy = null;
+        source = null;
+        contextMap = null;
+        contextStack = null;
+        threadName = null;
+        // primitive fields that cannot be cleared:
+        //timeMillis;
+        //threadId;
+        //threadPriority;
+        //includeLocation;
+        //endOfBatch;
+        //nanoTime;
+    }
 
     @Override
     public String getLoggerFqcn() {
@@ -70,11 +135,72 @@ public class MutableLogEvent implements LogEvent {
 
     @Override
     public Message getMessage() {
+        if (message == null) {
+            return (messageText == null) ? EMPTY : this;
+        }
         return message;
     }
 
-    public void setMessage(Message message) {
-        this.message = message;
+    public void setMessage(final Message msg) {
+        if (msg instanceof ReusableMessage) {
+            ((ReusableMessage) msg).formatTo(getMessageTextForWriting());
+        } else {
+            // if the Message instance is reused, there is no point in freezing its message here
+            if (!Constants.FORMAT_MESSAGES_IN_BACKGROUND && msg != null) { // LOG4J2-898: user may choose
+                msg.getFormattedMessage(); // LOG4J2-763: ask message to freeze parameters
+            }
+            this.message = msg;
+        }
+    }
+
+    private StringBuilder getMessageTextForWriting() {
+        if (messageText == null) {
+            // Should never happen:
+            // only happens if user logs a custom reused message when Constants.ENABLE_THREADLOCALS is false
+            messageText = new StringBuilder(INITIAL_REUSABLE_MESSAGE_SIZE);
+        }
+        messageText.setLength(0);
+        return messageText;
+    }
+
+    /**
+     * @see ReusableMessage#getFormattedMessage()
+     */
+    @Override
+    public String getFormattedMessage() {
+        return messageText.toString();
+    }
+
+    /**
+     * @see ReusableMessage#getFormat()
+     */
+    @Override
+    public String getFormat() {
+        return null;
+    }
+
+    /**
+     * @see ReusableMessage#getParameters()
+     */
+    @Override
+    public Object[] getParameters() {
+        return PARAMS;
+    }
+
+    /**
+     * @see ReusableMessage#getThrowable()
+     */
+    @Override
+    public Throwable getThrowable() {
+        return getThrown();
+    }
+
+    /**
+     * @see ReusableMessage#formatTo(StringBuilder)
+     */
+    @Override
+    public void formatTo(final StringBuilder buffer) {
+        buffer.append(messageText);
     }
 
     @Override
@@ -95,12 +221,33 @@ public class MutableLogEvent implements LogEvent {
         this.timeMillis = timeMillis;
     }
 
+    /**
+     * Returns the ThrowableProxy associated with the event, or null.
+     * @return The ThrowableProxy associated with the event.
+     */
     @Override
     public ThrowableProxy getThrownProxy() {
-        if (thrown != null) {
-            return new ThrowableProxy(thrown);
+        if (thrownProxy == null && thrown != null) {
+            thrownProxy = new ThrowableProxy(thrown);
         }
-        return null;
+        return thrownProxy;
+    }
+
+    /**
+     * Returns the StackTraceElement for the caller. This will be the entry that occurs right
+     * before the first occurrence of FQCN as a class name.
+     * @return the StackTraceElement for the caller.
+     */
+    @Override
+    public StackTraceElement getSource() {
+        if (source != null) {
+            return source;
+        }
+        if (loggerFqcn == null || !includeLocation) {
+            return null;
+        }
+        source = Log4jLogEvent.calcLocation(loggerFqcn);
+        return source;
     }
 
     @Override
@@ -149,14 +296,6 @@ public class MutableLogEvent implements LogEvent {
     }
 
     @Override
-    public StackTraceElement getSource() {
-        if (loggerFqcn == null || !includeLocation) {
-            return null;
-        }
-        return Log4jLogEvent.calcLocation(loggerFqcn);
-    }
-
-    @Override
     public boolean isIncludeLocation() {
         return includeLocation;
     }