Do not use System.out.println in server side code

JavaLoggingBackend

Java Problem Overview


I heard that using System.out.println for logging purposes is a very bad practice and this may force the server to fail.

I don't use this approach but I am very interested in knowing why System.out.println could make so trash things when used in backend code.

Java Solutions


Solution 1 - Java

System.out.println is an IO-operation and therefor is time consuming. The Problem with using it in your code is, that your program will wait until the println has finished. This may not be a problem with small sites but as soon as you get load or many iterations, you'll feel the pain.

The better approach is to use a logging framework. They use a message queue and write only if no other output is going on.

And another benefit is that you can configure separate log files for different purposes. Something your Ops team will love you for.

Read more here:

Solution 2 - Java

Check out Adam Biens article in the Java Magazine edition November/Dezember about stress testing JEE6 applications - it's free online, you only have to subscribe to it.

On page 43 he shows, that a server applications which manages to handle 1700 transactions per second falls down to only 800 when inserting a single System.out.println with fix String in each.

Solution 3 - Java

It's a bad practice because when your application goes in Production, you can't separate application logs from server logs.

Prod teams want that you separate logs produced by your application from the ones from the app server (tomcat, websphere, etc...) : they want to be able to monitor the app server diffrently from the application itself.

Moreover, using System.out, you can't define the log level : in Production, you don't want to print debug information.

Solution 4 - Java

It is considered to be bad because System.out.println(); eats more cpu and thus output comes slow means hurts the performance. (Actually every I/O operation eats cpu).

Solution 5 - Java

The reason is not that the server might fail but it might be hard to find such output on the server. You should always use some kind of logging framework with a defined behaviour and output file.

Solution 6 - Java

For one, having multiple requests hitting your server and printing the log on System.out isn't good practice.

  1. All the logs gets printed on screen (file descriptor). There's no way to scroll back and read the log.
  2. System.out isn't synchronized. There must be a concurrency management to manage printing via System.out
  3. You can't determine log levels through System.out. You can't separate your log levels to separate outputs on the fly.

I hope this helps.

Solution 7 - Java

  1. Program will wait until the println has finished. Loggers use message queue and write only if no other output is going on.
  2. System.out.println (SOPs) are not thread safe (i.e asynchronous) Loggers are thread safe (i.e synchronous)
  3. Loggers are highly configurable a. Formatting, Limiting log content achievable by loggers b. Multiple destination logging –file, console, DB
  4. SOPs write logs into Server log files. We need to keep application logs separate from Server logs as it may lead to Server Failure
  5. Server applications which manages to handle 1700 transactions per second falls down to only 800 when inserting a single SOPs with fix String in each

Solution 8 - Java

Using standard out is bad practice. However if you have a library, or code which uses System.out and System.err you can write your own PrintStream which logs the thread name and info() and error() the text instead. Once you have done this, you may be more relaxed about using System.out as it will write to the logs e.g. log4j.

Ideally you will use the proper logs directly esp for debug level logging. IMHO its doesn't have to matter that much, provided you don use the built-in System.out/err! (A big assumption admittedly)

Whether you use System.out which is re-directed to a file or use log4j or Java Logger to write to a file, the performance is almost exactly the same.

Solution 9 - Java

One more reason is that System.out and err are PrintStreams, which are consuming all underlying IOExceptions. See this methods of PrintStreams:

/**
 * Writes the specified byte to this stream.  If the byte is a newline and
 * automatic flushing is enabled then the <code>flush</code> method will be
 * invoked.
 *
 * <p> Note that the byte is written as given; to write a character that
 * will be translated according to the platform's default character
 * encoding, use the <code>print(char)</code> or <code>println(char)</code>
 * methods.
 *
 * @param  b  The byte to be written
 * @see #print(char)
 * @see #println(char)
 */
public void write(int b) {
    try {
        synchronized (this) {
            ensureOpen();
            out.write(b);
            if ((b == '\n') && autoFlush)
                out.flush();
        }
    }
    catch (InterruptedIOException x) {
        Thread.currentThread().interrupt();
    }
    catch (IOException x) {
        trouble = true;
    }
}

/**
 * Flushes the stream and checks its error state. The internal error state
 * is set to <code>true</code> when the underlying output stream throws an
 * <code>IOException</code> other than <code>InterruptedIOException</code>,
 * and when the <code>setError</code> method is invoked.  If an operation
 * on the underlying output stream throws an
 * <code>InterruptedIOException</code>, then the <code>PrintStream</code>
 * converts the exception back into an interrupt by doing:
 * <pre>
 *     Thread.currentThread().interrupt();
 * </pre>
 * or the equivalent.
 *
 * @return <code>true</code> if and only if this stream has encountered an
 *         <code>IOException</code> other than
 *         <code>InterruptedIOException</code>, or the
 *         <code>setError</code> method has been invoked
 */
public boolean checkError() {
    if (out != null)
        flush();
    if (out instanceof java.io.PrintStream) {
        PrintStream ps = (PrintStream) out;
        return ps.checkError();
    }
    return trouble;
}

So an IOException from the underlying stream is ALWAYS consumed, and usually the people never call checkError on System out, so they are not even knowing that something happened.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionOleksandrView Question on Stackoverflow
Solution 1 - JavaLarsView Answer on Stackoverflow
Solution 2 - JavaAlexander RühlView Answer on Stackoverflow
Solution 3 - JavaJean-Philippe BriendView Answer on Stackoverflow
Solution 4 - JavaHarry JoyView Answer on Stackoverflow
Solution 5 - JavatobiasbayerView Answer on Stackoverflow
Solution 6 - JavaBuhake SindiView Answer on Stackoverflow
Solution 7 - JavaYatish BalajiView Answer on Stackoverflow
Solution 8 - JavaPeter LawreyView Answer on Stackoverflow
Solution 9 - JavaGábor LiptákView Answer on Stackoverflow