Skip to content

Conversation

ppkarwasz
Copy link
Contributor

Historically, throwable pattern converters (%ex, %xEx, etc.) behaved in a context-sensitive way:

  • If the preceding formatter’s expansion did not end with whitespace, the converter automatically inserted a space before rendering the exception.

In version 2.25.0, this was changed to insert a newline instead of a space, but the behavior was still dependent on surrounding context.

What this change does

This PR removes the context-dependent behavior altogether and makes %ex expansion fully predictable, while remaining backward-compatible:

  • When %ex is added implicitly because alwaysWriteExceptions=true:

    • If the pattern already ends with %n, a plain %ex is appended.
    • Otherwise, %notEmpty{%n%ex} is appended. This ensures exceptions are always clearly separated from the main log message by a newline, without adding extra characters when no exception is present.
  • When %ex is explicitly included in the pattern by the user:

    • Its expansion is rendered exactly as written in the pattern.
    • It will never prepend a newline on its own.

Why

  • Eliminates confusing context-sensitive behavior.
  • Makes output consistent and predictable.
  • Preserves legacy expectations by only modifying implicitly added %ex.

Closes #3873

Historically, throwable pattern converters (`%ex`, `%xEx`, etc.) behaved in a context-sensitive way: * If the **preceding formatter’s expansion** did not end with whitespace, the converter automatically inserted a space before rendering the exception. In version `2.25.0`, this was changed to insert a **newline** instead of a space, but the behavior was still dependent on surrounding context. #### What this change does This PR removes the context-dependent behavior altogether and makes `%ex` expansion fully predictable, while remaining backward-compatible: * When `%ex` is **added implicitly** because `alwaysWriteExceptions=true`: * If the pattern already ends with `%n`, a plain `%ex` is appended. * Otherwise, `%notEmpty{%n%ex}` is appended. This ensures exceptions are always clearly separated from the main log message by a newline, without adding extra characters when no exception is present. * When `%ex` is **explicitly included** in the pattern by the user: * Its expansion is rendered exactly as written in the pattern. * It will **never** prepend a newline on its own. #### Why * Eliminates confusing context-sensitive behavior. * Makes output consistent and predictable. * Preserves legacy expectations by only modifying implicitly added `%ex`. Closes #3873
@ppkarwasz ppkarwasz added this to the 2.25.2 milestone Sep 8, 2025
@ppkarwasz ppkarwasz merged commit c41feed into 2.x Sep 12, 2025
11 checks passed
@github-project-automation github-project-automation bot moved this from To triage to Done in Log4j bug tracker Sep 12, 2025
@ppkarwasz ppkarwasz deleted the fix/2.x/3873-throwable-converter branch September 12, 2025 11:00
@vy vy added the layouts Affects one or more Layout plugins label Sep 18, 2025
vy added a commit that referenced this pull request Sep 18, 2025
Historically, throwable pattern converters (`%ex`, `%xEx`, etc.) behaved in a context-sensitive way: * If the **preceding formatter’s expansion** did not end with whitespace, the converter automatically inserted a space before rendering the exception. In version `2.25.0`, this was changed to insert a **newline** instead of a space, but the behavior was still dependent on surrounding context. #### What this change does This PR removes the context-dependent behavior altogether and makes `%ex` expansion fully predictable, while remaining backward-compatible: * When `%ex` is **added implicitly** because `alwaysWriteExceptions=true`: * If the pattern already ends with `%n`, a plain `%ex` is appended. * Otherwise, `%notEmpty{%n%ex}` is appended. This ensures exceptions are always clearly separated from the main log message by a newline, without adding extra characters when no exception is present. * When `%ex` is **explicitly included** in the pattern by the user: * Its expansion is rendered exactly as written in the pattern. * It will **never** prepend a newline on its own. #### Why * Eliminates confusing context-sensitive behavior. * Makes output consistent and predictable. * Preserves legacy expectations by only modifying implicitly added `%ex`. Closes #3873 Co-authored-by: Volkan Yazıcı <volkan@yazi.ci>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

layouts Affects one or more Layout plugins

2 participants