Monday, June 20, 2016

Why use Log4j logging vs System.out.println in Java

Printing messages to the console is an integral part of development, testing and debugging 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 pretty handy System.out.println() methods to print something on 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 warning while using System.out.println() for logging purpose, 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 console is redirected.

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

Why use Log4j logging vs System.out.println in Java

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) 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.e. you can disable message belongs to one particular log level e.g. you would be more concerned to see WARN messages than DEBUG messages in production.

2) The second point, which is related to the previous one is that logging framework allows you to suppress message from another log 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 generates 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 logging level using JMX without restarting the server.

3) 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 this facilities when you use the System.out.println() statements for logging messages. What more, eve Joshua Bloch has also suggested using a properly logging facility e.g. java.util.Logger for logging in his classic book Effective Java, one of the must-read books for experienced Java programmers.

Logging vs System.out.println in Java

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 live with millions of users or trades.

Log4j in Java application

Logging also affects performance in a big way, I have seen a live example where 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.

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 application 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 over print() statements. Though, formatted output with metadata, controlling log level at runtime are some of the features you certainly don't want to ignore.

Further Learning
Complete Java Masterclass
Java Fundamentals: The Java Language
Java In-Depth: Become a Complete Java Engineer!

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


Ashish Agarwal said...

logging also provide some benefits like for error we can send mails or we can insert into database without some extra code for that.

Javin Paul said...

@Ashish, good points, Indeed, you can configure Log4j to insert log statements into database or send email.

Remko Popma said...

It would be great if you and other bloggers would write about Log4j 2. As you may know, Log4j-1.2 became End Of Life in 2015 and is no longer supported. That’s a nice way to say it is dead.

Log4j 2 on the other hand is actively being developed and is very much alive. Log4j 2 has some cool features like support for Java 8 lambdas, it is garbage-free(!) and performance-wise it runs circles around the competition (log4j-1.2, Logback and JUL).

There is a lot of interesting stuff to write about, take a look at its Async Loggers.

For us as an industry it is important to keep learning and switch to modern technology when something becomes outdated.

I think it’s great that bloggers like yourself help to make knowledge of modern Java technology available to many people!

Javin Paul said...

Hello @Remko, Sure, I'll write about Log4j 2. I have already used it as an asynchronous logging library, as you mentioned to improve performance of mission critical Java application. Though, this article is in general using logger over System.out.println, Log4j is just a symbolic representation for logging library. Thanks for suggestion though.

Balaji Manoharan said...

Very Good article. Though its simple when think about logging. But we think about performance its matters more.

Javin Paul said...

@Balaji, Indeed, performance is a big issue here, with logging you can always reduce logging to improve performance, btw, in practice attaining right balance of performance and logging is easier said than done.

Remko Popma said...

Logging can indeed be a cause of performance issues. Modern hardware is extremely fast, but old logging libraries (like Log4j 1.2 and Logback) suffer from lock contention. Log4j 2 has Async Loggers based on the LMAX Disruptor which makes a huge performance difference. Don't "log less", upgrade!

Post a Comment