diff --git a/log4j-api-test/src/test/java/org/apache/logging/log4j/message/ParameterFormatterTest.java b/log4j-api-test/src/test/java/org/apache/logging/log4j/message/ParameterFormatterTest.java index ee4735191d5..af7a3acc777 100644 --- a/log4j-api-test/src/test/java/org/apache/logging/log4j/message/ParameterFormatterTest.java +++ b/log4j-api-test/src/test/java/org/apache/logging/log4j/message/ParameterFormatterTest.java @@ -16,156 +16,106 @@ */ package org.apache.logging.log4j.message; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.assertj.core.api.Assertions.assertThat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; +import org.apache.logging.log4j.message.ParameterFormatter.MessagePatternAnalysis; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.MethodSource; /** * Tests {@link ParameterFormatter}. */ public class ParameterFormatterTest { - @Test - public void testCountArgumentPlaceholders() { - assertEquals(0, ParameterFormatter.countArgumentPlaceholders("")); - assertEquals(0, ParameterFormatter.countArgumentPlaceholders("aaa")); - assertEquals(0, ParameterFormatter.countArgumentPlaceholders("\\{}")); - assertEquals(1, ParameterFormatter.countArgumentPlaceholders("{}")); - assertEquals(1, ParameterFormatter.countArgumentPlaceholders("{}\\{}")); - assertEquals(2, ParameterFormatter.countArgumentPlaceholders("{}{}")); - assertEquals(3, ParameterFormatter.countArgumentPlaceholders("{}{}{}")); - assertEquals(4, ParameterFormatter.countArgumentPlaceholders("{}{}{}aa{}")); - assertEquals(4, ParameterFormatter.countArgumentPlaceholders("{}{}{}a{]b{}")); - assertEquals(5, ParameterFormatter.countArgumentPlaceholders("{}{}{}a{}b{}")); - } - - @Test - public void testFormat3StringArgs() { - final String testMsg = "Test message {}{} {}"; - final String[] args = {"a", "b", "c"}; - final String result = ParameterFormatter.format(testMsg, args); - assertEquals("Test message ab c", result); - } - - @Test - public void testFormatNullArgs() { - final String testMsg = "Test message {} {} {} {} {} {}"; - final String[] args = {"a", null, "c", null, null, null}; - final String result = ParameterFormatter.format(testMsg, args); - assertEquals("Test message a null c null null null", result); - } - - @Test - public void testFormatStringArgsIgnoresSuperfluousArgs() { - final String testMsg = "Test message {}{} {}"; - final String[] args = {"a", "b", "c", "unnecessary", "superfluous"}; - final String result = ParameterFormatter.format(testMsg, args); - assertEquals("Test message ab c", result); - } - - @Test - public void testFormatStringArgsWithEscape() { - final String testMsg = "Test message \\{}{} {}"; - final String[] args = {"a", "b", "c"}; - final String result = ParameterFormatter.format(testMsg, args); - assertEquals("Test message {}a b", result); - } - - @Test - public void testFormatStringArgsWithTrailingEscape() { - final String testMsg = "Test message {}{} {}\\"; - final String[] args = {"a", "b", "c"}; - final String result = ParameterFormatter.format(testMsg, args); - assertEquals("Test message ab c\\", result); - } - - @Test - public void testFormatStringArgsWithTrailingEscapedEscape() { - final String testMsg = "Test message {}{} {}\\\\"; - final String[] args = {"a", "b", "c"}; - final String result = ParameterFormatter.format(testMsg, args); - assertEquals("Test message ab c\\\\", result); - } - - @Test - public void testFormatStringArgsWithEscapedEscape() { - final String testMsg = "Test message \\\\{}{} {}"; - final String[] args = {"a", "b", "c"}; - final String result = ParameterFormatter.format(testMsg, args); - assertEquals("Test message \\ab c", result); - } - - @Test - public void testFormatMessage3StringArgs() { - final String testMsg = "Test message {}{} {}"; - final String[] args = {"a", "b", "c"}; - final StringBuilder sb = new StringBuilder(); - ParameterFormatter.formatMessage(sb, testMsg, args, 3); - final String result = sb.toString(); - assertEquals("Test message ab c", result); - } - - @Test - public void testFormatMessageNullArgs() { - final String testMsg = "Test message {} {} {} {} {} {}"; - final String[] args = {"a", null, "c", null, null, null}; - final StringBuilder sb = new StringBuilder(); - ParameterFormatter.formatMessage(sb, testMsg, args, 6); - final String result = sb.toString(); - assertEquals("Test message a null c null null null", result); - } - - @Test - public void testFormatMessageStringArgsIgnoresSuperfluousArgs() { - final String testMsg = "Test message {}{} {}"; - final String[] args = {"a", "b", "c", "unnecessary", "superfluous"}; - final StringBuilder sb = new StringBuilder(); - ParameterFormatter.formatMessage(sb, testMsg, args, 5); - final String result = sb.toString(); - assertEquals("Test message ab c", result); - } - - @Test - public void testFormatMessageStringArgsWithEscape() { - final String testMsg = "Test message \\{}{} {}"; - final String[] args = {"a", "b", "c"}; - final StringBuilder sb = new StringBuilder(); - ParameterFormatter.formatMessage(sb, testMsg, args, 3); - final String result = sb.toString(); - assertEquals("Test message {}a b", result); - } - - @Test - public void testFormatMessageStringArgsWithTrailingEscape() { - final String testMsg = "Test message {}{} {}\\"; - final String[] args = {"a", "b", "c"}; - final StringBuilder sb = new StringBuilder(); - ParameterFormatter.formatMessage(sb, testMsg, args, 3); - final String result = sb.toString(); - assertEquals("Test message ab c\\", result); - } - - @Test - public void testFormatMessageStringArgsWithTrailingEscapedEscape() { - final String testMsg = "Test message {}{} {}\\\\"; - final String[] args = {"a", "b", "c"}; - final StringBuilder sb = new StringBuilder(); - ParameterFormatter.formatMessage(sb, testMsg, args, 3); - final String result = sb.toString(); - assertEquals("Test message ab c\\\\", result); - } - - @Test - public void testFormatMessageStringArgsWithEscapedEscape() { - final String testMsg = "Test message \\\\{}{} {}"; - final String[] args = {"a", "b", "c"}; - final StringBuilder sb = new StringBuilder(); - ParameterFormatter.formatMessage(sb, testMsg, args, 3); - final String result = sb.toString(); - assertEquals("Test message \\ab c", result); + @ParameterizedTest + @CsvSource({ + "0,,false,", + "0,,false,aaa", + "0,,true,\\{}", + "1,0,false,{}", + "1,0,true,{}\\{}", + "1,2,true,\\\\{}", + "2,8:10,true,foo \\{} {}{}", + "2,8:10,true,foo {\\} {}{}", + "2,0:2,false,{}{}", + "3,0:2:4,false,{}{}{}", + "4,0:2:4:8,false,{}{}{}aa{}", + "4,0:2:4:10,false,{}{}{}a{]b{}", + "5,0:2:4:7:10,false,{}{}{}a{}b{}" + }) + public void test_pattern_analysis( + final int placeholderCount, + final String placeholderCharIndicesString, + final boolean escapedPlaceholderFound, + final String pattern) { + MessagePatternAnalysis analysis = ParameterFormatter.analyzePattern(pattern, placeholderCount); + assertThat(analysis.placeholderCount).isEqualTo(placeholderCount); + if (placeholderCount > 0) { + final int[] placeholderCharIndices = Arrays.stream(placeholderCharIndicesString.split(":")) + .mapToInt(Integer::parseInt) + .toArray(); + assertThat(analysis.placeholderCharIndices).startsWith(placeholderCharIndices); + assertThat(analysis.escapedCharFound).isEqualTo(escapedPlaceholderFound); + } + } + + @ParameterizedTest + @MethodSource("messageFormattingTestCases") + void assertMessageFormatting( + final String pattern, final Object[] args, final int argCount, final String expectedFormattedMessage) { + MessagePatternAnalysis analysis = ParameterFormatter.analyzePattern(pattern, -1); + final StringBuilder buffer = new StringBuilder(); + ParameterFormatter.formatMessage(buffer, pattern, args, argCount, analysis); + String actualFormattedMessage = buffer.toString(); + assertThat(actualFormattedMessage).isEqualTo(expectedFormattedMessage); + } + + static Object[][] messageFormattingTestCases() { + return new Object[][] { + new Object[] {"Test message {}{} {}", new Object[] {"a", "b", "c"}, 3, "Test message ab c"}, + new Object[] { + "Test message {} {} {} {} {} {}", + new Object[] {"a", null, "c", null, null, null}, + 6, + "Test message a null c null null null" + }, + new Object[] { + "Test message {}{} {}", + new Object[] {"a", "b", "c", "unnecessary", "superfluous"}, + 5, + "Test message ab c" + }, + new Object[] {"Test message \\{}{} {}", new Object[] {"a", "b", "c"}, 3, "Test message {}a b"}, + new Object[] {"Test message {}{} {}\\", new Object[] {"a", "b", "c"}, 3, "Test message ab c\\"}, + new Object[] {"Test message {}{} {}\\\\", new Object[] {"a", "b", "c"}, 3, "Test message ab c\\"}, + new Object[] {"Test message \\\\{}{} {}", new Object[] {"a", "b", "c"}, 3, "Test message \\ab c"}, + new Object[] {"Test message {}{} {}", new Object[] {"a", "b", "c"}, 3, "Test message ab c"}, + new Object[] { + "Test message {} {} {} {} {} {}", + new Object[] {"a", null, "c", null, null, null}, + 6, + "Test message a null c null null null" + }, + new Object[] { + "Test message {}{} {}", + new Object[] {"a", "b", "c", "unnecessary", "superfluous"}, + 5, + "Test message ab c" + }, + new Object[] {"Test message \\{}{} {}", new Object[] {"a", "b", "c"}, 3, "Test message {}a b"}, + new Object[] {"Test message {}{} {}\\", new Object[] {"a", "b", "c"}, 3, "Test message ab c\\"}, + new Object[] {"Test message {}{} {}\\\\", new Object[] {"a", "b", "c"}, 3, "Test message ab c\\"}, + new Object[] {"Test message \\\\{}{} {}", new Object[] {"a", "b", "c"}, 3, "Test message \\ab c"}, + new Object[] {"foo \\\\\\{} {}", new Object[] {"bar"}, 1, "foo \\{} bar"}, + new Object[] {"missing arg {} {}", new Object[] {1, 2}, 1, "missing arg 1 {}"}, + new Object[] {"foo {\\} {}", new Object[] {"bar"}, 1, "foo {\\} bar"} + }; } @Test @@ -177,7 +127,7 @@ public void testDeepToString() { list.add(2); final String actual = ParameterFormatter.deepToString(list); final String expected = "[1, [..." + ParameterFormatter.identityToString(list) + "...], 2]"; - assertEquals(expected, actual); + assertThat(actual).isEqualTo(expected); } @Test @@ -191,7 +141,7 @@ public void testDeepToStringUsingNonRecursiveButConsequentObjects() { list.add(3); final String actual = ParameterFormatter.deepToString(list); final String expected = "[1, [0], 2, [0], 3]"; - assertEquals(expected, actual); + assertThat(actual).isEqualTo(expected); } @Test @@ -203,6 +153,6 @@ public void testIdentityToString() { list.add(2); final String actual = ParameterFormatter.identityToString(list); final String expected = list.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(list)); - assertEquals(expected, actual); + assertThat(actual).isEqualTo(expected); } } diff --git a/log4j-api-test/src/test/java/org/apache/logging/log4j/message/ParameterizedMessageTest.java b/log4j-api-test/src/test/java/org/apache/logging/log4j/message/ParameterizedMessageTest.java index 686edf52556..d17f5723d2d 100644 --- a/log4j-api-test/src/test/java/org/apache/logging/log4j/message/ParameterizedMessageTest.java +++ b/log4j-api-test/src/test/java/org/apache/logging/log4j/message/ParameterizedMessageTest.java @@ -115,7 +115,7 @@ public void testFormatStringArgsWithTrailingEscapedEscape() { final String testMsg = "Test message {}{} {}\\\\"; final String[] args = {"a", "b", "c"}; final String result = ParameterizedMessage.format(testMsg, args); - assertEquals("Test message ab c\\\\", result); + assertEquals("Test message ab c\\", result); } @Test diff --git a/log4j-api-test/src/test/java/org/apache/logging/log4j/message/ReusableParameterizedMessageTest.java b/log4j-api-test/src/test/java/org/apache/logging/log4j/message/ReusableParameterizedMessageTest.java index 10adcf6f8a7..1a03523c7b3 100644 --- a/log4j-api-test/src/test/java/org/apache/logging/log4j/message/ReusableParameterizedMessageTest.java +++ b/log4j-api-test/src/test/java/org/apache/logging/log4j/message/ReusableParameterizedMessageTest.java @@ -112,7 +112,7 @@ public void testFormatStringArgsWithTrailingEscapedEscape() { final String[] args = {"a", "b", "c"}; final String result = new ReusableParameterizedMessage().set(testMsg, (Object[]) args).getFormattedMessage(); - assertEquals("Test message ab c\\\\", result); + assertEquals("Test message ab c\\", result); } @Test diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/BasicThreadInformation.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/BasicThreadInformation.java index 26dfbed3023..fae8236793f 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/message/BasicThreadInformation.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/BasicThreadInformation.java @@ -16,7 +16,9 @@ */ package org.apache.logging.log4j.message; -import org.apache.logging.log4j.util.Chars; +import static org.apache.logging.log4j.util.Chars.LF; +import static org.apache.logging.log4j.util.Chars.SPACE; + import org.apache.logging.log4j.util.StringBuilders; /** @@ -78,7 +80,7 @@ public int hashCode() { */ @Override public void printThreadInfo(final StringBuilder sb) { - StringBuilders.appendDqValue(sb, name).append(Chars.SPACE); + StringBuilders.appendDqValue(sb, name).append(SPACE); if (isDaemon) { sb.append("daemon "); } @@ -86,8 +88,8 @@ public void printThreadInfo(final StringBuilder sb) { if (threadGroupName != null) { StringBuilders.appendKeyDqValue(sb, "group", threadGroupName); } - sb.append('\n'); - sb.append("\tThread state: ").append(state.name()).append('\n'); + sb.append(LF); + sb.append("\tThread state: ").append(state.name()).append(LF); } /** @@ -98,7 +100,7 @@ public void printThreadInfo(final StringBuilder sb) { @Override public void printStack(final StringBuilder sb, final StackTraceElement[] trace) { for (final StackTraceElement element : trace) { - sb.append("\tat ").append(element).append('\n'); + sb.append("\tat ").append(element).append(LF); } } } diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/FormattedMessage.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/FormattedMessage.java index b936c3a5a58..2b15e355822 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/message/FormattedMessage.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/FormattedMessage.java @@ -21,7 +21,6 @@ import java.util.Arrays; import java.util.Locale; import java.util.Objects; -import java.util.regex.Pattern; /** * Handles messages that contain a format String. This converts each message into a {@link MessageFormatMessage}, @@ -30,9 +29,6 @@ */ public class FormattedMessage implements Message { - private static final String FORMAT_SPECIFIER = "%(\\d+\\$)?([-#+ 0,(\\<]*)?(\\d+)?(\\.\\d+)?([tT])?([a-zA-Z%])"; - private static final Pattern MSG_PATTERN = Pattern.compile(FORMAT_SPECIFIER); - private final String messagePattern; private final Object[] argArray; private String formattedMessage; @@ -168,7 +164,27 @@ public String getFormattedMessage() { return formattedMessage; } + /** + * Gets the message implementation to which formatting is delegated. + * + * + *

+ * Mixing specifiers from multiple types is not supported. + *

+ * + * @param msgPattern The message pattern. + * @param args The parameters. + * @param aThrowable The throwable + * @return The message that performs formatting. + */ protected Message getMessage(final String msgPattern, final Object[] args, final Throwable aThrowable) { + // Check for valid `{ ArgumentIndex [, FormatType [, FormatStyle]] }` format specifiers try { final MessageFormat format = new MessageFormat(msgPattern); final Format[] formats = format.getFormats(); @@ -178,14 +194,13 @@ protected Message getMessage(final String msgPattern, final Object[] args, final } catch (final Exception ignored) { // Obviously, the message is not a proper pattern for MessageFormat. } - try { - if (MSG_PATTERN.matcher(msgPattern).find()) { - return new StringFormattedMessage(locale, msgPattern, args); - } - } catch (final Exception ignored) { - // Also not properly formatted. + // Check for non-escaped `{}` format specifiers + // This case also includes patterns without any `java.util.Formatter` specifiers + if (ParameterFormatter.analyzePattern(msgPattern, 1).placeholderCount > 0 || msgPattern.indexOf('%') == -1) { + return new ParameterizedMessage(msgPattern, args, aThrowable); } - return new ParameterizedMessage(msgPattern, args, aThrowable); + // Interpret as `java.util.Formatter` format + return new StringFormattedMessage(locale, msgPattern, args); } /** diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/FormattedMessageFactory.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/FormattedMessageFactory.java index b7b35263cb7..7a63dc5be8d 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/message/FormattedMessageFactory.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/FormattedMessageFactory.java @@ -31,9 +31,7 @@ public class FormattedMessageFactory implements MessageFactory { /** * Constructs a message factory with default flow strings. */ - public FormattedMessageFactory() { - super(); - } + public FormattedMessageFactory() {} /** * Creates {@link StringFormattedMessage} instances. diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/LocalizedMessage.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/LocalizedMessage.java index 51239cbb497..56622ddbf64 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/message/LocalizedMessage.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/LocalizedMessage.java @@ -38,7 +38,7 @@ public class LocalizedMessage implements Message, LoggerNameAwareMessage { private final Locale locale; - private final StatusLogger logger = StatusLogger.getLogger(); + private static final StatusLogger logger = StatusLogger.getLogger(); private String loggerName; private final String key; diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/LocalizedMessageFactory.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/LocalizedMessageFactory.java index aea9c1333c2..bb67efd04e3 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/message/LocalizedMessageFactory.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/LocalizedMessageFactory.java @@ -68,7 +68,7 @@ public ResourceBundle getResourceBundle() { @Override public Message newMessage(final String key) { if (resourceBundle == null) { - return new LocalizedMessage(baseName, key, null); + return new LocalizedMessage(baseName, key); } return new LocalizedMessage(resourceBundle, key); } diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/Message.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/Message.java index c0b247c732e..4841983c24b 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/message/Message.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/Message.java @@ -73,6 +73,11 @@ public interface Message { * * @return The message format. Some implementations, such as ParameterizedMessage, will use this as * the message "pattern". Other Messages may simply return an empty String. + * TODO Do all messages have a format? What syntax? Using a Formatter object could be cleaner. + * (RG) In SimpleMessage the format is identical to the formatted message. In ParameterizedMessage and + * StructuredDataMessage it is not. It is up to the Message implementer to determine what this + * method will return. A Formatter is inappropriate as this is very specific to the Message + * implementation so it isn't clear to me how having a Formatter separate from the Message would be cleaner. */ String getFormat(); diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/ObjectArrayMessage.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/ObjectArrayMessage.java index fbba8f91a04..bf6a8426763 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/message/ObjectArrayMessage.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/ObjectArrayMessage.java @@ -17,6 +17,7 @@ package org.apache.logging.log4j.message; import java.util.Arrays; +import org.apache.logging.log4j.util.Constants; /** * Handles messages that contain an Object[]. @@ -31,10 +32,8 @@ */ public final class ObjectArrayMessage implements Message { - private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0]; - - private final transient Object[] array; - private transient String arrayString; + private final Object[] array; + private String arrayString; /** * Creates the ObjectMessage. @@ -43,7 +42,7 @@ public final class ObjectArrayMessage implements Message { * The Object to format. */ public ObjectArrayMessage(final Object... obj) { - this.array = obj == null ? EMPTY_OBJECT_ARRAY : obj; + this.array = obj == null ? Constants.EMPTY_OBJECT_ARRAY : obj; } private boolean equalObjectsOrStrings(final Object[] left, final Object[] right) { diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/ObjectMessage.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/ObjectMessage.java index f6b53158015..ae952cd7896 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/message/ObjectMessage.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/ObjectMessage.java @@ -99,7 +99,7 @@ public boolean equals(final Object o) { } final ObjectMessage that = (ObjectMessage) o; - return equalObjectsOrStrings(obj, that.obj); + return obj == null ? that.obj == null : equalObjectsOrStrings(obj, that.obj); } private boolean equalObjectsOrStrings(final Object left, final Object right) { @@ -108,7 +108,7 @@ private boolean equalObjectsOrStrings(final Object left, final Object right) { @Override public int hashCode() { - return obj.hashCode(); + return obj != null ? obj.hashCode() : 0; } @Override diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterFormatter.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterFormatter.java index db88b240b92..66f8ca08643 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterFormatter.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterFormatter.java @@ -60,325 +60,263 @@ final class ParameterFormatter { private static final char DELIM_START = '{'; private static final char DELIM_STOP = '}'; private static final char ESCAPE_CHAR = '\\'; - private static final DateTimeFormatter FORMATTER = + + private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ").withZone(ZoneId.systemDefault()); private ParameterFormatter() {} /** - * Counts the number of unescaped placeholders in the given messagePattern. + * Analyzes – finds argument placeholder (i.e., {@literal "{}"}) occurrences, etc. – the given message pattern. + *

+ * Only {@literal "{}"} strings are treated as argument placeholders. + * Escaped or incomplete argument placeholders will be ignored. + * Some invalid argument placeholder examples: + *

+ *
+     * { }
+     * foo\{}
+     * {bar
+     * {buzz}
+     * 
* - * @param messagePattern the message pattern to be analyzed. - * @return the number of unescaped placeholders. + * @param pattern a message pattern to be analyzed + * @param argCount + * The number of arguments to be formatted. + * For instance, for a parametrized message containing 7 placeholders in the pattern and 4 arguments for formatting, analysis will only need to store the index of the first 4 placeholder characters. + * A negative value indicates no limit. + * @return the analysis result */ - static int countArgumentPlaceholders(final String messagePattern) { - if (messagePattern == null) { - return 0; - } - final int length = messagePattern.length(); - int result = 0; - boolean isEscaped = false; - for (int i = 0; i < length - 1; i++) { - final char curChar = messagePattern.charAt(i); - if (curChar == ESCAPE_CHAR) { - isEscaped = !isEscaped; - } else if (curChar == DELIM_START) { - if (!isEscaped && messagePattern.charAt(i + 1) == DELIM_STOP) { - result++; - i++; - } - isEscaped = false; - } else { - isEscaped = false; - } - } - return result; + static MessagePatternAnalysis analyzePattern(final String pattern, final int argCount) { + MessagePatternAnalysis analysis = new MessagePatternAnalysis(); + analyzePattern(pattern, argCount, analysis); + return analysis; } /** - * Counts the number of unescaped placeholders in the given messagePattern. + * Analyzes – finds argument placeholder (i.e., {@literal "{}"}) occurrences, etc. – the given message pattern. + *

+ * Only {@literal "{}"} strings are treated as argument placeholders. + * Escaped or incomplete argument placeholders will be ignored. + * Some invalid argument placeholder examples: + *

+ *
+     * { }
+     * foo\{}
+     * {bar
+     * {buzz}
+     * 
* - * @param messagePattern the message pattern to be analyzed. - * @return the number of unescaped placeholders. + * @param pattern a message pattern to be analyzed + * @param argCount + * The number of arguments to be formatted. + * For instance, for a parametrized message containing 7 placeholders in the pattern and 4 arguments for formatting, analysis will only need to store the index of the first 4 placeholder characters. + * A negative value indicates no limit. + * @param analysis an object to store the results */ - static int countArgumentPlaceholders2(final String messagePattern, final int[] indices) { - if (messagePattern == null) { - return 0; + static void analyzePattern(final String pattern, final int argCount, final MessagePatternAnalysis analysis) { + + // Short-circuit if there is nothing interesting + final int l; + if (pattern == null || (l = pattern.length()) < 2) { + analysis.placeholderCount = 0; + return; } - final int length = messagePattern.length(); - int result = 0; - boolean isEscaped = false; - for (int i = 0; i < length - 1; i++) { - final char curChar = messagePattern.charAt(i); - if (curChar == ESCAPE_CHAR) { - isEscaped = !isEscaped; - indices[0] = -1; // escaping means fast path is not available... - result++; - } else if (curChar == DELIM_START) { - if (!isEscaped && messagePattern.charAt(i + 1) == DELIM_STOP) { - indices[result] = i; - result++; - i++; - } - isEscaped = false; + + // Count `{}` occurrences that is not escaped, i.e., not `\`-prefixed + boolean escaped = false; + analysis.placeholderCount = 0; + analysis.escapedCharFound = false; + for (int i = 0; i < (l - 1); i++) { + final char c = pattern.charAt(i); + if (c == ESCAPE_CHAR) { + analysis.escapedCharFound = true; + escaped = !escaped; } else { - isEscaped = false; + if (escaped) { + escaped = false; + } else if (c == DELIM_START && pattern.charAt(i + 1) == DELIM_STOP) { + if (argCount < 0 || analysis.placeholderCount < argCount) { + analysis.ensurePlaceholderCharIndicesCapacity(argCount); + analysis.placeholderCharIndices[analysis.placeholderCount++] = i++; + } + // `argCount` is exceeded, skip storing the index + else { + analysis.placeholderCount++; + i++; + } + } } } - return result; } /** - * Counts the number of unescaped placeholders in the given messagePattern. - * - * @param messagePattern the message pattern to be analyzed. - * @return the number of unescaped placeholders. + * @see #analyzePattern(String, int, MessagePatternAnalysis) */ - static int countArgumentPlaceholders3(final char[] messagePattern, final int length, final int[] indices) { - int result = 0; - boolean isEscaped = false; - for (int i = 0; i < length - 1; i++) { - final char curChar = messagePattern[i]; - if (curChar == ESCAPE_CHAR) { - isEscaped = !isEscaped; - } else if (curChar == DELIM_START) { - if (!isEscaped && messagePattern[i + 1] == DELIM_STOP) { - indices[result] = i; - result++; - i++; - } - isEscaped = false; - } else { - isEscaped = false; + static final class MessagePatternAnalysis { + + /** + * The size of the {@link #placeholderCharIndices} buffer to be allocated if it is found to be null. + */ + private static final int PLACEHOLDER_CHAR_INDEX_BUFFER_INITIAL_SIZE = 8; + + /** + * The size {@link #placeholderCharIndices} buffer will be extended with if it has found to be insufficient. + */ + private static final int PLACEHOLDER_CHAR_INDEX_BUFFER_SIZE_INCREMENT = 8; + + /** + * The total number of argument placeholder occurrences. + */ + int placeholderCount; + + /** + * The array of indices pointing to the first character of the found argument placeholder occurrences. + */ + int[] placeholderCharIndices; + + /** + * Flag indicating if an escaped (i.e., `\`-prefixed) character is found. + */ + boolean escapedCharFound; + + private void ensurePlaceholderCharIndicesCapacity(final int argCount) { + + // Initialize the index buffer, if necessary + if (placeholderCharIndices == null) { + final int length = Math.max(argCount, PLACEHOLDER_CHAR_INDEX_BUFFER_INITIAL_SIZE); + placeholderCharIndices = new int[length]; + } + + // Extend the index buffer, if necessary + else if (placeholderCount >= placeholderCharIndices.length) { + final int newLength = argCount > 0 + ? argCount + : Math.addExact(placeholderCharIndices.length, PLACEHOLDER_CHAR_INDEX_BUFFER_SIZE_INCREMENT); + final int[] newPlaceholderCharIndices = new int[newLength]; + System.arraycopy(placeholderCharIndices, 0, newPlaceholderCharIndices, 0, placeholderCount); + placeholderCharIndices = newPlaceholderCharIndices; } } - return result; } /** - * Replace placeholders in the given messagePattern with arguments. + * Format the following pattern using provided arguments. * - * @param messagePattern the message pattern containing placeholders. - * @param arguments the arguments to be used to replace placeholders. - * @return the formatted message. + * @param pattern a formatting pattern + * @param args arguments to be formatted + * @return the formatted message */ - static String format(final String messagePattern, final Object[] arguments) { + static String format(final String pattern, final Object[] args, int argCount) { final StringBuilder result = new StringBuilder(); - final int argCount = arguments == null ? 0 : arguments.length; - formatMessage(result, messagePattern, arguments, argCount); + final MessagePatternAnalysis analysis = analyzePattern(pattern, argCount); + formatMessage(result, pattern, args, argCount, analysis); return result.toString(); } - /** - * Replace placeholders in the given messagePattern with arguments. - * - * @param buffer the buffer to write the formatted message into - * @param messagePattern the message pattern containing placeholders. - * @param arguments the arguments to be used to replace placeholders. - */ - static void formatMessage2( + static void formatMessage( final StringBuilder buffer, - final String messagePattern, - final Object[] arguments, + final String pattern, + final Object[] args, final int argCount, - final int[] indices) { - if (messagePattern == null || arguments == null || argCount == 0) { - buffer.append(messagePattern); - return; - } - int previous = 0; - for (int i = 0; i < argCount; i++) { - buffer.append(messagePattern, previous, indices[i]); - previous = indices[i] + 2; - recursiveDeepToString(arguments[i], buffer); - } - buffer.append(messagePattern, previous, messagePattern.length()); - } + final MessagePatternAnalysis analysis) { - /** - * Replace placeholders in the given messagePattern with arguments. - * - * @param buffer the buffer to write the formatted message into - * @param messagePattern the message pattern containing placeholders. - * @param arguments the arguments to be used to replace placeholders. - */ - static void formatMessage3( - final StringBuilder buffer, - final char[] messagePattern, - final int patternLength, - final Object[] arguments, - final int argCount, - final int[] indices) { - if (messagePattern == null) { - return; - } - if (arguments == null || argCount == 0) { - buffer.append(messagePattern); + // Short-circuit if there is nothing interesting + if (pattern == null || args == null || analysis.placeholderCount == 0) { + buffer.append(pattern); return; } - int previous = 0; - for (int i = 0; i < argCount; i++) { - buffer.append(messagePattern, previous, indices[i]); - previous = indices[i] + 2; - recursiveDeepToString(arguments[i], buffer); - } - buffer.append(messagePattern, previous, patternLength); - } - /** - * Replace placeholders in the given messagePattern with arguments. - * - * @param buffer the buffer to write the formatted message into - * @param messagePattern the message pattern containing placeholders. - * @param arguments the arguments to be used to replace placeholders. - */ - static void formatMessage( - final StringBuilder buffer, final String messagePattern, final Object[] arguments, final int argCount) { - if (messagePattern == null || arguments == null || argCount == 0) { - buffer.append(messagePattern); - return; + // Fail if there are insufficient arguments + if (analysis.placeholderCount > args.length) { + final String message = String.format( + "found %d argument placeholders, but provided %d for pattern `%s`", + analysis.placeholderCount, args.length, pattern); + throw new IllegalArgumentException(message); } - int escapeCounter = 0; - int currentArgument = 0; - int i = 0; - final int len = messagePattern.length(); - for (; i < len - 1; i++) { // last char is excluded from the loop - final char curChar = messagePattern.charAt(i); - if (curChar == ESCAPE_CHAR) { - escapeCounter++; - } else { - if (isDelimPair(curChar, messagePattern, i)) { // looks ahead one char - i++; - // write escaped escape chars - writeEscapedEscapeChars(escapeCounter, buffer); - - if (isOdd(escapeCounter)) { - // i.e. escaped: write escaped escape chars - writeDelimPair(buffer); - } else { - // unescaped - writeArgOrDelimPair(arguments, argCount, currentArgument, buffer); - currentArgument++; - } - } else { - handleLiteralChar(buffer, escapeCounter, curChar); - } - escapeCounter = 0; - } + // Fast-path for patterns containing no escapes + if (analysis.escapedCharFound) { + formatMessageContainingEscapes(buffer, pattern, args, argCount, analysis); } - handleRemainingCharIfAny(messagePattern, len, buffer, escapeCounter, i); - } - /** - * Returns {@code true} if the specified char and the char at {@code curCharIndex + 1} in the specified message - * pattern together form a "{}" delimiter pair, returns {@code false} otherwise. - */ - // Profiling showed this method is important to log4j performance. Modify with care! - // 22 bytes (allows immediate JVM inlining: < 35 bytes) LOG4J2-1096 - private static boolean isDelimPair(final char curChar, final String messagePattern, final int curCharIndex) { - return curChar == DELIM_START && messagePattern.charAt(curCharIndex + 1) == DELIM_STOP; + // Slow-path for patterns containing escapes + else { + formatMessageContainingNoEscapes(buffer, pattern, args, argCount, analysis); + } } - /** - * Detects whether the message pattern has been fully processed or if an unprocessed character remains and processes - * it if necessary, returning the resulting position in the result char array. - */ - // Profiling showed this method is important to log4j performance. Modify with care! - // 28 bytes (allows immediate JVM inlining: < 35 bytes) LOG4J2-1096 - private static void handleRemainingCharIfAny( - final String messagePattern, - final int len, + static void formatMessageContainingNoEscapes( final StringBuilder buffer, - final int escapeCounter, - final int i) { - if (i == len - 1) { - final char curChar = messagePattern.charAt(i); - handleLastChar(buffer, escapeCounter, curChar); - } - } + final String pattern, + final Object[] args, + final int argCount, + final MessagePatternAnalysis analysis) { - /** - * Processes the last unprocessed character and returns the resulting position in the result char array. - */ - // Profiling showed this method is important to log4j performance. Modify with care! - // 28 bytes (allows immediate JVM inlining: < 35 bytes) LOG4J2-1096 - private static void handleLastChar(final StringBuilder buffer, final int escapeCounter, final char curChar) { - if (curChar == ESCAPE_CHAR) { - writeUnescapedEscapeChars(escapeCounter + 1, buffer); - } else { - handleLiteralChar(buffer, escapeCounter, curChar); + // Format each argument and the text preceding it + int precedingTextStartIndex = 0; + final int argLimit = Math.min(analysis.placeholderCount, argCount); + for (int argIndex = 0; argIndex < argLimit; argIndex++) { + final int placeholderCharIndex = analysis.placeholderCharIndices[argIndex]; + buffer.append(pattern, precedingTextStartIndex, placeholderCharIndex); + recursiveDeepToString(args[argIndex], buffer); + precedingTextStartIndex = placeholderCharIndex + 2; } - } - - /** - * Processes a literal char (neither an '\' escape char nor a "{}" delimiter pair) and returns the resulting - * position. - */ - // Profiling showed this method is important to log4j performance. Modify with care! - // 16 bytes (allows immediate JVM inlining: < 35 bytes) LOG4J2-1096 - private static void handleLiteralChar(final StringBuilder buffer, final int escapeCounter, final char curChar) { - // any other char beside ESCAPE or DELIM_START/STOP-combo - // write unescaped escape chars - writeUnescapedEscapeChars(escapeCounter, buffer); - buffer.append(curChar); - } - - /** - * Writes "{}" to the specified result array at the specified position and returns the resulting position. - */ - // Profiling showed this method is important to log4j performance. Modify with care! - // 18 bytes (allows immediate JVM inlining: < 35 bytes) LOG4J2-1096 - private static void writeDelimPair(final StringBuilder buffer) { - buffer.append(DELIM_START); - buffer.append(DELIM_STOP); - } - /** - * Returns {@code true} if the specified parameter is odd. - */ - // Profiling showed this method is important to log4j performance. Modify with care! - // 11 bytes (allows immediate JVM inlining: < 35 bytes) LOG4J2-1096 - private static boolean isOdd(final int number) { - return (number & 1) == 1; - } - - /** - * Writes a '\' char to the specified result array (starting at the specified position) for each pair of - * '\' escape chars encountered in the message format and returns the resulting position. - */ - // Profiling showed this method is important to log4j performance. Modify with care! - // 11 bytes (allows immediate JVM inlining: < 35 bytes) LOG4J2-1096 - private static void writeEscapedEscapeChars(final int escapeCounter, final StringBuilder buffer) { - final int escapedEscapes = escapeCounter >> 1; // divide by two - writeUnescapedEscapeChars(escapedEscapes, buffer); + // Format the last trailing text + buffer.append(pattern, precedingTextStartIndex, pattern.length()); } - /** - * Writes the specified number of '\' chars to the specified result array (starting at the specified position) and - * returns the resulting position. - */ - // Profiling showed this method is important to log4j performance. Modify with care! - // 20 bytes (allows immediate JVM inlining: < 35 bytes) LOG4J2-1096 - private static void writeUnescapedEscapeChars(int escapeCounter, final StringBuilder buffer) { - while (escapeCounter > 0) { - buffer.append(ESCAPE_CHAR); - escapeCounter--; - } - } - - /** - * Appends the argument at the specified argument index (or, if no such argument exists, the "{}" delimiter pair) to - * the specified result char array at the specified position and returns the resulting position. - */ - // Profiling showed this method is important to log4j performance. Modify with care! - // 25 bytes (allows immediate JVM inlining: < 35 bytes) LOG4J2-1096 - private static void writeArgOrDelimPair( - final Object[] arguments, final int argCount, final int currentArgument, final StringBuilder buffer) { - if (currentArgument < argCount) { - recursiveDeepToString(arguments[currentArgument], buffer); - } else { - writeDelimPair(buffer); + static void formatMessageContainingEscapes( + final StringBuilder buffer, + final String pattern, + final Object[] args, + final int argCount, + final MessagePatternAnalysis analysis) { + + // Format each argument and the text preceding it + int precedingTextStartIndex = 0; + final int argLimit = Math.min(analysis.placeholderCount, argCount); + for (int argIndex = 0; argIndex < argLimit; argIndex++) { + final int placeholderCharIndex = analysis.placeholderCharIndices[argIndex]; + copyMessagePatternContainingEscapes(buffer, pattern, precedingTextStartIndex, placeholderCharIndex); + recursiveDeepToString(args[argIndex], buffer); + precedingTextStartIndex = placeholderCharIndex + 2; + } + + // Format the last trailing text + copyMessagePatternContainingEscapes(buffer, pattern, precedingTextStartIndex, pattern.length()); + } + + private static void copyMessagePatternContainingEscapes( + final StringBuilder buffer, final String pattern, final int startIndex, final int endIndex) { + boolean escaped = false; + int i = startIndex; + for (; i < endIndex; i++) { + final char c = pattern.charAt(i); + if (c == ESCAPE_CHAR) { + if (escaped) { + // Found an escaped `\`, skip appending it + escaped = false; + } else { + escaped = true; + buffer.append(c); + } + } else { + if (escaped) { + if (c == DELIM_START && pattern.charAt(i + 1) == DELIM_STOP) { + // Found an escaped placeholder, override the earlier appended `\` + buffer.setLength(buffer.length() - 1); + buffer.append("{}"); + i++; + } else { + buffer.append(c); + } + escaped = false; + } else { + buffer.append(c); + } + } } } @@ -499,7 +437,7 @@ private static boolean appendDate(final Object o, final StringBuilder str) { if (!(o instanceof Date)) { return false; } - str.append(FORMATTER.format(((Date) o).toInstant())); + str.append(DATE_FORMATTER.format(((Date) o).toInstant())); return true; } @@ -579,15 +517,14 @@ private static void appendMap(final Object o, final StringBuilder str, final Set final Map oMap = (Map) o; str.append('{'); boolean isFirst = true; - for (final Object o1 : oMap.entrySet()) { - final Map.Entry current = (Map.Entry) o1; + for (final Map.Entry entry : oMap.entrySet()) { if (isFirst) { isFirst = false; } else { str.append(", "); } - final Object key = current.getKey(); - final Object value = current.getValue(); + final Object key = entry.getKey(); + final Object value = entry.getValue(); recursiveDeepToString(key, str, cloneDejaVu(effectiveDejaVu)); str.append('='); recursiveDeepToString(value, str, cloneDejaVu(effectiveDejaVu)); diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterizedMessage.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterizedMessage.java index aae12e6f374..69bce67c14a 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterizedMessage.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterizedMessage.java @@ -16,19 +16,32 @@ */ package org.apache.logging.log4j.message; +import static org.apache.logging.log4j.message.ParameterFormatter.analyzePattern; + import java.util.Arrays; import java.util.Objects; +import org.apache.logging.log4j.message.ParameterFormatter.MessagePatternAnalysis; import org.apache.logging.log4j.spi.LoggingSystem; import org.apache.logging.log4j.spi.recycler.Recycler; import org.apache.logging.log4j.util.StringBuilderFormattable; import org.apache.logging.log4j.util.StringBuilders; /** - * Handles messages that consist of a format string containing '{}' to represent each replaceable token, and - * the parameters. + * A {@link Message} accepting argument placeholders in the formatting pattern. + *

+ * Only {@literal "{}"} strings are treated as argument placeholders. + * Escaped (i.e., {@code "\"}-prefixed) or incomplete argument placeholders will be ignored. + * Examples of argument placeholders that will be discarded and rendered intact: + *

+ *
+ * { }
+ * foo\{}
+ * {bar
+ * {buzz}
+ * 
*

- * This class was originally written for Lilith by Joern Huxhorn where it is - * licensed under the LGPL. It has been relicensed here with his permission providing that this attribution remain. + * This class was originally written for Lilith by Jörn Huxhorn and licensed under the LGPL. + * It has been relicensed here with his permission providing that this attribution remain. *

*/ public class ParameterizedMessage implements Message, StringBuilderFormattable { @@ -36,141 +49,127 @@ public class ParameterizedMessage implements Message, StringBuilderFormattable { // Should this be configurable? private static final int DEFAULT_STRING_BUILDER_SIZE = 255; - /** - * Prefix for recursion. - */ - public static final String RECURSION_PREFIX = ParameterFormatter.RECURSION_PREFIX; - /** - * Suffix for recursion. - */ - public static final String RECURSION_SUFFIX = ParameterFormatter.RECURSION_SUFFIX; - - /** - * Prefix for errors. - */ - public static final String ERROR_PREFIX = ParameterFormatter.ERROR_PREFIX; - - /** - * Separator for errors. - */ - public static final String ERROR_SEPARATOR = ParameterFormatter.ERROR_SEPARATOR; - - /** - * Separator for error messages. - */ - public static final String ERROR_MSG_SEPARATOR = ParameterFormatter.ERROR_MSG_SEPARATOR; - - /** - * Suffix for errors. - */ - public static final String ERROR_SUFFIX = ParameterFormatter.ERROR_SUFFIX; - private static final Recycler STRING_BUILDER_RECYCLER = LoggingSystem.getRecyclerFactory() .create(() -> new StringBuilder(DEFAULT_STRING_BUILDER_SIZE), stringBuilder -> { StringBuilders.trimToMaxSize(stringBuilder, DEFAULT_STRING_BUILDER_SIZE); stringBuilder.setLength(0); }); - private String messagePattern; - private final Object[] argArray; + private final String pattern; + + private final transient Object[] args; + + private final transient Throwable throwable; + + private final MessagePatternAnalysis patternAnalysis; private String formattedMessage; - private Throwable throwable; - private int[] indices; - private int usedCount; /** - * Creates a parameterized message. - * @param messagePattern The message "format" string. This will be a String containing "{}" placeholders - * where parameters should be substituted. - * @param arguments The arguments for substitution. - * @param throwable A Throwable. + * Constructs an instance. + *

+ * The {@link Throwable} associated with the message (and returned in {@link #getThrowable()}) will be determined as follows: + *

+ *
    + *
  1. If a {@code throwable} argument is provided
  2. + *
  3. If the last argument is a {@link Throwable} and is not referred to by any placeholder in the pattern
  4. + *
+ * + * @param pattern a formatting pattern + * @param args arguments to be formatted + * @param throwable a {@link Throwable} */ - public ParameterizedMessage(final String messagePattern, final Object[] arguments, final Throwable throwable) { - this.argArray = arguments; - this.throwable = throwable; - init(messagePattern); + public ParameterizedMessage(final String pattern, final Object[] args, final Throwable throwable) { + this.args = args; + this.pattern = pattern; + this.patternAnalysis = analyzePattern(pattern, args != null ? args.length : 0); + this.throwable = determineThrowable(throwable, this.args, patternAnalysis); + } + + private static Throwable determineThrowable( + final Throwable throwable, final Object[] args, final MessagePatternAnalysis analysis) { + + // Short-circuit if an explicit `Throwable` is provided + if (throwable != null) { + return throwable; + } + + // If the last `Throwable` argument is not consumed in the pattern, use that + if (args != null && args.length > analysis.placeholderCount) { + Object lastArg = args[args.length - 1]; + if (lastArg instanceof Throwable) { + return (Throwable) lastArg; + } + } + + // No `Throwable`s available + return null; } /** - * Constructs a ParameterizedMessage which contains the arguments converted to String as well as an optional - * Throwable. - * - *

If the last argument is a Throwable and is NOT used up by a placeholder in the message pattern it is returned - * in {@link #getThrowable()} and won't be contained in the created String[]. - * If it is used up {@link #getThrowable()} will return null even if the last argument was a Throwable!

+ * Constructor with a pattern and multiple arguments. + *

+ * If the last argument is a {@link Throwable} and is not referred to by any placeholder in the pattern, it is returned in {@link #getThrowable()}. + *

* - * @param messagePattern the message pattern that to be checked for placeholders. - * @param arguments the argument array to be converted. + * @param pattern a formatting pattern + * @param args arguments to be formatted */ - public ParameterizedMessage(final String messagePattern, final Object... arguments) { - this.argArray = arguments; - init(messagePattern); + public ParameterizedMessage(final String pattern, final Object... args) { + this(pattern, args, null); } /** - * Constructor with a pattern and a single parameter. - * @param messagePattern The message pattern. - * @param arg The parameter. + * Constructor with a pattern and a single argument. + *

+ * If the argument is a {@link Throwable} and is not referred to by any placeholder in the pattern, it is returned in {@link #getThrowable()}. + *

+ * + * @param pattern a formatting pattern + * @param arg an argument */ - public ParameterizedMessage(final String messagePattern, final Object arg) { - this(messagePattern, new Object[] {arg}); + public ParameterizedMessage(final String pattern, final Object arg) { + this(pattern, new Object[] {arg}); } /** - * Constructor with a pattern and two parameters. - * @param messagePattern The message pattern. - * @param arg0 The first parameter. - * @param arg1 The second parameter. + * Constructor with a pattern and two arguments. + *

+ * If the last argument is a {@link Throwable} and is not referred to by any placeholder in the pattern, it is returned in {@link #getThrowable()} and won't be contained in the formatted message. + *

+ * + * @param pattern a formatting pattern + * @param arg0 the first argument + * @param arg1 the second argument */ - public ParameterizedMessage(final String messagePattern, final Object arg0, final Object arg1) { - this(messagePattern, new Object[] {arg0, arg1}); - } - - private void init(final String messagePattern) { - this.messagePattern = messagePattern; - final int len = Math.max(1, messagePattern == null ? 0 : messagePattern.length() >> 1); // divide by 2 - this.indices = new int[len]; // LOG4J2-1542 ensure non-zero array length - final int placeholders = ParameterFormatter.countArgumentPlaceholders2(messagePattern, indices); - initThrowable(argArray, placeholders); - this.usedCount = Math.min(placeholders, argArray == null ? 0 : argArray.length); - } - - private void initThrowable(final Object[] params, final int usedParams) { - if (params != null) { - final int argCount = params.length; - if (usedParams < argCount && this.throwable == null && params[argCount - 1] instanceof Throwable) { - this.throwable = (Throwable) params[argCount - 1]; - } - } + public ParameterizedMessage(final String pattern, final Object arg0, final Object arg1) { + this(pattern, new Object[] {arg0, arg1}); } /** - * Returns the message pattern. - * @return the message pattern. + * @return the message formatting pattern */ @Override public String getFormat() { - return messagePattern; + return pattern; } /** - * Returns the message parameters. - * @return the message parameters. + * @return the message arguments */ @Override public Object[] getParameters() { - return argArray; + return args; } /** - * Returns the Throwable that was given as the last argument, if any. - * It will not survive serialization. The Throwable exists as part of the message - * primarily so that it can be extracted from the end of the list of parameters - * and then be added to the LogEvent. As such, the Throwable in the event should - * not be used once the LogEvent has been constructed. + * The {@link Throwable} provided along with the message by one of the following means: + *
    + *
  1. explicitly in the constructor
  2. + *
  3. as the last message argument that is not referred to by any placeholder in the formatting pattern
  4. + *
* - * @return the Throwable, if any. + * @return the {@link Throwable} provided along with the message */ @Override public Throwable getThrowable() { @@ -179,7 +178,11 @@ public Throwable getThrowable() { /** * Returns the formatted message. - * @return the formatted message. + *

+ * If possible, the result will be cached for subsequent invocations. + *

+ * + * @return the formatted message */ @Override public String getFormattedMessage() { @@ -200,23 +203,19 @@ public void formatTo(final StringBuilder buffer) { if (formattedMessage != null) { buffer.append(formattedMessage); } else { - if (indices[0] < 0) { - ParameterFormatter.formatMessage(buffer, messagePattern, argArray, usedCount); - } else { - ParameterFormatter.formatMessage2(buffer, messagePattern, argArray, usedCount, indices); - } + final int argCount = args != null ? args.length : 0; + ParameterFormatter.formatMessage(buffer, pattern, args, argCount, patternAnalysis); } } /** - * Replace placeholders in the given messagePattern with arguments. - * - * @param messagePattern the message pattern containing placeholders. - * @param arguments the arguments to be used to replace placeholders. - * @return the formatted message. + * @param pattern a message pattern containing argument placeholders + * @param args arguments to be used to replace placeholders + * @return the formatted message */ - public static String format(final String messagePattern, final Object[] arguments) { - return ParameterFormatter.format(messagePattern, arguments); + public static String format(final String pattern, final Object[] args) { + final int argCount = args != null ? args.length : 0; + return ParameterFormatter.format(pattern, args, argCount); } @Override @@ -224,26 +223,29 @@ public boolean equals(final Object object) { if (this == object) { return true; } - if (!(object instanceof ParameterizedMessage)) { + if (object == null || getClass() != object.getClass()) { return false; } final ParameterizedMessage that = (ParameterizedMessage) object; - return Objects.equals(this.messagePattern, that.messagePattern) && Arrays.equals(this.argArray, that.argArray); + return Objects.equals(pattern, that.pattern) && Arrays.equals(args, that.args); } @Override public int hashCode() { - int result = Objects.hash(messagePattern); - result = 31 * result + Arrays.hashCode(argArray); + int result = pattern != null ? pattern.hashCode() : 0; + result = 31 * result + (args != null ? Arrays.hashCode(args) : 0); return result; } /** - * Returns the number of argument placeholders. - * @param messagePattern the message pattern to be analyzed + * @param pattern the message pattern to be analyzed + * @return the number of argument placeholders */ - public static int countArgumentPlaceholders(final String messagePattern) { - return ParameterFormatter.countArgumentPlaceholders(messagePattern); + public static int countArgumentPlaceholders(final String pattern) { + if (pattern == null) { + return 0; + } + return analyzePattern(pattern, -1).placeholderCount; } /** @@ -294,7 +296,7 @@ public static String identityToString(final Object obj) { @Override public String toString() { - return "ParameterizedMessage[messagePattern=" + messagePattern + ", stringArgs=" + Arrays.toString(argArray) + return "ParameterizedMessage[messagePattern=" + pattern + ", stringArgs=" + Arrays.toString(args) + ", throwable=" + throwable + ']'; } } diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterizedNoReferenceMessageFactory.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterizedNoReferenceMessageFactory.java index 225eecc78b3..6d58644bf68 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterizedNoReferenceMessageFactory.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterizedNoReferenceMessageFactory.java @@ -78,9 +78,7 @@ public Throwable getThrowable() { /** * Constructs a message factory with default flow strings. */ - public ParameterizedNoReferenceMessageFactory() { - super(); - } + public ParameterizedNoReferenceMessageFactory() {} /** * Instance of ParameterizedStatusMessageFactory. diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableMessageFactory.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableMessageFactory.java index 3b71f2896ff..6ec36d5308a 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableMessageFactory.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableMessageFactory.java @@ -65,7 +65,7 @@ public ReusableMessageFactory(final RecyclerFactory recyclerFactory) { * @param message the message to make available again * @since 2.7 */ - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") public static void release(final Message message) { // LOG4J2-1583 if (message instanceof ReusableMessage) { ((ReusableMessage) message).clear(); diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java index 928e201f1bc..db209f866df 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java @@ -17,6 +17,7 @@ package org.apache.logging.log4j.message; import java.util.Arrays; +import org.apache.logging.log4j.message.ParameterFormatter.MessagePatternAnalysis; import org.apache.logging.log4j.spi.LoggingSystem; import org.apache.logging.log4j.spi.recycler.Recycler; import org.apache.logging.log4j.spi.recycler.RecyclerFactory; @@ -35,14 +36,13 @@ public class ReusableParameterizedMessage implements ReusableMessage, ParameterVisitable { private static final int MIN_BUILDER_SIZE = 512; - private static final int MAX_PARMS = 10; + private static final int MAX_PARAMS = 10; private String messagePattern; + private final MessagePatternAnalysis patternAnalysis = new MessagePatternAnalysis(); private int argCount; - private int usedCount; - private final int[] indices = new int[256]; private Object[] varargs; - private Object[] params = new Object[MAX_PARMS]; + private Object[] params = new Object[MAX_PARAMS]; private Throwable throwable; private final Recycler bufferRecycler; @@ -58,7 +58,7 @@ public ReusableParameterizedMessage(final RecyclerFactory recyclerFactory) { bufferRecycler = recyclerFactory.create( () -> { final int currentPatternLength = messagePattern == null ? 0 : messagePattern.length(); - int capacity = Math.max(MIN_BUILDER_SIZE, Math.multiplyExact(currentPatternLength, 2)); + final int capacity = Math.max(MIN_BUILDER_SIZE, Math.multiplyExact(currentPatternLength, 2)); return new StringBuilder(capacity); }, buffer -> { @@ -81,22 +81,20 @@ public Object[] swapParameters(final Object[] emptyReplacement) { Object[] result; if (varargs == null) { result = params; - if (emptyReplacement.length >= MAX_PARMS) { + if (emptyReplacement.length >= MAX_PARAMS) { params = emptyReplacement; - } else { + } else if (argCount <= emptyReplacement.length) { // Bad replacement! Too small, may blow up future 10-arg messages. - if (argCount <= emptyReplacement.length) { - // copy params into the specified replacement array and return that - System.arraycopy(params, 0, emptyReplacement, 0, argCount); - // Do not retain references to objects in the reusable params array. - for (int i = 0; i < argCount; i++) { - params[i] = null; - } - result = emptyReplacement; - } else { - // replacement array is too small for current content and future content: discard it - params = new Object[MAX_PARMS]; + // copy params into the specified replacement array and return that + System.arraycopy(params, 0, emptyReplacement, 0, argCount); + // Do not retain references to objects in the reusable params array. + for (int i = 0; i < argCount; i++) { + params[i] = null; } + result = emptyReplacement; + } else { + // replacement array is too small for current content and future content: discard it + params = new Object[MAX_PARAMS]; } } else { // The returned array will be reused by the caller in future swapParameter() calls. @@ -105,7 +103,7 @@ public Object[] swapParameters(final Object[] emptyReplacement) { // and return it. This helps the caller to retain a reusable array of at least 10 elements. // NOTE: LOG4J2-1688 unearthed the use case that an application array (not a varargs array) is passed // as the argument array. This array should not be modified, so it cannot be passed to the caller - // who will at some point null out the elements in the array). + // who will at some point null out the elements in the array. if (argCount <= emptyReplacement.length) { result = emptyReplacement; } else { @@ -136,53 +134,44 @@ public Message memento() { return new ParameterizedMessage(messagePattern, getTrimmedParams()); } - private void init(final String messagePattern, final int argCount, final Object[] paramArray) { + private void init(final String messagePattern, final int argCount, final Object[] args) { this.varargs = null; this.messagePattern = messagePattern; this.argCount = argCount; - final int placeholderCount = count(messagePattern, indices); - initThrowable(paramArray, argCount, placeholderCount); - this.usedCount = Math.min(placeholderCount, argCount); - } - - private static int count(final String messagePattern, final int[] indices) { - try { - // try the fast path first - return ParameterFormatter.countArgumentPlaceholders2(messagePattern, indices); - } catch (final Exception ex) { // fallback if more than int[] length (256) parameter placeholders - return ParameterFormatter.countArgumentPlaceholders(messagePattern); - } + ParameterFormatter.analyzePattern(messagePattern, argCount, patternAnalysis); + this.throwable = determineThrowable(args, argCount, patternAnalysis.placeholderCount); } - private void initThrowable(final Object[] params, final int argCount, final int usedParams) { - if (usedParams < argCount && params[argCount - 1] instanceof Throwable) { - this.throwable = (Throwable) params[argCount - 1]; - } else { - this.throwable = null; + private static Throwable determineThrowable(final Object[] args, final int argCount, final int placeholderCount) { + if (placeholderCount < argCount) { + final Object lastArg = args[argCount - 1]; + if (lastArg instanceof Throwable) { + return (Throwable) lastArg; + } } + return null; } - protected ReusableParameterizedMessage set(final String messagePattern, final Object... arguments) { + ReusableParameterizedMessage set(final String messagePattern, final Object... arguments) { init(messagePattern, arguments == null ? 0 : arguments.length, arguments); varargs = arguments; return this; } - protected ReusableParameterizedMessage set(final String messagePattern, final Object p0) { + ReusableParameterizedMessage set(final String messagePattern, final Object p0) { params[0] = p0; init(messagePattern, 1, params); return this; } - protected ReusableParameterizedMessage set(final String messagePattern, final Object p0, final Object p1) { + ReusableParameterizedMessage set(final String messagePattern, final Object p0, final Object p1) { params[0] = p0; params[1] = p1; init(messagePattern, 2, params); return this; } - protected ReusableParameterizedMessage set( - final String messagePattern, final Object p0, final Object p1, final Object p2) { + ReusableParameterizedMessage set(final String messagePattern, final Object p0, final Object p1, final Object p2) { params[0] = p0; params[1] = p1; params[2] = p2; @@ -190,7 +179,7 @@ protected ReusableParameterizedMessage set( return this; } - protected ReusableParameterizedMessage set( + ReusableParameterizedMessage set( final String messagePattern, final Object p0, final Object p1, final Object p2, final Object p3) { params[0] = p0; params[1] = p1; @@ -200,7 +189,7 @@ protected ReusableParameterizedMessage set( return this; } - protected ReusableParameterizedMessage set( + ReusableParameterizedMessage set( final String messagePattern, final Object p0, final Object p1, @@ -216,7 +205,7 @@ protected ReusableParameterizedMessage set( return this; } - protected ReusableParameterizedMessage set( + ReusableParameterizedMessage set( final String messagePattern, final Object p0, final Object p1, @@ -234,7 +223,7 @@ protected ReusableParameterizedMessage set( return this; } - protected ReusableParameterizedMessage set( + ReusableParameterizedMessage set( final String messagePattern, final Object p0, final Object p1, @@ -254,7 +243,7 @@ protected ReusableParameterizedMessage set( return this; } - protected ReusableParameterizedMessage set( + ReusableParameterizedMessage set( final String messagePattern, final Object p0, final Object p1, @@ -276,7 +265,7 @@ protected ReusableParameterizedMessage set( return this; } - protected ReusableParameterizedMessage set( + ReusableParameterizedMessage set( final String messagePattern, final Object p0, final Object p1, @@ -300,7 +289,7 @@ protected ReusableParameterizedMessage set( return this; } - protected ReusableParameterizedMessage set( + ReusableParameterizedMessage set( final String messagePattern, final Object p0, final Object p1, @@ -375,11 +364,7 @@ public String getFormattedMessage() { @Override public void formatTo(final StringBuilder builder) { - if (indices[0] < 0) { - ParameterFormatter.formatMessage(builder, messagePattern, getParams(), argCount); - } else { - ParameterFormatter.formatMessage2(builder, messagePattern, getParams(), usedCount, indices); - } + ParameterFormatter.formatMessage(builder, messagePattern, getParams(), argCount, patternAnalysis); } @Override @@ -395,5 +380,11 @@ public void clear() { // LOG4J2-1583 varargs = null; messagePattern = null; throwable = null; + // Cut down on the memory usage after an analysis with an excessive argument count + final int placeholderCharIndicesMaxLength = 16; + if (patternAnalysis.placeholderCharIndices != null + && patternAnalysis.placeholderCharIndices.length > placeholderCharIndicesMaxLength) { + patternAnalysis.placeholderCharIndices = new int[placeholderCharIndicesMaxLength]; + } } } diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableSimpleMessage.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableSimpleMessage.java index 88712bb5fef..bdf775b92bb 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableSimpleMessage.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableSimpleMessage.java @@ -24,7 +24,6 @@ */ @PerformanceSensitive("allocation") public class ReusableSimpleMessage implements ReusableMessage, CharSequence, ParameterVisitable { - private static final Object[] EMPTY_PARAMS = new Object[0]; private CharSequence charSequence; public void set(final String message) { @@ -47,7 +46,7 @@ public String getFormat() { @Override public Object[] getParameters() { - return EMPTY_PARAMS; + return Constants.EMPTY_OBJECT_ARRAY; } @Override diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/SimpleMessageFactory.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/SimpleMessageFactory.java index ad1e56fda5b..6cb17092e17 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/message/SimpleMessageFactory.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/SimpleMessageFactory.java @@ -17,7 +17,8 @@ package org.apache.logging.log4j.message; /** - * Creates {@link FormattedMessage} instances for {@link MessageFactory} methods. + * Creates {@link FormattedMessage} instances for {@link MessageFactory2} methods (and {@link MessageFactory} by + * extension.) *

* This uses is the simplest possible implementation of {@link Message}, the where you give the message to the * constructor argument as a String. diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/StringFormatterMessageFactory.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/StringFormatterMessageFactory.java index 7096b4d3694..7ce4296ba57 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/message/StringFormatterMessageFactory.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/StringFormatterMessageFactory.java @@ -44,9 +44,7 @@ public final class StringFormatterMessageFactory implements MessageFactory { /** * Constructs a message factory with default flow strings. */ - public StringFormatterMessageFactory() { - super(); - } + public StringFormatterMessageFactory() {} /** * Creates {@link StringFormattedMessage} instances. diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/ThreadDumpMessage.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/ThreadDumpMessage.java index b0d699f69c0..31bcf595478 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/message/ThreadDumpMessage.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/ThreadDumpMessage.java @@ -16,6 +16,8 @@ */ package org.apache.logging.log4j.message; +import static org.apache.logging.log4j.util.Chars.LF; + import aQute.bnd.annotation.Cardinality; import aQute.bnd.annotation.Resolution; import aQute.bnd.annotation.spi.ServiceConsumer; @@ -41,6 +43,7 @@ public class ThreadDumpMessage implements Message, StringBuilderFormattable { private final Map threads; private final String title; + private String formattedMessage; /** * Generate a ThreadDumpMessage with a title. @@ -62,6 +65,9 @@ public String toString() { */ @Override public String getFormattedMessage() { + if (formattedMessage != null) { + return formattedMessage; + } final StringBuilder sb = new StringBuilder(255); formatTo(sb); return sb.toString(); @@ -70,14 +76,14 @@ public String getFormattedMessage() { @Override public void formatTo(final StringBuilder sb) { sb.append(title); - if (!title.isEmpty()) { - sb.append('\n'); + if (title.length() > 0) { + sb.append(LF); } for (final Map.Entry entry : threads.entrySet()) { final ThreadInformation info = entry.getKey(); info.printThreadInfo(sb); info.printStack(sb, entry.getValue()); - sb.append('\n'); + sb.append(LF); } } @@ -106,7 +112,7 @@ public Object[] getParameters() { * Implementations of this class are loaded via the standard java Service Provider interface. *

*/ - public interface ThreadInfoFactory { + public static interface ThreadInfoFactory { Map createThreadInfo(); } diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractLogger.java b/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractLogger.java index 5dd788c06b1..f5210e1452e 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractLogger.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractLogger.java @@ -30,7 +30,6 @@ import org.apache.logging.log4j.spi.recycler.Recycler; import org.apache.logging.log4j.spi.recycler.RecyclerFactory; import org.apache.logging.log4j.status.StatusLogger; -import org.apache.logging.log4j.util.Cast; import org.apache.logging.log4j.util.LambdaUtil; import org.apache.logging.log4j.util.MessageSupplier; import org.apache.logging.log4j.util.PerformanceSensitive; @@ -169,8 +168,8 @@ public static void checkMessageFactory(final ExtendedLogger logger, final Messag } @Override - public void catching(final Level level, final Throwable t) { - catching(FQCN, level, t); + public void catching(final Level level, final Throwable throwable) { + catching(FQCN, level, throwable); } /** @@ -178,22 +177,22 @@ public void catching(final Level level, final Throwable t) { * * @param fqcn The fully qualified class name of the caller. * @param level The logging level. - * @param t The Throwable. + * @param throwable The Throwable. */ - protected void catching(final String fqcn, final Level level, final Throwable t) { + protected void catching(final String fqcn, final Level level, final Throwable throwable) { if (isEnabled(level, CATCHING_MARKER, (Object) null, null)) { - logMessageSafely(fqcn, level, CATCHING_MARKER, catchingMsg(t), t); + logMessageSafely(fqcn, level, CATCHING_MARKER, catchingMsg(throwable), throwable); } } @Override - public void catching(final Throwable t) { + public void catching(final Throwable throwable) { if (isEnabled(Level.ERROR, CATCHING_MARKER, (Object) null, null)) { - logMessageSafely(FQCN, Level.ERROR, CATCHING_MARKER, catchingMsg(t), t); + logMessageSafely(FQCN, Level.ERROR, CATCHING_MARKER, catchingMsg(throwable), throwable); } } - protected Message catchingMsg(final Throwable t) { + protected Message catchingMsg(final Throwable throwable) { return messageFactory.newMessage(CATCHING); } @@ -203,18 +202,18 @@ public void debug(final Marker marker, final CharSequence message) { } @Override - public void debug(final Marker marker, final CharSequence message, final Throwable t) { - logIfEnabled(FQCN, Level.DEBUG, marker, message, t); + public void debug(final Marker marker, final CharSequence message, final Throwable throwable) { + logIfEnabled(FQCN, Level.DEBUG, marker, message, throwable); } @Override - public void debug(final Marker marker, final Message msg) { - logIfEnabled(FQCN, Level.DEBUG, marker, msg, msg != null ? msg.getThrowable() : null); + public void debug(final Marker marker, final Message message) { + logIfEnabled(FQCN, Level.DEBUG, marker, message, message != null ? message.getThrowable() : null); } @Override - public void debug(final Marker marker, final Message msg, final Throwable t) { - logIfEnabled(FQCN, Level.DEBUG, marker, msg, t); + public void debug(final Marker marker, final Message message, final Throwable throwable) { + logIfEnabled(FQCN, Level.DEBUG, marker, message, throwable); } @Override @@ -223,8 +222,8 @@ public void debug(final Marker marker, final Object message) { } @Override - public void debug(final Marker marker, final Object message, final Throwable t) { - logIfEnabled(FQCN, Level.DEBUG, marker, message, t); + public void debug(final Marker marker, final Object message, final Throwable throwable) { + logIfEnabled(FQCN, Level.DEBUG, marker, message, throwable); } @Override @@ -238,18 +237,18 @@ public void debug(final Marker marker, final String message, final Object... par } @Override - public void debug(final Marker marker, final String message, final Throwable t) { - logIfEnabled(FQCN, Level.DEBUG, marker, message, t); + public void debug(final Marker marker, final String message, final Throwable throwable) { + logIfEnabled(FQCN, Level.DEBUG, marker, message, throwable); } @Override - public void debug(final Message msg) { - logIfEnabled(FQCN, Level.DEBUG, null, msg, msg != null ? msg.getThrowable() : null); + public void debug(final Message message) { + logIfEnabled(FQCN, Level.DEBUG, null, message, message != null ? message.getThrowable() : null); } @Override - public void debug(final Message msg, final Throwable t) { - logIfEnabled(FQCN, Level.DEBUG, null, msg, t); + public void debug(final Message message, final Throwable throwable) { + logIfEnabled(FQCN, Level.DEBUG, null, message, throwable); } @Override @@ -258,8 +257,8 @@ public void debug(final CharSequence message) { } @Override - public void debug(final CharSequence message, final Throwable t) { - logIfEnabled(FQCN, Level.DEBUG, null, message, t); + public void debug(final CharSequence message, final Throwable throwable) { + logIfEnabled(FQCN, Level.DEBUG, null, message, throwable); } @Override @@ -268,8 +267,8 @@ public void debug(final Object message) { } @Override - public void debug(final Object message, final Throwable t) { - logIfEnabled(FQCN, Level.DEBUG, null, message, t); + public void debug(final Object message, final Throwable throwable) { + logIfEnabled(FQCN, Level.DEBUG, null, message, throwable); } @Override @@ -283,8 +282,8 @@ public void debug(final String message, final Object... params) { } @Override - public void debug(final String message, final Throwable t) { - logIfEnabled(FQCN, Level.DEBUG, null, message, t); + public void debug(final String message, final Throwable throwable) { + logIfEnabled(FQCN, Level.DEBUG, null, message, throwable); } @Override @@ -324,23 +323,23 @@ public void debug(final String message, final Supplier... paramSuppliers) { } @Override - public void debug(final Marker marker, final MessageSupplier msgSupplier) { - logIfEnabled(FQCN, Level.DEBUG, marker, msgSupplier, (Throwable) null); + public void debug(final Marker marker, final MessageSupplier messageSupplier) { + logIfEnabled(FQCN, Level.DEBUG, marker, messageSupplier, (Throwable) null); } @Override - public void debug(final Marker marker, final MessageSupplier msgSupplier, final Throwable t) { - logIfEnabled(FQCN, Level.DEBUG, marker, msgSupplier, t); + public void debug(final Marker marker, final MessageSupplier messageSupplier, final Throwable throwable) { + logIfEnabled(FQCN, Level.DEBUG, marker, messageSupplier, throwable); } @Override - public void debug(final MessageSupplier msgSupplier) { - logIfEnabled(FQCN, Level.DEBUG, null, msgSupplier, (Throwable) null); + public void debug(final MessageSupplier messageSupplier) { + logIfEnabled(FQCN, Level.DEBUG, null, messageSupplier, (Throwable) null); } @Override - public void debug(final MessageSupplier msgSupplier, final Throwable t) { - logIfEnabled(FQCN, Level.DEBUG, null, msgSupplier, t); + public void debug(final MessageSupplier messageSupplier, final Throwable throwable) { + logIfEnabled(FQCN, Level.DEBUG, null, messageSupplier, throwable); } @Override @@ -648,13 +647,13 @@ protected EntryMessage entryMsg(final String format, final Supplier... paramS } @Override - public void error(final Marker marker, final Message msg) { - logIfEnabled(FQCN, Level.ERROR, marker, msg, msg != null ? msg.getThrowable() : null); + public void error(final Marker marker, final Message message) { + logIfEnabled(FQCN, Level.ERROR, marker, message, message != null ? message.getThrowable() : null); } @Override - public void error(final Marker marker, final Message msg, final Throwable t) { - logIfEnabled(FQCN, Level.ERROR, marker, msg, t); + public void error(final Marker marker, final Message message, final Throwable throwable) { + logIfEnabled(FQCN, Level.ERROR, marker, message, throwable); } @Override @@ -663,8 +662,8 @@ public void error(final Marker marker, final CharSequence message) { } @Override - public void error(final Marker marker, final CharSequence message, final Throwable t) { - logIfEnabled(FQCN, Level.ERROR, marker, message, t); + public void error(final Marker marker, final CharSequence message, final Throwable throwable) { + logIfEnabled(FQCN, Level.ERROR, marker, message, throwable); } @Override @@ -673,8 +672,8 @@ public void error(final Marker marker, final Object message) { } @Override - public void error(final Marker marker, final Object message, final Throwable t) { - logIfEnabled(FQCN, Level.ERROR, marker, message, t); + public void error(final Marker marker, final Object message, final Throwable throwable) { + logIfEnabled(FQCN, Level.ERROR, marker, message, throwable); } @Override @@ -688,18 +687,18 @@ public void error(final Marker marker, final String message, final Object... par } @Override - public void error(final Marker marker, final String message, final Throwable t) { - logIfEnabled(FQCN, Level.ERROR, marker, message, t); + public void error(final Marker marker, final String message, final Throwable throwable) { + logIfEnabled(FQCN, Level.ERROR, marker, message, throwable); } @Override - public void error(final Message msg) { - logIfEnabled(FQCN, Level.ERROR, null, msg, msg != null ? msg.getThrowable() : null); + public void error(final Message message) { + logIfEnabled(FQCN, Level.ERROR, null, message, message != null ? message.getThrowable() : null); } @Override - public void error(final Message msg, final Throwable t) { - logIfEnabled(FQCN, Level.ERROR, null, msg, t); + public void error(final Message message, final Throwable throwable) { + logIfEnabled(FQCN, Level.ERROR, null, message, throwable); } @Override @@ -708,8 +707,8 @@ public void error(final CharSequence message) { } @Override - public void error(final CharSequence message, final Throwable t) { - logIfEnabled(FQCN, Level.ERROR, null, message, t); + public void error(final CharSequence message, final Throwable throwable) { + logIfEnabled(FQCN, Level.ERROR, null, message, throwable); } @Override @@ -718,8 +717,8 @@ public void error(final Object message) { } @Override - public void error(final Object message, final Throwable t) { - logIfEnabled(FQCN, Level.ERROR, null, message, t); + public void error(final Object message, final Throwable throwable) { + logIfEnabled(FQCN, Level.ERROR, null, message, throwable); } @Override @@ -733,8 +732,8 @@ public void error(final String message, final Object... params) { } @Override - public void error(final String message, final Throwable t) { - logIfEnabled(FQCN, Level.ERROR, null, message, t); + public void error(final String message, final Throwable throwable) { + logIfEnabled(FQCN, Level.ERROR, null, message, throwable); } @Override @@ -774,23 +773,23 @@ public void error(final String message, final Supplier... paramSuppliers) { } @Override - public void error(final Marker marker, final MessageSupplier msgSupplier) { - logIfEnabled(FQCN, Level.ERROR, marker, msgSupplier, (Throwable) null); + public void error(final Marker marker, final MessageSupplier messageSupplier) { + logIfEnabled(FQCN, Level.ERROR, marker, messageSupplier, (Throwable) null); } @Override - public void error(final Marker marker, final MessageSupplier msgSupplier, final Throwable t) { - logIfEnabled(FQCN, Level.ERROR, marker, msgSupplier, t); + public void error(final Marker marker, final MessageSupplier messageSupplier, final Throwable throwable) { + logIfEnabled(FQCN, Level.ERROR, marker, messageSupplier, throwable); } @Override - public void error(final MessageSupplier msgSupplier) { - logIfEnabled(FQCN, Level.ERROR, null, msgSupplier, (Throwable) null); + public void error(final MessageSupplier messageSupplier) { + logIfEnabled(FQCN, Level.ERROR, null, messageSupplier, (Throwable) null); } @Override - public void error(final MessageSupplier msgSupplier, final Throwable t) { - logIfEnabled(FQCN, Level.ERROR, null, msgSupplier, t); + public void error(final MessageSupplier messageSupplier, final Throwable throwable) { + logIfEnabled(FQCN, Level.ERROR, null, messageSupplier, throwable); } @Override @@ -1038,13 +1037,13 @@ protected Message exitMsg(final String format, final Object result) { } @Override - public void fatal(final Marker marker, final Message msg) { - logIfEnabled(FQCN, Level.FATAL, marker, msg, msg != null ? msg.getThrowable() : null); + public void fatal(final Marker marker, final Message message) { + logIfEnabled(FQCN, Level.FATAL, marker, message, message != null ? message.getThrowable() : null); } @Override - public void fatal(final Marker marker, final Message msg, final Throwable t) { - logIfEnabled(FQCN, Level.FATAL, marker, msg, t); + public void fatal(final Marker marker, final Message message, final Throwable throwable) { + logIfEnabled(FQCN, Level.FATAL, marker, message, throwable); } @Override @@ -1053,8 +1052,8 @@ public void fatal(final Marker marker, final CharSequence message) { } @Override - public void fatal(final Marker marker, final CharSequence message, final Throwable t) { - logIfEnabled(FQCN, Level.FATAL, marker, message, t); + public void fatal(final Marker marker, final CharSequence message, final Throwable throwable) { + logIfEnabled(FQCN, Level.FATAL, marker, message, throwable); } @Override @@ -1063,8 +1062,8 @@ public void fatal(final Marker marker, final Object message) { } @Override - public void fatal(final Marker marker, final Object message, final Throwable t) { - logIfEnabled(FQCN, Level.FATAL, marker, message, t); + public void fatal(final Marker marker, final Object message, final Throwable throwable) { + logIfEnabled(FQCN, Level.FATAL, marker, message, throwable); } @Override @@ -1078,18 +1077,18 @@ public void fatal(final Marker marker, final String message, final Object... par } @Override - public void fatal(final Marker marker, final String message, final Throwable t) { - logIfEnabled(FQCN, Level.FATAL, marker, message, t); + public void fatal(final Marker marker, final String message, final Throwable throwable) { + logIfEnabled(FQCN, Level.FATAL, marker, message, throwable); } @Override - public void fatal(final Message msg) { - logIfEnabled(FQCN, Level.FATAL, null, msg, msg != null ? msg.getThrowable() : null); + public void fatal(final Message message) { + logIfEnabled(FQCN, Level.FATAL, null, message, message != null ? message.getThrowable() : null); } @Override - public void fatal(final Message msg, final Throwable t) { - logIfEnabled(FQCN, Level.FATAL, null, msg, t); + public void fatal(final Message message, final Throwable throwable) { + logIfEnabled(FQCN, Level.FATAL, null, message, throwable); } @Override @@ -1098,8 +1097,8 @@ public void fatal(final CharSequence message) { } @Override - public void fatal(final CharSequence message, final Throwable t) { - logIfEnabled(FQCN, Level.FATAL, null, message, t); + public void fatal(final CharSequence message, final Throwable throwable) { + logIfEnabled(FQCN, Level.FATAL, null, message, throwable); } @Override @@ -1108,8 +1107,8 @@ public void fatal(final Object message) { } @Override - public void fatal(final Object message, final Throwable t) { - logIfEnabled(FQCN, Level.FATAL, null, message, t); + public void fatal(final Object message, final Throwable throwable) { + logIfEnabled(FQCN, Level.FATAL, null, message, throwable); } @Override @@ -1123,8 +1122,8 @@ public void fatal(final String message, final Object... params) { } @Override - public void fatal(final String message, final Throwable t) { - logIfEnabled(FQCN, Level.FATAL, null, message, t); + public void fatal(final String message, final Throwable throwable) { + logIfEnabled(FQCN, Level.FATAL, null, message, throwable); } @Override @@ -1164,23 +1163,23 @@ public void fatal(final String message, final Supplier... paramSuppliers) { } @Override - public void fatal(final Marker marker, final MessageSupplier msgSupplier) { - logIfEnabled(FQCN, Level.FATAL, marker, msgSupplier, (Throwable) null); + public void fatal(final Marker marker, final MessageSupplier messageSupplier) { + logIfEnabled(FQCN, Level.FATAL, marker, messageSupplier, (Throwable) null); } @Override - public void fatal(final Marker marker, final MessageSupplier msgSupplier, final Throwable t) { - logIfEnabled(FQCN, Level.FATAL, marker, msgSupplier, t); + public void fatal(final Marker marker, final MessageSupplier messageSupplier, final Throwable throwable) { + logIfEnabled(FQCN, Level.FATAL, marker, messageSupplier, throwable); } @Override - public void fatal(final MessageSupplier msgSupplier) { - logIfEnabled(FQCN, Level.FATAL, null, msgSupplier, (Throwable) null); + public void fatal(final MessageSupplier messageSupplier) { + logIfEnabled(FQCN, Level.FATAL, null, messageSupplier, (Throwable) null); } @Override - public void fatal(final MessageSupplier msgSupplier, final Throwable t) { - logIfEnabled(FQCN, Level.FATAL, null, msgSupplier, t); + public void fatal(final MessageSupplier messageSupplier, final Throwable throwable) { + logIfEnabled(FQCN, Level.FATAL, null, messageSupplier, throwable); } @Override @@ -1392,9 +1391,10 @@ public void fatal( logIfEnabled(FQCN, Level.FATAL, null, message, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9); } + @SuppressWarnings("unchecked") @Override public MF getMessageFactory() { - return Cast.cast(messageFactory); + return (MF) messageFactory; } @Override @@ -1408,13 +1408,13 @@ public String getName() { } @Override - public void info(final Marker marker, final Message msg) { - logIfEnabled(FQCN, Level.INFO, marker, msg, msg != null ? msg.getThrowable() : null); + public void info(final Marker marker, final Message message) { + logIfEnabled(FQCN, Level.INFO, marker, message, message != null ? message.getThrowable() : null); } @Override - public void info(final Marker marker, final Message msg, final Throwable t) { - logIfEnabled(FQCN, Level.INFO, marker, msg, t); + public void info(final Marker marker, final Message message, final Throwable throwable) { + logIfEnabled(FQCN, Level.INFO, marker, message, throwable); } @Override @@ -1423,8 +1423,8 @@ public void info(final Marker marker, final CharSequence message) { } @Override - public void info(final Marker marker, final CharSequence message, final Throwable t) { - logIfEnabled(FQCN, Level.INFO, marker, message, t); + public void info(final Marker marker, final CharSequence message, final Throwable throwable) { + logIfEnabled(FQCN, Level.INFO, marker, message, throwable); } @Override @@ -1433,8 +1433,8 @@ public void info(final Marker marker, final Object message) { } @Override - public void info(final Marker marker, final Object message, final Throwable t) { - logIfEnabled(FQCN, Level.INFO, marker, message, t); + public void info(final Marker marker, final Object message, final Throwable throwable) { + logIfEnabled(FQCN, Level.INFO, marker, message, throwable); } @Override @@ -1448,18 +1448,18 @@ public void info(final Marker marker, final String message, final Object... para } @Override - public void info(final Marker marker, final String message, final Throwable t) { - logIfEnabled(FQCN, Level.INFO, marker, message, t); + public void info(final Marker marker, final String message, final Throwable throwable) { + logIfEnabled(FQCN, Level.INFO, marker, message, throwable); } @Override - public void info(final Message msg) { - logIfEnabled(FQCN, Level.INFO, null, msg, msg != null ? msg.getThrowable() : null); + public void info(final Message message) { + logIfEnabled(FQCN, Level.INFO, null, message, message != null ? message.getThrowable() : null); } @Override - public void info(final Message msg, final Throwable t) { - logIfEnabled(FQCN, Level.INFO, null, msg, t); + public void info(final Message message, final Throwable throwable) { + logIfEnabled(FQCN, Level.INFO, null, message, throwable); } @Override @@ -1468,8 +1468,8 @@ public void info(final CharSequence message) { } @Override - public void info(final CharSequence message, final Throwable t) { - logIfEnabled(FQCN, Level.INFO, null, message, t); + public void info(final CharSequence message, final Throwable throwable) { + logIfEnabled(FQCN, Level.INFO, null, message, throwable); } @Override @@ -1478,8 +1478,8 @@ public void info(final Object message) { } @Override - public void info(final Object message, final Throwable t) { - logIfEnabled(FQCN, Level.INFO, null, message, t); + public void info(final Object message, final Throwable throwable) { + logIfEnabled(FQCN, Level.INFO, null, message, throwable); } @Override @@ -1493,8 +1493,8 @@ public void info(final String message, final Object... params) { } @Override - public void info(final String message, final Throwable t) { - logIfEnabled(FQCN, Level.INFO, null, message, t); + public void info(final String message, final Throwable throwable) { + logIfEnabled(FQCN, Level.INFO, null, message, throwable); } @Override @@ -1534,23 +1534,23 @@ public void info(final String message, final Supplier... paramSuppliers) { } @Override - public void info(final Marker marker, final MessageSupplier msgSupplier) { - logIfEnabled(FQCN, Level.INFO, marker, msgSupplier, (Throwable) null); + public void info(final Marker marker, final MessageSupplier messageSupplier) { + logIfEnabled(FQCN, Level.INFO, marker, messageSupplier, (Throwable) null); } @Override - public void info(final Marker marker, final MessageSupplier msgSupplier, final Throwable t) { - logIfEnabled(FQCN, Level.INFO, marker, msgSupplier, t); + public void info(final Marker marker, final MessageSupplier messageSupplier, final Throwable throwable) { + logIfEnabled(FQCN, Level.INFO, marker, messageSupplier, throwable); } @Override - public void info(final MessageSupplier msgSupplier) { - logIfEnabled(FQCN, Level.INFO, null, msgSupplier, (Throwable) null); + public void info(final MessageSupplier messageSupplier) { + logIfEnabled(FQCN, Level.INFO, null, messageSupplier, (Throwable) null); } @Override - public void info(final MessageSupplier msgSupplier, final Throwable t) { - logIfEnabled(FQCN, Level.INFO, null, msgSupplier, t); + public void info(final MessageSupplier messageSupplier, final Throwable throwable) { + logIfEnabled(FQCN, Level.INFO, null, messageSupplier, throwable); } @Override @@ -1833,13 +1833,13 @@ public boolean isWarnEnabled(final Marker marker) { } @Override - public void log(final Level level, final Marker marker, final Message msg) { - logIfEnabled(FQCN, level, marker, msg, msg != null ? msg.getThrowable() : null); + public void log(final Level level, final Marker marker, final Message message) { + logIfEnabled(FQCN, level, marker, message, message != null ? message.getThrowable() : null); } @Override - public void log(final Level level, final Marker marker, final Message msg, final Throwable t) { - logIfEnabled(FQCN, level, marker, msg, t); + public void log(final Level level, final Marker marker, final Message message, final Throwable throwable) { + logIfEnabled(FQCN, level, marker, message, throwable); } @Override @@ -1848,9 +1848,9 @@ public void log(final Level level, final Marker marker, final CharSequence messa } @Override - public void log(final Level level, final Marker marker, final CharSequence message, final Throwable t) { - if (isEnabled(level, marker, message, t)) { - logMessage(FQCN, level, marker, message, t); + public void log(final Level level, final Marker marker, final CharSequence message, final Throwable throwable) { + if (isEnabled(level, marker, message, throwable)) { + logMessage(FQCN, level, marker, message, throwable); } } @@ -1860,9 +1860,9 @@ public void log(final Level level, final Marker marker, final Object message) { } @Override - public void log(final Level level, final Marker marker, final Object message, final Throwable t) { - if (isEnabled(level, marker, message, t)) { - logMessage(FQCN, level, marker, message, t); + public void log(final Level level, final Marker marker, final Object message, final Throwable throwable) { + if (isEnabled(level, marker, message, throwable)) { + logMessage(FQCN, level, marker, message, throwable); } } @@ -1877,18 +1877,18 @@ public void log(final Level level, final Marker marker, final String message, fi } @Override - public void log(final Level level, final Marker marker, final String message, final Throwable t) { - logIfEnabled(FQCN, level, marker, message, t); + public void log(final Level level, final Marker marker, final String message, final Throwable throwable) { + logIfEnabled(FQCN, level, marker, message, throwable); } @Override - public void log(final Level level, final Message msg) { - logIfEnabled(FQCN, level, null, msg, msg != null ? msg.getThrowable() : null); + public void log(final Level level, final Message message) { + logIfEnabled(FQCN, level, null, message, message != null ? message.getThrowable() : null); } @Override - public void log(final Level level, final Message msg, final Throwable t) { - logIfEnabled(FQCN, level, null, msg, t); + public void log(final Level level, final Message message, final Throwable throwable) { + logIfEnabled(FQCN, level, null, message, throwable); } @Override @@ -1897,8 +1897,8 @@ public void log(final Level level, final CharSequence message) { } @Override - public void log(final Level level, final CharSequence message, final Throwable t) { - logIfEnabled(FQCN, level, null, message, t); + public void log(final Level level, final CharSequence message, final Throwable throwable) { + logIfEnabled(FQCN, level, null, message, throwable); } @Override @@ -1907,8 +1907,8 @@ public void log(final Level level, final Object message) { } @Override - public void log(final Level level, final Object message, final Throwable t) { - logIfEnabled(FQCN, level, null, message, t); + public void log(final Level level, final Object message, final Throwable throwable) { + logIfEnabled(FQCN, level, null, message, throwable); } @Override @@ -1922,8 +1922,8 @@ public void log(final Level level, final String message, final Object... params) } @Override - public void log(final Level level, final String message, final Throwable t) { - logIfEnabled(FQCN, level, null, message, t); + public void log(final Level level, final String message, final Throwable throwable) { + logIfEnabled(FQCN, level, null, message, throwable); } @Override @@ -1964,23 +1964,24 @@ public void log(final Level level, final String message, final Supplier... pa } @Override - public void log(final Level level, final Marker marker, final MessageSupplier msgSupplier) { - logIfEnabled(FQCN, level, marker, msgSupplier, (Throwable) null); + public void log(final Level level, final Marker marker, final MessageSupplier messageSupplier) { + logIfEnabled(FQCN, level, marker, messageSupplier, (Throwable) null); } @Override - public void log(final Level level, final Marker marker, final MessageSupplier msgSupplier, final Throwable t) { - logIfEnabled(FQCN, level, marker, msgSupplier, t); + public void log( + final Level level, final Marker marker, final MessageSupplier messageSupplier, final Throwable throwable) { + logIfEnabled(FQCN, level, marker, messageSupplier, throwable); } @Override - public void log(final Level level, final MessageSupplier msgSupplier) { - logIfEnabled(FQCN, level, null, msgSupplier, (Throwable) null); + public void log(final Level level, final MessageSupplier messageSupplier) { + logIfEnabled(FQCN, level, null, messageSupplier, (Throwable) null); } @Override - public void log(final Level level, final MessageSupplier msgSupplier, final Throwable t) { - logIfEnabled(FQCN, level, null, msgSupplier, t); + public void log(final Level level, final MessageSupplier messageSupplier, final Throwable throwable) { + logIfEnabled(FQCN, level, null, messageSupplier, throwable); } @Override @@ -2224,9 +2225,13 @@ public void log( @Override public void logIfEnabled( - final String fqcn, final Level level, final Marker marker, final Message msg, final Throwable t) { - if (isEnabled(level, marker, msg, t)) { - logMessageSafely(fqcn, level, marker, msg, t); + final String fqcn, + final Level level, + final Marker marker, + final Message message, + final Throwable throwable) { + if (isEnabled(level, marker, message, throwable)) { + logMessageSafely(fqcn, level, marker, message, throwable); } } @@ -2235,26 +2240,34 @@ public void logIfEnabled( final String fqcn, final Level level, final Marker marker, - final MessageSupplier msgSupplier, - final Throwable t) { - if (isEnabled(level, marker, msgSupplier, t)) { - logMessage(fqcn, level, marker, msgSupplier, t); + final MessageSupplier messageSupplier, + final Throwable throwable) { + if (isEnabled(level, marker, messageSupplier, throwable)) { + logMessage(fqcn, level, marker, messageSupplier, throwable); } } @Override public void logIfEnabled( - final String fqcn, final Level level, final Marker marker, final Object message, final Throwable t) { - if (isEnabled(level, marker, message, t)) { - logMessage(fqcn, level, marker, message, t); + final String fqcn, + final Level level, + final Marker marker, + final Object message, + final Throwable throwable) { + if (isEnabled(level, marker, message, throwable)) { + logMessage(fqcn, level, marker, message, throwable); } } @Override public void logIfEnabled( - final String fqcn, final Level level, final Marker marker, final CharSequence message, final Throwable t) { - if (isEnabled(level, marker, message, t)) { - logMessage(fqcn, level, marker, message, t); + final String fqcn, + final Level level, + final Marker marker, + final CharSequence message, + final Throwable throwable) { + if (isEnabled(level, marker, message, throwable)) { + logMessage(fqcn, level, marker, message, throwable); } } @@ -2462,30 +2475,44 @@ public void logIfEnabled( @Override public void logIfEnabled( - final String fqcn, final Level level, final Marker marker, final String message, final Throwable t) { - if (isEnabled(level, marker, message, t)) { - logMessage(fqcn, level, marker, message, t); + final String fqcn, + final Level level, + final Marker marker, + final String message, + final Throwable throwable) { + if (isEnabled(level, marker, message, throwable)) { + logMessage(fqcn, level, marker, message, throwable); } } protected void logMessage( - final String fqcn, final Level level, final Marker marker, final CharSequence message, final Throwable t) { - logMessageSafely(fqcn, level, marker, messageFactory.newMessage(message), t); + final String fqcn, + final Level level, + final Marker marker, + final CharSequence message, + final Throwable throwable) { + logMessageSafely(fqcn, level, marker, messageFactory.newMessage(message), throwable); } protected void logMessage( - final String fqcn, final Level level, final Marker marker, final Object message, final Throwable t) { - logMessageSafely(fqcn, level, marker, messageFactory.newMessage(message), t); + final String fqcn, + final Level level, + final Marker marker, + final Object message, + final Throwable throwable) { + logMessageSafely(fqcn, level, marker, messageFactory.newMessage(message), throwable); } protected void logMessage( final String fqcn, final Level level, final Marker marker, - final MessageSupplier msgSupplier, - final Throwable t) { - final Message message = LambdaUtil.get(msgSupplier); - logMessageSafely(fqcn, level, marker, message, (t == null && message != null) ? message.getThrowable() : t); + final MessageSupplier messageSupplier, + final Throwable throwable) { + final Message message = LambdaUtil.get(messageSupplier); + final Throwable effectiveThrowable = + (throwable == null && message != null) ? message.getThrowable() : throwable; + logMessageSafely(fqcn, level, marker, message, effectiveThrowable); } @SuppressWarnings("deprecation") @@ -2502,8 +2529,12 @@ protected void logMessage( } protected void logMessage( - final String fqcn, final Level level, final Marker marker, final String message, final Throwable t) { - logMessageSafely(fqcn, level, marker, messageFactory.newMessage(message), t); + final String fqcn, + final Level level, + final Marker marker, + final String message, + final Throwable throwable) { + logMessageSafely(fqcn, level, marker, messageFactory.newMessage(message), throwable); } protected void logMessage(final String fqcn, final Level level, final Marker marker, final String message) { @@ -2701,16 +2732,16 @@ protected void log( @Override public void printf(final Level level, final Marker marker, final String format, final Object... params) { if (isEnabled(level, marker, format, params)) { - final Message msg = new StringFormattedMessage(format, params); - logMessageSafely(FQCN, level, marker, msg, msg.getThrowable()); + final Message message = new StringFormattedMessage(format, params); + logMessageSafely(FQCN, level, marker, message, message.getThrowable()); } } @Override public void printf(final Level level, final String format, final Object... params) { if (isEnabled(level, null, format, params)) { - final Message msg = new StringFormattedMessage(format, params); - logMessageSafely(FQCN, level, null, msg, msg.getThrowable()); + final Message message = new StringFormattedMessage(format, params); + logMessageSafely(FQCN, level, null, message, message.getThrowable()); } } @@ -2718,12 +2749,16 @@ public void printf(final Level level, final String format, final Object... param // NOTE: This is a hot method. Current implementation compiles to 30 bytes of byte code. // This is within the 35 byte MaxInlineSize threshold. Modify with care! private void logMessageSafely( - final String fqcn, final Level level, final Marker marker, final Message msg, final Throwable throwable) { + final String fqcn, + final Level level, + final Marker marker, + final Message message, + final Throwable throwable) { try { - logMessageTrackRecursion(fqcn, level, marker, msg, throwable); + logMessageTrackRecursion(fqcn, level, marker, message, throwable); } finally { // LOG4J2-1583 prevent scrambled logs when logging calls are nested (logging in toString()) - messageFactory.recycle(msg); + messageFactory.recycle(message); } } @@ -2731,10 +2766,14 @@ private void logMessageSafely( // NOTE: This is a hot method. Current implementation compiles to 33 bytes of byte code. // This is within the 35 byte MaxInlineSize threshold. Modify with care! private void logMessageTrackRecursion( - final String fqcn, final Level level, final Marker marker, final Message msg, final Throwable throwable) { + final String fqcn, + final Level level, + final Marker marker, + final Message message, + final Throwable throwable) { try { incrementRecursionDepth(); // LOG4J2-1518, LOG4J2-2031 - tryLogMessage(fqcn, getLocation(fqcn), level, marker, msg, throwable); + tryLogMessage(fqcn, getLocation(fqcn), level, marker, message, throwable); } finally { decrementRecursionDepth(); } @@ -2771,7 +2810,7 @@ public static int getRecursionDepth() { } @PerformanceSensitive - // NOTE: This is a hot method. Current implementation compiles to 27 bytes of byte code. + // NOTE: This is a hot method. Current implementation compiles to 26 bytes of byte code. // This is within the 35 byte MaxInlineSize threshold. Modify with care! private void tryLogMessage( final String fqcn, @@ -2812,13 +2851,13 @@ private void handleLogMessageException(final Throwable throwable, final String f } @Override - public T throwing(final T t) { - return throwing(FQCN, Level.ERROR, t); + public T throwing(final T throwable) { + return throwing(FQCN, Level.ERROR, throwable); } @Override - public T throwing(final Level level, final T t) { - return throwing(FQCN, level, t); + public T throwing(final Level level, final T throwable) { + return throwing(FQCN, level, throwable); } /** @@ -2827,28 +2866,28 @@ public T throwing(final Level level, final T t) { * @param the type of the Throwable. * @param fqcn the fully qualified class name of this Logger implementation. * @param level The logging Level. - * @param t The Throwable. + * @param throwable The Throwable. * @return the Throwable. */ - protected T throwing(final String fqcn, final Level level, final T t) { + protected T throwing(final String fqcn, final Level level, final T throwable) { if (isEnabled(level, THROWING_MARKER, (Object) null, null)) { - logMessageSafely(fqcn, level, THROWING_MARKER, throwingMsg(t), t); + logMessageSafely(fqcn, level, THROWING_MARKER, throwingMsg(throwable), throwable); } - return t; + return throwable; } - protected Message throwingMsg(final Throwable t) { + protected Message throwingMsg(final Throwable throwable) { return messageFactory.newMessage(THROWING); } @Override - public void trace(final Marker marker, final Message msg) { - logIfEnabled(FQCN, Level.TRACE, marker, msg, msg != null ? msg.getThrowable() : null); + public void trace(final Marker marker, final Message message) { + logIfEnabled(FQCN, Level.TRACE, marker, message, message != null ? message.getThrowable() : null); } @Override - public void trace(final Marker marker, final Message msg, final Throwable t) { - logIfEnabled(FQCN, Level.TRACE, marker, msg, t); + public void trace(final Marker marker, final Message message, final Throwable throwable) { + logIfEnabled(FQCN, Level.TRACE, marker, message, throwable); } @Override @@ -2857,8 +2896,8 @@ public void trace(final Marker marker, final CharSequence message) { } @Override - public void trace(final Marker marker, final CharSequence message, final Throwable t) { - logIfEnabled(FQCN, Level.TRACE, marker, message, t); + public void trace(final Marker marker, final CharSequence message, final Throwable throwable) { + logIfEnabled(FQCN, Level.TRACE, marker, message, throwable); } @Override @@ -2867,8 +2906,8 @@ public void trace(final Marker marker, final Object message) { } @Override - public void trace(final Marker marker, final Object message, final Throwable t) { - logIfEnabled(FQCN, Level.TRACE, marker, message, t); + public void trace(final Marker marker, final Object message, final Throwable throwable) { + logIfEnabled(FQCN, Level.TRACE, marker, message, throwable); } @Override @@ -2882,18 +2921,18 @@ public void trace(final Marker marker, final String message, final Object... par } @Override - public void trace(final Marker marker, final String message, final Throwable t) { - logIfEnabled(FQCN, Level.TRACE, marker, message, t); + public void trace(final Marker marker, final String message, final Throwable throwable) { + logIfEnabled(FQCN, Level.TRACE, marker, message, throwable); } @Override - public void trace(final Message msg) { - logIfEnabled(FQCN, Level.TRACE, null, msg, msg != null ? msg.getThrowable() : null); + public void trace(final Message message) { + logIfEnabled(FQCN, Level.TRACE, null, message, message != null ? message.getThrowable() : null); } @Override - public void trace(final Message msg, final Throwable t) { - logIfEnabled(FQCN, Level.TRACE, null, msg, t); + public void trace(final Message message, final Throwable throwable) { + logIfEnabled(FQCN, Level.TRACE, null, message, throwable); } @Override @@ -2902,8 +2941,8 @@ public void trace(final CharSequence message) { } @Override - public void trace(final CharSequence message, final Throwable t) { - logIfEnabled(FQCN, Level.TRACE, null, message, t); + public void trace(final CharSequence message, final Throwable throwable) { + logIfEnabled(FQCN, Level.TRACE, null, message, throwable); } @Override @@ -2912,8 +2951,8 @@ public void trace(final Object message) { } @Override - public void trace(final Object message, final Throwable t) { - logIfEnabled(FQCN, Level.TRACE, null, message, t); + public void trace(final Object message, final Throwable throwable) { + logIfEnabled(FQCN, Level.TRACE, null, message, throwable); } @Override @@ -2927,8 +2966,8 @@ public void trace(final String message, final Object... params) { } @Override - public void trace(final String message, final Throwable t) { - logIfEnabled(FQCN, Level.TRACE, null, message, t); + public void trace(final String message, final Throwable throwable) { + logIfEnabled(FQCN, Level.TRACE, null, message, throwable); } @Override @@ -2968,23 +3007,23 @@ public void trace(final String message, final Supplier... paramSuppliers) { } @Override - public void trace(final Marker marker, final MessageSupplier msgSupplier) { - logIfEnabled(FQCN, Level.TRACE, marker, msgSupplier, (Throwable) null); + public void trace(final Marker marker, final MessageSupplier messageSupplier) { + logIfEnabled(FQCN, Level.TRACE, marker, messageSupplier, (Throwable) null); } @Override - public void trace(final Marker marker, final MessageSupplier msgSupplier, final Throwable t) { - logIfEnabled(FQCN, Level.TRACE, marker, msgSupplier, t); + public void trace(final Marker marker, final MessageSupplier messageSupplier, final Throwable throwable) { + logIfEnabled(FQCN, Level.TRACE, marker, messageSupplier, throwable); } @Override - public void trace(final MessageSupplier msgSupplier) { - logIfEnabled(FQCN, Level.TRACE, null, msgSupplier, (Throwable) null); + public void trace(final MessageSupplier messageSupplier) { + logIfEnabled(FQCN, Level.TRACE, null, messageSupplier, (Throwable) null); } @Override - public void trace(final MessageSupplier msgSupplier, final Throwable t) { - logIfEnabled(FQCN, Level.TRACE, null, msgSupplier, t); + public void trace(final MessageSupplier messageSupplier, final Throwable throwable) { + logIfEnabled(FQCN, Level.TRACE, null, messageSupplier, throwable); } @Override @@ -3268,13 +3307,13 @@ public R traceExit(final Message message, final R result) { } @Override - public void warn(final Marker marker, final Message msg) { - logIfEnabled(FQCN, Level.WARN, marker, msg, msg != null ? msg.getThrowable() : null); + public void warn(final Marker marker, final Message message) { + logIfEnabled(FQCN, Level.WARN, marker, message, message != null ? message.getThrowable() : null); } @Override - public void warn(final Marker marker, final Message msg, final Throwable t) { - logIfEnabled(FQCN, Level.WARN, marker, msg, t); + public void warn(final Marker marker, final Message message, final Throwable throwable) { + logIfEnabled(FQCN, Level.WARN, marker, message, throwable); } @Override @@ -3283,8 +3322,8 @@ public void warn(final Marker marker, final CharSequence message) { } @Override - public void warn(final Marker marker, final CharSequence message, final Throwable t) { - logIfEnabled(FQCN, Level.WARN, marker, message, t); + public void warn(final Marker marker, final CharSequence message, final Throwable throwable) { + logIfEnabled(FQCN, Level.WARN, marker, message, throwable); } @Override @@ -3293,8 +3332,8 @@ public void warn(final Marker marker, final Object message) { } @Override - public void warn(final Marker marker, final Object message, final Throwable t) { - logIfEnabled(FQCN, Level.WARN, marker, message, t); + public void warn(final Marker marker, final Object message, final Throwable throwable) { + logIfEnabled(FQCN, Level.WARN, marker, message, throwable); } @Override @@ -3308,18 +3347,18 @@ public void warn(final Marker marker, final String message, final Object... para } @Override - public void warn(final Marker marker, final String message, final Throwable t) { - logIfEnabled(FQCN, Level.WARN, marker, message, t); + public void warn(final Marker marker, final String message, final Throwable throwable) { + logIfEnabled(FQCN, Level.WARN, marker, message, throwable); } @Override - public void warn(final Message msg) { - logIfEnabled(FQCN, Level.WARN, null, msg, msg != null ? msg.getThrowable() : null); + public void warn(final Message message) { + logIfEnabled(FQCN, Level.WARN, null, message, message != null ? message.getThrowable() : null); } @Override - public void warn(final Message msg, final Throwable t) { - logIfEnabled(FQCN, Level.WARN, null, msg, t); + public void warn(final Message message, final Throwable throwable) { + logIfEnabled(FQCN, Level.WARN, null, message, throwable); } @Override @@ -3328,8 +3367,8 @@ public void warn(final CharSequence message) { } @Override - public void warn(final CharSequence message, final Throwable t) { - logIfEnabled(FQCN, Level.WARN, null, message, t); + public void warn(final CharSequence message, final Throwable throwable) { + logIfEnabled(FQCN, Level.WARN, null, message, throwable); } @Override @@ -3338,8 +3377,8 @@ public void warn(final Object message) { } @Override - public void warn(final Object message, final Throwable t) { - logIfEnabled(FQCN, Level.WARN, null, message, t); + public void warn(final Object message, final Throwable throwable) { + logIfEnabled(FQCN, Level.WARN, null, message, throwable); } @Override @@ -3353,8 +3392,8 @@ public void warn(final String message, final Object... params) { } @Override - public void warn(final String message, final Throwable t) { - logIfEnabled(FQCN, Level.WARN, null, message, t); + public void warn(final String message, final Throwable throwable) { + logIfEnabled(FQCN, Level.WARN, null, message, throwable); } @Override @@ -3394,23 +3433,23 @@ public void warn(final String message, final Supplier... paramSuppliers) { } @Override - public void warn(final Marker marker, final MessageSupplier msgSupplier) { - logIfEnabled(FQCN, Level.WARN, marker, msgSupplier, (Throwable) null); + public void warn(final Marker marker, final MessageSupplier messageSupplier) { + logIfEnabled(FQCN, Level.WARN, marker, messageSupplier, (Throwable) null); } @Override - public void warn(final Marker marker, final MessageSupplier msgSupplier, final Throwable t) { - logIfEnabled(FQCN, Level.WARN, marker, msgSupplier, t); + public void warn(final Marker marker, final MessageSupplier messageSupplier, final Throwable throwable) { + logIfEnabled(FQCN, Level.WARN, marker, messageSupplier, throwable); } @Override - public void warn(final MessageSupplier msgSupplier) { - logIfEnabled(FQCN, Level.WARN, null, msgSupplier, (Throwable) null); + public void warn(final MessageSupplier messageSupplier) { + logIfEnabled(FQCN, Level.WARN, null, messageSupplier, (Throwable) null); } @Override - public void warn(final MessageSupplier msgSupplier, final Throwable t) { - logIfEnabled(FQCN, Level.WARN, null, msgSupplier, t); + public void warn(final MessageSupplier messageSupplier, final Throwable throwable) { + logIfEnabled(FQCN, Level.WARN, null, messageSupplier, throwable); } @Override @@ -3714,7 +3753,7 @@ public LogBuilder atLevel(final Level level) { * * @since 2.20.0 */ - protected LogBuilder getLogBuilder(Level level) { + protected LogBuilder getLogBuilder(final Level level) { DefaultLogBuilder builder = recycler.acquire(); return builder.reset(this, level); } diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/spi/GarbageFreeSortedArrayThreadContextMap.java b/log4j-api/src/main/java/org/apache/logging/log4j/spi/GarbageFreeSortedArrayThreadContextMap.java index 542962dd484..5fe721ee39b 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/spi/GarbageFreeSortedArrayThreadContextMap.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/spi/GarbageFreeSortedArrayThreadContextMap.java @@ -155,7 +155,7 @@ public String get(final String key) { @Override public V getValue(final String key) { final StringMap map = localMap.get(); - return map == null ? null : map.getValue(key); + return map == null ? null : map.getValue(key); } @Override diff --git a/log4j-perf-test/src/main/java/org/apache/logging/log4j/message/ParameterFormatterBenchmark.java b/log4j-perf-test/src/main/java/org/apache/logging/log4j/message/ParameterFormatterBenchmark.java index 8ec3f10ef11..b4d35002f53 100644 --- a/log4j-perf-test/src/main/java/org/apache/logging/log4j/message/ParameterFormatterBenchmark.java +++ b/log4j-perf-test/src/main/java/org/apache/logging/log4j/message/ParameterFormatterBenchmark.java @@ -46,153 +46,48 @@ public class ParameterFormatterBenchmark { @State(Scope.Thread) public static class ThreadState { - StringBuilder buffer = new StringBuilder(2048); - int[] indices = new int[255]; - char[] copy = new char[4096]; - } - @Benchmark - @BenchmarkMode(Mode.SampleTime) - @OutputTimeUnit(TimeUnit.NANOSECONDS) - public int latency3ParamsV3(final ThreadState state) { - state.buffer.setLength(0); - final String STR = "p1={}, p2={}, p3={}"; - final int length = STR.length(); - STR.getChars(0, length, state.copy, 0); - final int count = ParameterFormatter.countArgumentPlaceholders3(state.copy, length, state.indices); - ParameterFormatter.formatMessage3(state.buffer, state.copy, length, ARGS, count, state.indices); - return state.buffer.length(); - } + private final MessagePatternAnalysis analysis = new MessagePatternAnalysis(); - @Benchmark - @BenchmarkMode(Mode.SampleTime) - @OutputTimeUnit(TimeUnit.NANOSECONDS) - public int latency5ParamsV3(final ThreadState state) { - state.buffer.setLength(0); - final String STR = "p1={}, p2={}, p3={}, p4={}, p5={}"; - final int length = STR.length(); - STR.getChars(0, length, state.copy, 0); - final int count = ParameterFormatter.countArgumentPlaceholders3(state.copy, length, state.indices); - ParameterFormatter.formatMessage3(state.buffer, state.copy, length, ARGS, count, state.indices); - return state.buffer.length(); - } + private final StringBuilder buffer = new StringBuilder(2048); - @Benchmark - @BenchmarkMode(Mode.SampleTime) - @OutputTimeUnit(TimeUnit.NANOSECONDS) - public int latency7ParamsV3(final ThreadState state) { - state.buffer.setLength(0); - final String STR = "p1={}, p2={}, p3={}, p4={}, p5={}, p6={}, p7={}"; - final int length = STR.length(); - STR.getChars(0, length, state.copy, 0); - final int count = ParameterFormatter.countArgumentPlaceholders3(state.copy, length, state.indices); - ParameterFormatter.formatMessage3(state.buffer, state.copy, length, ARGS, count, state.indices); - return state.buffer.length(); - } - - @Benchmark - @BenchmarkMode(Mode.SampleTime) - @OutputTimeUnit(TimeUnit.NANOSECONDS) - public int latency9ParamsV3(final ThreadState state) { - state.buffer.setLength(0); - final String STR = "p1={}, p2={}, p3={}, p4={}, p5={}, p6={}, p7={}, p8={}, p9={}"; - final int length = STR.length(); - STR.getChars(0, length, state.copy, 0); - final int count = ParameterFormatter.countArgumentPlaceholders3(state.copy, length, state.indices); - ParameterFormatter.formatMessage3(state.buffer, state.copy, length, ARGS, count, state.indices); - return state.buffer.length(); - } - - @Benchmark - @BenchmarkMode(Mode.SampleTime) - @OutputTimeUnit(TimeUnit.NANOSECONDS) - public int latency3ParamsV2(final ThreadState state) { - state.buffer.setLength(0); - final int count = ParameterFormatter.countArgumentPlaceholders2("p1={}, p2={}, p3={}", state.indices); - ParameterFormatter.formatMessage2(state.buffer, "p1={}, p2={}, p3={}", ARGS, count, state.indices); - return state.buffer.length(); - } - - @Benchmark - @BenchmarkMode(Mode.SampleTime) - @OutputTimeUnit(TimeUnit.NANOSECONDS) - public int latency5ParamsV2(final ThreadState state) { - state.buffer.setLength(0); - final int count = - ParameterFormatter.countArgumentPlaceholders2("p1={}, p2={}, p3={}, p4={}, p5={}", state.indices); - ParameterFormatter.formatMessage2( - state.buffer, "p1={}, p2={}, p3={}, p4={}, p5={}", ARGS, count, state.indices); - return state.buffer.length(); - } - - @Benchmark - @BenchmarkMode(Mode.SampleTime) - @OutputTimeUnit(TimeUnit.NANOSECONDS) - public int latency7ParamsV2(final ThreadState state) { - state.buffer.setLength(0); - final int count = ParameterFormatter.countArgumentPlaceholders2( - "p1={}, p2={}, p3={}, p4={}, p5={}, p6={}, p7={}", state.indices); - ParameterFormatter.formatMessage2( - state.buffer, "p1={}, p2={}, p3={}, p4={}, p5={}, p6={}, p7={}", ARGS, count, state.indices); - return state.buffer.length(); - } - - @Benchmark - @BenchmarkMode(Mode.SampleTime) - @OutputTimeUnit(TimeUnit.NANOSECONDS) - public int latency9ParamsV2(final ThreadState state) { - state.buffer.setLength(0); - final int count = ParameterFormatter.countArgumentPlaceholders2( - "p1={}, p2={}, p3={}, p4={}, p5={}, p6={}, p7={}, p8={}, p9={}", state.indices); - ParameterFormatter.formatMessage2( - state.buffer, - "p1={}, p2={}, p3={}, p4={}, p5={}, p6={}, p7={}, p8={}, p9={}", - ARGS, - count, - state.indices); - return state.buffer.length(); + public ThreadState() { + analysis.placeholderCharIndices = new int[10]; + } } @Benchmark @BenchmarkMode(Mode.SampleTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) public int latency3Params(final ThreadState state) { - state.buffer.setLength(0); - final int count = ParameterFormatter.countArgumentPlaceholders("p1={}, p2={}, p3={}"); - ParameterFormatter.formatMessage(state.buffer, "p1={}, p2={}, p3={}", ARGS, count); - return state.buffer.length(); + return latencyParams(state, "p1={}, p2={}, p3={}"); } @Benchmark @BenchmarkMode(Mode.SampleTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) public int latency5Params(final ThreadState state) { - state.buffer.setLength(0); - final int count = ParameterFormatter.countArgumentPlaceholders("p1={}, p2={}, p3={}, p4={}, p5={}"); - ParameterFormatter.formatMessage(state.buffer, "p1={}, p2={}, p3={}, p4={}, p5={}", ARGS, count); - return state.buffer.length(); + return latencyParams(state, "p1={}, p2={}, p3={}, p4={}, p5={}"); } @Benchmark @BenchmarkMode(Mode.SampleTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) public int latency7Params(final ThreadState state) { - state.buffer.setLength(0); - final int count = - ParameterFormatter.countArgumentPlaceholders("p1={}, p2={}, p3={}, p4={}, p5={}, p6={}, p7={}"); - ParameterFormatter.formatMessage(state.buffer, "p1={}, p2={}, p3={}, p4={}, p5={}, p6={}, p7={}", ARGS, count); - return state.buffer.length(); + return latencyParams(state, "p1={}, p2={}, p3={}, p4={}, p5={}, p6={}, p7={}"); } @Benchmark @BenchmarkMode(Mode.SampleTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) public int latency9Params(final ThreadState state) { + return latencyParams(state, "p1={}, p2={}, p3={}, p4={}, p5={}, p6={}, p7={}, p8={}, p9={}"); + } + + private static int latencyParams(final ThreadState state, final String pattern) { state.buffer.setLength(0); - final int count = ParameterFormatter.countArgumentPlaceholders( - "p1={}, p2={}, p3={}, p4={}, p5={}, p6={}, p7={}, p8={}, p9={}"); - ParameterFormatter.formatMessage( - state.buffer, "p1={}, p2={}, p3={}, p4={}, p5={}, p6={}, p7={}, p8={}, p9={}", ARGS, count); + ParameterFormatter.analyzePattern(pattern, -1, state.analysis); + ParameterFormatter.formatMessage(state.buffer, pattern, ARGS, state.analysis.placeholderCount, state.analysis); return state.buffer.length(); } } diff --git a/src/changelog/.3.x.x/1223_change_formatted_message_heuristic.xml b/src/changelog/.3.x.x/1223_change_formatted_message_heuristic.xml new file mode 100644 index 00000000000..4aedfc4c24c --- /dev/null +++ b/src/changelog/.3.x.x/1223_change_formatted_message_heuristic.xml @@ -0,0 +1,11 @@ + + + + + Change the order of evaluation of `FormattedMessage` formatters. + Messages are evaluated using `java.util.Format` only if they don't comply to the `java.text.MessageFormat` or `ParameterizedMessage` format. + + diff --git a/src/changelog/.3.x.x/1626_parameter_format_rewrite.xml b/src/changelog/.3.x.x/1626_parameter_format_rewrite.xml new file mode 100644 index 00000000000..da776840520 --- /dev/null +++ b/src/changelog/.3.x.x/1626_parameter_format_rewrite.xml @@ -0,0 +1,26 @@ + + + + + + + Rewrote message parameter formatter with improved escape handling +