This is an automated email from the ASF dual-hosted git repository.

vy pushed a commit to branch 2.x
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git


The following commit(s) were added to refs/heads/2.x by this push:
     new d46918c9e3 Take `Throwable#toString()` into account while rendering 
stack traces in Pattern Layout (#4033)
d46918c9e3 is described below

commit d46918c9e350ba64f1c4af25aea3758c36453b33
Author: JongminChung <[email protected]>
AuthorDate: Thu Mar 5 22:51:59 2026 +0900

    Take `Throwable#toString()` into account while rendering stack traces in 
Pattern Layout (#4033)
    
    Signed-off-by: Jongmin Chung <[email protected]>
    Co-authored-by: Volkan Yazıcı <[email protected]>
---
 .../log4j/core/EventParameterMemoryLeakTest.java   |  7 ++--
 .../pattern/ThrowablePatternConverterTest.java     | 37 ++++++++++++++++++++--
 .../core/pattern/ThrowableStackTraceRenderer.java  |  7 +---
 .../.2.x.x/4033_fix_custom_throwable_to_sting.xml  | 13 ++++++++
 4 files changed, 51 insertions(+), 13 deletions(-)

diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/EventParameterMemoryLeakTest.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/EventParameterMemoryLeakTest.java
index ff08d2b2cf..d8b1d90cf2 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/EventParameterMemoryLeakTest.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/EventParameterMemoryLeakTest.java
@@ -59,11 +59,8 @@ class EventParameterMemoryLeakTest {
                 assertThat(messages).hasSize(4);
                 assertThat(messages.get(0)).isEqualTo("Message with parameter 
%s", parameter.value);
                 assertThat(messages.get(1)).isEqualTo(parameter.value);
-                assertThat(messages.get(2))
-                        .startsWith(String.format("test%n%s: %s", 
ObjectThrowable.class.getName(), parameter.value));
-                assertThat(messages.get(3))
-                        .startsWith(
-                                String.format("test hello%n%s: %s", 
ObjectThrowable.class.getName(), parameter.value));
+                
assertThat(messages.get(2)).startsWith(String.format("test%n%s", new 
ObjectThrowable(parameter)));
+                assertThat(messages.get(3)).startsWith(String.format("test 
hello%n%s", new ObjectThrowable(parameter)));
 
                 // Return the GC subject
                 return parameter;
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverterTest.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverterTest.java
index ea9294e58a..0ce38d0323 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverterTest.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverterTest.java
@@ -79,6 +79,23 @@ public class ThrowablePatternConverterTest {
         }
     }
 
+    /**
+     * Test exception whose {@link #toString()} is intentionally overridden to 
return a fixed value.
+     */
+    private static final class ToStringOverridingException extends 
RuntimeException {
+
+        private static final ToStringOverridingException INSTANCE = new 
ToStringOverridingException();
+
+        private ToStringOverridingException() {
+            super(EXCEPTION);
+        }
+
+        @Override
+        public String toString() {
+            return "foo";
+        }
+    }
+
     static Stream<SeparatorTestCase> separatorTestCases() {
         final String level = LEVEL.toString();
         return Stream.of(
@@ -214,6 +231,14 @@ public class ThrowablePatternConverterTest {
             assertThat(actualStackTrace).as("pattern=`%s`", 
effectivePattern).isEqualTo(expectedStackTrace);
         }
 
+        @Test
+        void full_output_should_use_custom_toString() {
+            final Throwable exception = ToStringOverridingException.INSTANCE;
+            final String expectedStackTrace = 
renderStackTraceUsingJava(exception);
+            final String actualStackTrace = convert(patternPrefix, exception);
+            assertThat(actualStackTrace).isEqualTo(expectedStackTrace);
+        }
+
         // This test does not provide `separator` and `suffix` options, since 
the reference output will be obtained from
         // `Throwable#printStackTrace()`, which doesn't take these into 
account.
         @ParameterizedTest
@@ -252,10 +277,14 @@ public class ThrowablePatternConverterTest {
         }
 
         private String renderStackTraceUsingJava() {
+            return renderStackTraceUsingJava(EXCEPTION);
+        }
+
+        private String renderStackTraceUsingJava(final Throwable throwable) {
             final Charset charset = StandardCharsets.UTF_8;
             try (final ByteArrayOutputStream outputStream = new 
ByteArrayOutputStream();
                     final PrintStream printStream = new 
PrintStream(outputStream, false, charset.name())) {
-                EXCEPTION.printStackTrace(printStream);
+                throwable.printStackTrace(printStream);
                 printStream.flush();
                 return new String(outputStream.toByteArray(), charset);
             } catch (final Exception error) {
@@ -545,9 +574,13 @@ public class ThrowablePatternConverterTest {
     }
 
     static String convert(final String pattern) {
+        return convert(pattern, EXCEPTION);
+    }
+
+    private static String convert(final String pattern, final Throwable 
throwable) {
         final List<PatternFormatter> patternFormatters = 
PATTERN_PARSER.parse(pattern, false, true, true);
         final LogEvent logEvent =
-                
Log4jLogEvent.newBuilder().setThrown(EXCEPTION).setLevel(LEVEL).build();
+                
Log4jLogEvent.newBuilder().setThrown(throwable).setLevel(LEVEL).build();
         final StringBuilder buffer = new StringBuilder();
         for (final PatternFormatter patternFormatter : patternFormatters) {
             patternFormatter.format(logEvent, buffer);
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowableStackTraceRenderer.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowableStackTraceRenderer.java
index 885d7de36e..4d21021321 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowableStackTraceRenderer.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowableStackTraceRenderer.java
@@ -138,12 +138,7 @@ class ThrowableStackTraceRenderer<C extends 
ThrowableStackTraceRenderer.Context>
     }
 
     static void renderThrowableMessage(final StringBuilder buffer, final 
Throwable throwable) {
-        final String message = throwable.getLocalizedMessage();
-        buffer.append(throwable.getClass().getName());
-        if (message != null) {
-            buffer.append(": ");
-            buffer.append(message);
-        }
+        buffer.append(throwable);
     }
 
     final void renderStackTraceElements(
diff --git a/src/changelog/.2.x.x/4033_fix_custom_throwable_to_sting.xml 
b/src/changelog/.2.x.x/4033_fix_custom_throwable_to_sting.xml
new file mode 100644
index 0000000000..761380f81c
--- /dev/null
+++ b/src/changelog/.2.x.x/4033_fix_custom_throwable_to_sting.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entry xmlns="https://logging.apache.org/xml/ns";
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+       xsi:schemaLocation="
+           https://logging.apache.org/xml/ns
+           https://logging.apache.org/xml/ns/log4j-changelog-0.xsd";
+       type="changed">
+    <issue id="3623" 
link="https://github.com/apache/logging-log4j2/issues/3623"/>
+    <issue id="4033" 
link="https://github.com/apache/logging-log4j2/pull/4033"/>
+    <description format="asciidoc">
+        Take `Throwable#toString()` into account while rendering stack traces 
in Pattern Layout.
+    </description>
+</entry>

Reply via email to