Skip to content

Commit b550403

Browse files
committed
StatusLogger: Write to stderr by default
`StatusLogger` messages used to be written to stderr by default. Since 2.23.0, they are being written 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`. A simple test case has been added that captures stdout/stderr and ensures that the default `StatusLogger` is not emitting anything to stdout. Fixes #3665.
1 parent c84ff4a commit b550403

File tree

3 files changed

+67
-1
lines changed

3 files changed

+67
-1
lines changed
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to you under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.logging.log4j.status;
18+
19+
import static org.assertj.core.api.Assertions.assertThat;
20+
import static org.junit.jupiter.api.Assertions.assertEquals;
21+
22+
import java.io.ByteArrayOutputStream;
23+
import java.io.PrintStream;
24+
import org.junit.jupiter.api.AfterEach;
25+
import org.junit.jupiter.api.BeforeEach;
26+
import org.junit.jupiter.api.Test;
27+
28+
class StatusLoggerTest {
29+
private final PrintStream origOut = System.out;
30+
private final PrintStream origErr = System.err;
31+
private ByteArrayOutputStream outBuf;
32+
private ByteArrayOutputStream errBuf;
33+
34+
@BeforeEach
35+
void setupStreams() {
36+
outBuf = new ByteArrayOutputStream();
37+
errBuf = new ByteArrayOutputStream();
38+
System.setOut(new PrintStream(outBuf));
39+
System.setErr(new PrintStream(errBuf));
40+
}
41+
42+
@AfterEach
43+
void resetStreams() {
44+
System.setOut(origOut);
45+
System.setErr(origErr);
46+
}
47+
48+
@Test
49+
void status_logger_writes_to_stderr_by_default() {
50+
StatusLogger statusLogger = new StatusLogger();
51+
statusLogger.error("Test message");
52+
53+
assertEquals("", outBuf.toString());
54+
assertThat(errBuf.toString()).contains("Test message");
55+
}
56+
}

log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,7 @@ private static final class InstanceHolder {
531531
StatusLogger.class.getSimpleName(),
532532
ParameterizedNoReferenceMessageFactory.INSTANCE,
533533
Config.getInstance(),
534-
new StatusConsoleListener(requireNonNull(Config.getInstance().fallbackListenerLevel)));
534+
new StatusConsoleListener(requireNonNull(Config.getInstance().fallbackListenerLevel), System.err));
535535
}
536536

537537
/**
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<entry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xmlns="https://logging.apache.org/xml/ns"
4+
xsi:schemaLocation="https://logging.apache.org/xml/ns https://logging.apache.org/xml/ns/log4j-changelog-0.xsd"
5+
type="fixed">
6+
<issue id="3665" link="https://github.com/apache/logging-log4j2/issues/3665"/>
7+
<description format="asciidoc">
8+
StatusLogger now writes to standard error by default. This fixes a regression introduced in 2.23.0.
9+
</description>
10+
</entry>

0 commit comments

Comments
 (0)