Repository: logging-log4j2 Updated Branches: refs/heads/master 78c43c5b5 -> 0738cf970
LOG4J2-2307: RingBufferLogEvent and MutableLogEvent memento to MementoLogEvent MementoLogEvent provides the original format string and parameters in addition to the formatted text. Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/0738cf97 Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/0738cf97 Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/0738cf97 Branch: refs/heads/master Commit: 0738cf970c111a07a7307549b8c16af4d44af8a4 Parents: 78c43c5 Author: Carter Kozak <cko...@apache.org> Authored: Mon Apr 2 23:49:09 2018 -0400 Committer: Carter Kozak <cko...@apache.org> Committed: Sat Apr 7 10:01:53 2018 -0400 ---------------------------------------------------------------------- .../log4j/core/async/RingBufferLogEvent.java | 3 +- .../logging/log4j/core/impl/MementoMessage.java | 83 ++++++++++++++++++++ .../log4j/core/impl/MutableLogEvent.java | 2 +- .../apache/logging/log4j/core/LoggerTest.java | 11 ++- .../core/async/RingBufferLogEventTest.java | 26 ++++++ .../log4j/core/impl/MutableLogEventTest.java | 4 + src/changes/changes.xml | 3 + 7 files changed, 124 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0738cf97/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java index 27e7197..5e24d14 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java @@ -26,6 +26,7 @@ import org.apache.logging.log4j.ThreadContext.ContextStack; import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.core.impl.ContextDataFactory; import org.apache.logging.log4j.core.impl.Log4jLogEvent; +import org.apache.logging.log4j.core.impl.MementoMessage; import org.apache.logging.log4j.core.impl.ThrowableProxy; import org.apache.logging.log4j.core.time.Clock; import org.apache.logging.log4j.core.time.NanoClock; @@ -318,7 +319,7 @@ public class RingBufferLogEvent implements LogEvent, ReusableMessage, CharSequen private Message getNonNullImmutableMessage() { - return message != null ? message : new SimpleMessage(String.valueOf(messageText)); + return message != null ? message : new MementoMessage(String.valueOf(messageText), messageFormat, getParameters()); } @Override http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0738cf97/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MementoMessage.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MementoMessage.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MementoMessage.java new file mode 100644 index 0000000..c867ce4 --- /dev/null +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MementoMessage.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache license, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the license for the specific language governing permissions and + * limitations under the license. + */ +package org.apache.logging.log4j.core.impl; + +import org.apache.logging.log4j.message.Message; +import org.apache.logging.log4j.util.StringBuilderFormattable; + +import java.util.Arrays; + +/** + * <em>Consider this class private.</em> + * + * {@link MementoMessage} is intended to be used when we need to make an + * immutable copy of a {@link Message} without forgetting the original + * {@link Message#getFormat()} and {@link Message#getParameters()} values. + * + * @since 3.0 + */ +public final class MementoMessage implements Message, StringBuilderFormattable { + + private final String formattedMessage; + private final String format; + private final Object[] parameters; + + public MementoMessage(String formattedMessage, String format, Object[] parameters) { + this.formattedMessage = formattedMessage; + this.format = format; + this.parameters = parameters; + } + + @Override + public String getFormattedMessage() { + return formattedMessage; + } + + @Override + public String getFormat() { + return format; + } + + @Override + public Object[] getParameters() { + return parameters; + } + + /** + * Always returns null. + * + * @return null + */ + @Override + public Throwable getThrowable() { + return null; + } + + @Override + public void formatTo(StringBuilder buffer) { + buffer.append(formattedMessage); + } + + @Override + public String toString() { + return "MementoMessage{" + + "formattedMessage='" + formattedMessage + '\'' + + ", format='" + format + '\'' + + ", parameters=" + Arrays.toString(parameters) + + '}'; + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0738cf97/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 ecabcbc..be374a0 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 @@ -309,7 +309,7 @@ public class MutableLogEvent implements LogEvent, ReusableMessage, ParameterVisi return message; } final Object[] params = parameters == null ? new Object[0] : Arrays.copyOf(parameters, parameterCount); - return new ParameterizedMessage(messageText.toString(), params); + return new MementoMessage(messageText.toString(), messageFormat, params); } @Override http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0738cf97/log4j-core/src/test/java/org/apache/logging/log4j/core/LoggerTest.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/LoggerTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/LoggerTest.java index ba213ff..4cafb7b 100644 --- a/log4j-core/src/test/java/org/apache/logging/log4j/core/LoggerTest.java +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/LoggerTest.java @@ -16,6 +16,7 @@ */ package org.apache.logging.log4j.core; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotSame; @@ -39,9 +40,7 @@ import org.apache.logging.log4j.core.config.LoggerConfig; import org.apache.logging.log4j.junit.LoggerContextRule; import org.apache.logging.log4j.message.Message; import org.apache.logging.log4j.message.MessageFactory; -import org.apache.logging.log4j.message.ParameterizedMessage; import org.apache.logging.log4j.message.ParameterizedMessageFactory; -import org.apache.logging.log4j.message.ReusableParameterizedMessage; import org.apache.logging.log4j.message.StringFormatterMessageFactory; import org.apache.logging.log4j.message.StructuredDataMessage; import org.apache.logging.log4j.spi.AbstractLogger; @@ -415,14 +414,14 @@ public class LoggerTest { logger.error("Throwing with parameters {}", "TestParam", new NullPointerException("Test Exception")); final List<LogEvent> events = app.getEvents(); assertNotNull("Log event list not returned", events); - assertTrue("Incorrect number of log events: expected 1, actual " + events.size(), events.size() == 1); + assertEquals("Incorrect number of log events", 1, events.size()); final LogEvent event = events.get(0); final Throwable thrown = event.getThrown(); assertNotNull("No throwable present in log event", thrown); final Message msg = event.getMessage(); - assertTrue("Incorrect message type. Expected ParameterizedMessage/ReusableParameterizedMessage, actual " + msg.getClass().getSimpleName(), - msg instanceof ParameterizedMessage || msg instanceof ReusableParameterizedMessage); - + assertEquals("Throwing with parameters {}", msg.getFormat()); + assertEquals("Throwing with parameters TestParam", msg.getFormattedMessage()); + assertArrayEquals(new Object[] { "TestParam", thrown }, msg.getParameters()); } } http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0738cf97/log4j-core/src/test/java/org/apache/logging/log4j/core/async/RingBufferLogEventTest.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/RingBufferLogEventTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/RingBufferLogEventTest.java index 1d34921..f89a101 100644 --- a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/RingBufferLogEventTest.java +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/RingBufferLogEventTest.java @@ -33,6 +33,7 @@ import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.core.time.internal.DummyNanoClock; import org.apache.logging.log4j.core.time.internal.FixedPreciseClock; import org.apache.logging.log4j.message.ParameterConsumer; +import org.apache.logging.log4j.message.ReusableMessageFactory; import org.apache.logging.log4j.util.FilteredObjectInputStream; import org.apache.logging.log4j.util.StringMap; import org.apache.logging.log4j.core.impl.ThrowableProxy; @@ -182,6 +183,31 @@ public class RingBufferLogEventTest { } @Test + public void testCreateMementoRetainsParametersAndFormat() { + final RingBufferLogEvent evt = new RingBufferLogEvent(); + // Initialize the event with parameters + evt.swapParameters(new Object[10]); + final String loggerName = "logger.name"; + final Marker marker = MarkerManager.getMarker("marked man"); + final String fqcn = "f.q.c.n"; + final Level level = Level.TRACE; + ReusableMessageFactory factory = new ReusableMessageFactory(); + Message message = factory.newMessage("Hello {}!", "World"); + final Throwable t = new InternalError("not a real error"); + final ContextStack contextStack = new MutableThreadContextStack(Arrays.asList("a", "b")); + final String threadName = "main"; + final StackTraceElement location = null; + evt.setValues(null, loggerName, marker, fqcn, level, message, t, (StringMap) evt.getContextData(), + contextStack, -1, threadName, -1, location, new FixedPreciseClock(12345, 678), new DummyNanoClock(1)); + ((StringMap) evt.getContextData()).putValue("key", "value"); + + final Message actual = evt.createMemento().getMessage(); + assertEquals("Hello {}!", actual.getFormat()); + assertArrayEquals(new String[] { "World" }, actual.getParameters()); + assertEquals("Hello World!", actual.getFormattedMessage()); + } + + @Test public void testMessageTextNeverThrowsNpe() { final RingBufferLogEvent evt = new RingBufferLogEvent(); try { http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0738cf97/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/MutableLogEventTest.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/MutableLogEventTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/MutableLogEventTest.java index 2bee6fb..655b561 100644 --- a/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/MutableLogEventTest.java +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/MutableLogEventTest.java @@ -138,6 +138,10 @@ public class MutableLogEventTest { assertEquals("format", "msg in a {}", mutable.getFormat()); assertEquals("formatted", "msg in a bottle", mutable.getFormattedMessage()); assertEquals("parameters", new String[] {"bottle"}, mutable.getParameters()); + Message memento = mutable.memento(); + assertEquals("format", "msg in a {}", memento.getFormat()); + assertEquals("formatted", "msg in a bottle", memento.getFormattedMessage()); + assertEquals("parameters", new String[] {"bottle"}, memento.getParameters()); } @Test http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0738cf97/src/changes/changes.xml ---------------------------------------------------------------------- diff --git a/src/changes/changes.xml b/src/changes/changes.xml index f172b52..d7ca266 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -118,6 +118,9 @@ <action issue="LOG4J2-2306" dev="ckozak" type="fix"> FixedDateFormat parses timezone offsets, -8:00 is interpreted as GMT-8:00. </action> + <action issue="LOG4J2-2307" dev="ckozak" type="fix"> + MutableLogEvent and RingBufferLogEvent message mementos retain the original format string. + </action> </release> <release version="2.11.1" date="2018-MM-DD" description="GA Release 2.11.1"> <action issue="LOG4J2-2268" dev="rgoers" type="fix" due-to="Tilman Hausherr">