Why does java.util.logging.Logger print to stderr?
Asked Answered
D

5

20

I've got a simple setup to log a message: Java 8 Update 65 and Eclipse Mars:

import java.util.logging.Logger;

public class Example {

    private final static Logger LOGGER = Logger.getLogger(Example.class.getName());

    public static void main(String[] args) {
        LOGGER.info("Test");
    }

}

I would expect to get an output on the stdout, just like using System.out.println();, but instead it gets printed out on the stderr, which results in a red font on the eclipse console:

enter image description here

I know that I can change this behavior by writing a custom Handler, but I wish to know why the default output appears on the stderr instead of stdout?

A logger should use stdout for fine+info and use stderr for severe level.

Devanagari answered 8/12, 2015 at 12:34 Comment(0)
E
2

By default, the logger outputs log records of level INFO and above (i.e., INFO, WARNING and SEVERE) to standard error stream (System.err).

Source: www3.ntu.edu.sg/home/ehchua/programming/java/JavaLogging.html

Edirne answered 8/12, 2015 at 12:42 Comment(5)
Do you have a source or proof for this statement?Devanagari
Sorry, I should have provided it in the comment :) www3.ntu.edu.sg/home/ehchua/programming/java/JavaLogging.htmlMacerate
That the logger does that is already known by OP, the question is: "why".Sclerophyll
@Sclerophyll Yeah thats another question too, but at least I know this was done on purpose.Devanagari
Found this one as well: ConsoleHandler: A simple handler for writing formatted records to System.err Source:docs.oracle.com/javase/7/docs/technotes/guides/logging/… (chapter 1.5)Devanagari
J
10

The java.util.logging API was developed under JSR 47: Logging API Specification. According to the change log in the "Proposed Final Draft" the ConsoleHandler always used System.err. The JCP page also lists the original authors of the API and I think only those names truly know the answer to your question.

That said, I think the origin comes from System.err API docs.

Typically this stream corresponds to display output or another output destination specified by the host environment or user. By convention, this output stream is used to display error messages or other information that should come to the immediate attention of a user even if the principal output stream, the value of the variable out, has been redirected to a file or other destination that is typically not continuously monitored.

Opposed to System.out:

The "standard" output stream. This stream is already open and ready to accept output data. Typically this stream corresponds to display output or another output destination specified by the host environment or user.

Logging maps to diagnostics and not raw data. It is important to separate data from diagnostic error information especially when piping processes together as the downstream consumers are only ready to accept data information and not error messages. See Confused about stdin, stdout and stderr? for more detailed information.

Juxon answered 8/12, 2015 at 14:56 Comment(0)
G
4

You can create and extended ConsoleHandler to set the out to System.out instead of System.err

Logger logger = Logger.getLoger("your_logger_name");
logger.setUseParentHandler(false);
logger.addHandler(new ConsoleHandler() {
    {setOutputStream(System.out);}
});

Now all message on this logger will appear in the System.out console.

Galagalactagogue answered 9/7, 2019 at 14:23 Comment(2)
Don't do this, this will close System.err. (Have a look at setOutPutStream). A better way would be: ``` final class MigrationsCliConsoleHandler extends StreamHandler { MigrationsCliConsoleHandler() { setOutputStream(System.out); } @Override public void close() { flush(); } } ```Saber
The OP was aware of this and noted it in the original question. There is a whole different question dedicated to topic you are trying to answer.Juxon
W
3

It is well documented. By default, loggers publish to their parent's handlers, recursively up to the tree, until the other handler has been specified. You can loop over the parent's handlers and see that the default handler of the parent's logger is ConsoleHandler which uses System.err to publish log records.

public class Main {
    public static void main(String[] args) {
        Handler[] handlers = Logger.getLogger(Main.class.getName()).getParent().getHandlers();
        for (Handler handler : handlers) {
            System.out.println(handler.getClass().getName());
        }
    }
}
Washhouse answered 8/12, 2015 at 13:27 Comment(0)
E
2

By default, the logger outputs log records of level INFO and above (i.e., INFO, WARNING and SEVERE) to standard error stream (System.err).

Source: www3.ntu.edu.sg/home/ehchua/programming/java/JavaLogging.html

Edirne answered 8/12, 2015 at 12:42 Comment(5)
Do you have a source or proof for this statement?Devanagari
Sorry, I should have provided it in the comment :) www3.ntu.edu.sg/home/ehchua/programming/java/JavaLogging.htmlMacerate
That the logger does that is already known by OP, the question is: "why".Sclerophyll
@Sclerophyll Yeah thats another question too, but at least I know this was done on purpose.Devanagari
Found this one as well: ConsoleHandler: A simple handler for writing formatted records to System.err Source:docs.oracle.com/javase/7/docs/technotes/guides/logging/… (chapter 1.5)Devanagari
E
2

the reason they use stderr is because this stream "is used for error messages and diagnostics issued by the program" (source: https://www.gnu.org/software/libc/manual/html_node/Standard-Streams.html).

Electrochemistry answered 9/3, 2019 at 9:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.