Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE

1. Overview

In this tutorial, we’ll explore how to log messages to both file and console using the Apache Log4j2 library.

This is very useful in a non-prod environment where we may want to see debug messages in the console, and we may want to persist the higher level logs to a file for later analysis.

2. Project Setup

Let’s start by creating a Java project. We’ll add the log4j2 dependencies and look at how to configure and use the logger.

2.1. Log4j2 Dependency

Let’s add the log4j2 dependencies to our project. We’ll need the Apache Log4J Core and Apache Log4J API dependencies:

<dependencies>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.19.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>2.19.0</version>
    </dependency>
</dependencies>

2.2. Application Class

Now let’s use the log4j2 library to add some logging to our application:

public class Log4j2ConsoleAndFile {

    private static final Logger logger = LogManager.getLogger(Log4j2ConsoleAndFile.class);

    public static void main(String[] args) {
        logger.info("Hello World!");
        logger.debug("Hello World!");
    }
}

3. Log4j2 Configuration

To autoconfigure the logger, we need to have a configuration file on the classpath. It can be in JSON, XML, YAML, or properties format. The file should be named log4j2. For our example, let’s use a configuration file named log4j2.properties.

3.1. Logging to the Console

To log to any destination, we first need to define an appender that logs to the console. Let’s look at the configuration to do this:

appender.console.type = Console
appender.console.name = STDOUT
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n

Let’s understand each of the components of the configuration:

  • appender.console.type – Here, we specify the type of the appender that will be used to log. The type Console specifies that the appender will only write to the console. We should note that the word console in the key name is only a convention and not mandatory.
  • appender.console.name – We can give any unique name that we can use to refer to this appender later.
  • appender.console.layout.type – This decides the name of the layout class used to format the log messages.
  • appender.console.layout.pattern – This is the pattern that will be used to format the log messages.

To enable the console logger, we need to add the console appender to the root logger. We can do this using the name specified above:

rootLogger=debug, STDOUT

Using this configuration, we’ll log all debug and above messages to the console. For a console running in a local environment, debug level logging is common.

3.2. Logging to a File

Similarly, we can configure the logger to log to a file. This is often useful for persisting logs. Let’s define a file appender:

appender.file.type = File
appender.file.name = LOGFILE
appender.file.fileName=logs/log4j.log
appender.file.layout.type=PatternLayout
appender.file.layout.pattern=[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n
appender.file.filter.threshold.type = ThresholdFilter
appender.file.filter.threshold.level = info

In the case of a file appender, it’s mandatory to also specify the file name.

In addition to this, let’s also set the threshold level. Since we’re logging to a file, we don’t want to log all messages because it can take up a lot of persistent storage. We only want to log messages with a level of info or above. We can do this using the filter ThresholdFilter and setting its level info. 

To enable the file logger, we need to add the file appender to the root logger. We need to change the rootLogger configuration to include the file appender:

rootLogger=debug, STDOUT, LOGFILE

Even if we have used the level debug at the root level, the file logger will only log info and above messages.

4. Testing

Now let’s run the application and check the output in the console:

12:43:47,891 INFO  Application:8 - Hello World!
12:43:47,892 DEBUG Application:9 - Hello World!

As expected, we can see both the log messages in the console. If we check the log file at the path logs/log4j.log, we can see only the info level log message:

12:43:47,891 INFO  Application:8 - Hello World!

5. Conclusion

In this article, we learned how to log messages to both a console and a file. We created a Java project, configured Log4j2 using a properties file, and tested that messages are printed to both the console and file.

As always, the full source code is available over on GitHub.

Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE
res – REST with Spring (eBook) (everywhere)
Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.