Why use Log4j logging vs System.out.println in Java? Answer (original) (raw)

Printing messages to the console is an integral part of the development, testing, and debugging of a Java program. If you are working on a Server-side application, where you can not see what's going on inside the server, your only visibility tool is a log file; without logs, you can not do any debugging or see what's going on inside your application. Though, Java has a pretty handy System.out.println() method to print something on the console, which can also be routed to log file but not sufficient for a real-world Java application.

If you are running a Java program in Linux or any UNIX-based system, Log4j or SLF4j or any other logging framework offers a lot more features, flexibility, and improvement on message quality, which is not possible using the System.out.println() statement.

I strongly discourage using System.out.println() or System.err.println() methods for printing anything in production quality code, its simply not acceptable, and you will learn why you should prefer to use Log4j over System.out.println() in this post.

By the way, if you are using modern IDE like Eclipse or Netbeans, you may get a warning while using System.out.println() for logging purposes, which is good, otherwise, you may end up with a scenario where some messages are going to log file while other going somewhere else, probably on a file where the console is redirected.

It's also a best practice to use the Logging framework while coding in Java, even books like Clean Code also suggest learning Log4j for logging.

Why prefer Log4j over System.out.println

Many Java programmers have their own reason for using a logging framework like Log4j, java.util.Logger, SL4j, or even Apache Commons logging, but they all are better than using the System.out.println(). Though my advice is to prefer SLF4j over Log4j for logging in Java as discussed in that article.

Anyway, here are some of the reasons, which I think are enough to stop you using System.out.println() statements in production code:

1. Information segregation using Log Level

Any logging framework including Log4j, SL4J, logback, and java.util.logger allows you to log debugging information with a log level, later you can use that level as filtering criteria, I mean, you can disable messages belongs to one particular log level like you would be more concerned to see WARN messages than DEBUG messages in production.

2. Performance and Flexibility

The second point, which is related to the previous one is that the logging framework allows you to suppress messages from another logging level, for example, you can run your application in DEBUG mode in the test environment, but on ERROR mode in a production environment.

This will not only generate fewer logs but also improves the performance of your application because of less logging, see 10 tips on logging in Java to learn more about this.

This is not possible with System.out.println() statements which can not be controlled by any configuration or dynamically at runtime using JMX or any watchdog facility.

On the other hand, you can change the log level for log4j based logger without restarting your application by using a watchdog thread, which monitors a location for updated log4j.xml, the configuration file for Apache Log4j. The java.util.Logger also allows you to change the logging level using JMX without restarting the server.

3. Better Log Messages

By using a Logging framework, you can produce better outputs and metadata, which will help during troubleshooting and debug. Most logging framework e.g. Log4j allows you to print formatted output by specifying a formatting pattern by using PatterLayout, which can include a timestamp, name of the class, the Thread which is executing code, etc.

All of this information can be really useful while debugging concurrent applications where the output from multiple threads is overlapping. You don't get these facilities when you use the System.out.println() statements for logging messages.

What more, even Joshua Bloch has also suggested using a properly logging facility like java.util.Logger for logging in his classic book Effective Java, one of the must-read books for experienced Java programmers.

Using System.out or System.err rather than a dedicated logging facility makes it difficult to monitor the behavior of the program.

Example 1: The first Java program that a developer learns to write often looks like this:

public class MyClass

public static void main(String[] args) {

System.out.println("hello world");

}

}

While most programmers go on to learn many nuances and subtleties about Java, a surprising number hang on to this first lesson and never give up on writing messages to standard output using System.out.println() statement.

Well, this is Ok if you are writing small test programs but it certainly not right if you coding on a production system that lives with millions of users or trades.

Logging also affects performance in a big way, I have seen a live example where the support team left the production system on DEBUG level only to find the latency shoots up by 500 ms and users complaining about delayed execution.

Log4j in Java application

That's all about why a Java programmer should use a Logging framework over System.out.println() statement in production code. As I said, it's perfectly ok if you are writing test programs and small applications but it's not Ok in your real-world Java application.

You might know that you can also use Log4j without XML configuration or property files if that will encourage you to use it overprint() statements. Though, formatted output with metadata, controlling log level at runtime are some of the features you certainly don't want to ignore.

P.S. - If you want to learn more best practices, you can also check my post on 10 Java Concurrency Best Practices, every Java developer should follow.