Skip to content

Regression: StatusLogger has switched from stderr to stdout by default #3665

@rschmitt

Description

@rschmitt

Description

StatusLogger messages used to be written to stderr by default. Since 2.23.0, they are writing to stdout. This is a significant regression. As a rule, stderr is for humans, and stdout is for programs. The pipe operator redirects stdout by default, and a CLI utility can have its output corrupted because Log4j2 emitted a status message to stdout. For example, consider a program that emits JSON and has its output piped to jq: after upgrading to Log4j 2.23.0 or later, this program will cease to work correctly unless the StatusLogger is reconfigured to not emit anything, or is explicitly configured to write to stderr.

This regression can be fixed by calling the two-parameter constructor variant of StatusConsoleListener from StatusLogger:

diff --git log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java
index 6aec303cba..699dc66c8a 100644
--- log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java
+++ log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java
@@ -531,7 +531,7 @@ public class StatusLogger extends AbstractLogger {
                 StatusLogger.class.getSimpleName(),
                 ParameterizedNoReferenceMessageFactory.INSTANCE,
                 Config.getInstance(),
-                new StatusConsoleListener(requireNonNull(Config.getInstance().fallbackListenerLevel)));
+                new StatusConsoleListener(requireNonNull(Config.getInstance().fallbackListenerLevel), System.err));
     }

     /**

Logs & Reproduction

import org.apache.logging.log4j.LogManager;

public class LogTest {
    public static void main(String[] args) {
        LogManager.getLogger(LogTest.class);
        System.out.println("{\"this is\":\"stdout\"}");
        System.err.println("This is stderr");
    }
}
[0] ~ # javac -cp Downloads/log4j-api-2.24.3.jar LogTest.java
[0] ~ # for i in Downloads/log4j-api-*.jar; echo $i && (java -cp .:$i LogTest | jq . ; echo "")
Downloads/log4j-api-2.20.0.jar
ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console...
This is stderr
{
  "this is": "stdout"
}

Downloads/log4j-api-2.21.0.jar
ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console...
This is stderr
{
  "this is": "stdout"
}

Downloads/log4j-api-2.21.1.jar
ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console...
This is stderr
{
  "this is": "stdout"
}

Downloads/log4j-api-2.22.0.jar
ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console...
This is stderr
{
  "this is": "stdout"
}

Downloads/log4j-api-2.22.1.jar
ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console...
This is stderr
{
  "this is": "stdout"
}

Downloads/log4j-api-2.23.0.jar
jq: parse error: Invalid numeric literal at line 1, column 14
This is stderr

Downloads/log4j-api-2.23.1.jar
jq: parse error: Invalid numeric literal at line 1, column 14
This is stderr

Downloads/log4j-api-2.24.0.jar
jq: parse error: Invalid numeric literal at line 1, column 14
This is stderr

Downloads/log4j-api-2.24.1.jar
jq: parse error: Invalid numeric literal at line 1, column 14
This is stderr

Downloads/log4j-api-2.24.3.jar
jq: parse error: Invalid numeric literal at line 1, column 14
This is stderr

Metadata

Metadata

Assignees

No one assigned

    Labels

    apiAffects the public APIbugIncorrect, unexpected, or unintended behavior of existing code

    Type

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      pFad - Phonifier reborn

      Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

      Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


      Alternative Proxies:

      Alternative Proxy

      pFad Proxy

      pFad v3 Proxy

      pFad v4 Proxy