This is an automated email from the ASF dual-hosted git repository. pkarwasz pushed a commit to branch 2.x in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit 8209dfc1d645ef81e07253c03281fdcfc933d50c Author: PanLongfei <[email protected]> AuthorDate: Sat Mar 23 20:21:33 2024 +0800 Fix issue 2380: Log messages with sufficient parameters include exception should not give waring log --- .../log4j/message/ParameterizedMessageTest.java | 57 +++++++++++++--------- .../logging/log4j/message/ParameterFormatter.java | 19 +++++--- 2 files changed, 45 insertions(+), 31 deletions(-) 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 3f6ba36da0..4bd5df91be 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 @@ -185,27 +185,44 @@ class ParameterizedMessageTest { assertThat(actual.getFormattedMessage()).isEqualTo(expected.getFormattedMessage()); } - @Test - void formatToWithMoreArgsButNoWarn() { - final String pattern = "no warn {} {}"; - final String expectedMessage = "no warn a b"; - final Object[] args = {"a", "b", new RuntimeException()}; + /** + * In this test cases, constructed the following scenarios: <br> + * <p> + * 1. The arguments contains an exception, and the count of placeholder is equal to arguments include exception. <br> + * 2. The arguments contains an exception, and the count of placeholder is equal to arguments except exception.<br> + * All of these should not logged in status logger. + * </p> + * + * @return Streams + */ + static Stream<Object[]> testCasesWithExceptionArgsButNoWarn() { + return Stream.of( + new Object[] { + "with exception {} {}", + new Object[] {"a", new RuntimeException()}, + "with exception a java.lang.RuntimeException" + }, + new Object[] { + "with exception {} {}", new Object[] {"a", "b", new RuntimeException()}, "with exception a b" + }); + } + + @ParameterizedTest + @MethodSource("testCasesWithExceptionArgsButNoWarn") + void formatToWithExceptionButNoWarn(final String pattern, final Object[] args, final String expected) { final ParameterizedMessage message = new ParameterizedMessage(pattern, args); final StringBuilder buffer = new StringBuilder(); message.formatTo(buffer); - assertThat(buffer.toString()).isEqualTo(expectedMessage); - assertThat(message.getThrowable()).isInstanceOf(RuntimeException.class); + assertThat(buffer.toString()).isEqualTo(expected); final List<StatusData> statusDataList = statusListener.getStatusData().collect(Collectors.toList()); assertThat(statusDataList).hasSize(0); } - @Test - void formatWithMoreArgsButNoWarn() { - final String pattern = "no warn {} {}"; - final String expectedMessage = "no warn a b"; - final Object[] args = {"a", "b", new RuntimeException()}; + @ParameterizedTest + @MethodSource("testCasesWithExceptionArgsButNoWarn") + void formatWithExceptionButNoWarn(final String pattern, final Object[] args, final String expected) { final String message = ParameterizedMessage.format(pattern, args); - assertThat(message).isEqualTo(expectedMessage); + assertThat(message).isEqualTo(expected); final List<StatusData> statusDataList = statusListener.getStatusData().collect(Collectors.toList()); assertThat(statusDataList).hasSize(0); } @@ -228,12 +245,6 @@ class ParameterizedMessageTest { new Object[] {"more {} {} {}", 3, new Object[] {"a"}, "more a {} {}"}, new Object[] {"less {}", 1, new Object[] {"a", "b"}, "less a"}, new Object[] {"less {} {}", 2, new Object[] {"a", "b", "c"}, "less a b"}, - new Object[] { - "more throwable {} {}", - 2, - new Object[] {"a", new RuntimeException()}, - "more throwable a java.lang.RuntimeException" - }, new Object[] { "more throwable {} {} {}", 3, @@ -247,8 +258,8 @@ class ParameterizedMessageTest { @ParameterizedTest @MethodSource("testCasesForInsufficientFormatArgs") - void formatTo_should_warn_on_insufficient_args( - final String pattern, final int placeholderCount, Object[] args, final String expected) { + void formatToShouldWarnOnInsufficientArgs( + final String pattern, final int placeholderCount, final Object[] args, final String expected) { final int argCount = args == null ? 0 : args.length; verifyFormattingFailureOnInsufficientArgs(pattern, placeholderCount, argCount, expected, () -> { final ParameterizedMessage message = new ParameterizedMessage(pattern, args); @@ -260,8 +271,8 @@ class ParameterizedMessageTest { @ParameterizedTest @MethodSource("testCasesForInsufficientFormatArgs") - void format_should_warn_on_insufficient_args( - final String pattern, final int placeholderCount, Object[] args, final String expected) { + void formatShouldWarnOnInsufficientArgs( + final String pattern, final int placeholderCount, final Object[] args, final String expected) { final int argCount = args == null ? 0 : args.length; verifyFormattingFailureOnInsufficientArgs( pattern, placeholderCount, argCount, expected, () -> ParameterizedMessage.format(pattern, args)); 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 9964d118b7..cdc0e1de69 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 @@ -244,14 +244,17 @@ final class ParameterFormatter { return; } - // check if there are insufficient arguments that do not include Throwable arg - final int realArgCount = args.length; - final int noThrowableArgCount = realArgCount - ((args[realArgCount - 1] instanceof Throwable) ? 1 : 0); - if (analysis.placeholderCount != noThrowableArgCount) { - final String message = String.format( - "found %d argument placeholders, but provided %d for pattern `%s`", - analysis.placeholderCount, realArgCount, pattern); - STATUS_LOGGER.warn(message); + // #2380: check if the count of placeholder is not equal to the count of arguments + if (analysis.placeholderCount != argCount) { + final int realArgCount = args.length; + final int noThrowableArgCount = realArgCount - ((args[realArgCount - 1] instanceof Throwable) ? 1 : 0); + if (analysis.placeholderCount != noThrowableArgCount) { + STATUS_LOGGER.warn( + "found {} argument placeholders, but provided {} for pattern `{}`", + analysis.placeholderCount, + Math.min(realArgCount, argCount), + pattern); + } } // Fast-path for patterns containing no escapes
