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;
}