Log4J 2 Configuration: Using Properties File

Log4J 2 Configuration: Using Properties File

34 Comments

Log4J 2 is a logging framework designed to address the logging requirements of enterprise applications. Its predecessor Log4J 1.x has been around for more than one and a half decade and is still one of the most widely used Java logging framework. Log4J has even been ported to the .NET world. Log4net is one of the most popular logging frameworks for Microsoft’s .NET environment.

Log4J 2 goes steps ahead by removing the inherent architectural flaws of Log4J 1.x.  Since the initial release of Log4J 2 on August 2015, it’s quickly being adopted by the developer community. I wrote an introductory post on Log4J 2 here. If you have not read it, I recommend starting with the introductory post first. In this post, I will discuss how to configure Log4J 2 using a properties configuration file. This is just one of several ways you can configure Log4J 2.

What are Log4J 2 Configuration Files?

Log4J 2 provides various components, such as loggers, appenders, and layouts that work together to perform logging in an application. As different applications have different logging requirements, you’re able configure LogJ 2 accordingly. Also, you will often need to keep changing Log4J 2 configurations of an application across its deployment lifecycle. For example, it is common to set the logging level to DEBUG during development, and later switch it to ERROR to avoid filling your logs with excessive debug information. Similarly, during local development, you can work with the console appender to avoid file I/O overheads and in other deployment environments, set a file appender or some other persistent destination to preserve log messages.

You can configure Log4J 2 either programmatically in your application or through configuration files, such as properties, XML, JSON, and YAML residing on your project classpath. Through the use of configuration files, you have the flexibility of changing the various configuration options without modifying your application code. In this post we’re going to look at using properties file.

Setting up Log4J 2 to Use Properties File

Unlike its predecessor Log4J 1.x, Log4J 2 did not support configuration through properties file when it was initially released. It was from Log4J 2.4 that support for properties file was again added, but with a completely different syntax.

Log4J4 Maven Dependencies

To use Log4J 2 in your application, you need to ensure that the Log4J 2 jars are on your project classpath. If you intend to use properties file, give extra attention to ensure that you have the Log4J 2.4 or greater jars on the classpath. Otherwise, your properties file will not get picked.
When using Maven, specify the following Log4J 2 dependencies.

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

Log4J 2 Spring Boot Dependencies

If you want to use Log4J 2 in a Spring Boot project, things can be a bit tricky. Simply adding the dependencies above won’t work as Spring Boot will first find the default Logback classic on the classpath, and will use it. Therefore, you need to exclude the default dependency of the Spring Boot starter on Logback classic, and instead include the Spring Boot starter dependency on Log4J 2, like this.

. . .
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter</artifactId>
   <exclusions>
      <exclusion>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-logging</artifactId>
      </exclusion>
   </exclusions>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
. . .

This will configure Spring Boot to use Log4J 2, but with a catch – You still won’t be able to use properties file for configuration. As of Spring Boot 1.3.3 Release, Spring Boot starter dependency on Log4J 2 is for Log4J 2.1, and as I have already mentioned it is from Log4J 2.4 onward that properties file is supported. Therefore, you need to explicitly specify dependencies of Log4J 2.4 or above after excluding Spring Boot starter logging, like this.

. . .
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter</artifactId>
   <exclusions>
      <exclusion>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-logging</artifactId>
      </exclusion>
   </exclusions>
</dependency>

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

The above dependencies will set up Log4J 2 to use properties file in a Spring Boot application.

Spring Framework 5
Check out my Spring Framework 5: Beginner to Guru online course!

Configuring Log4J 2 using Properties File

By default, Log4J 2 looks for a properties file with the name log4j2.properties in the classpath. In a Spring Boot application, the log4j2.properties file will typically be in the resources folder.

Before we start configuring Log4J 2, we will write a Java class to generate log messages via Log4J 2.

Log4J2PropertiesConf.java

   //package guru.springframework.blog.log4j2properties;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Log4J2PropertiesConf {
    private static Logger logger = LogManager.getLogger();
    public void performSomeTask(){
        logger.debug("This is a debug message");
        logger.info("This is an info message");
        logger.warn("This is a warn message");
        logger.error("This is an error message");
        logger.fatal("This is a fatal message");
    }
}

To test the Log4J2PropertiesConf class above, we will write a JUnit test class.

Log4J2PropertiesConfTest.java

   //404: Not Found

We will now configure Log4J 2 using a properties file. Like any other Java properties file, a log4j2.properties file are a set of key value pairs with options to configure the various components of Log4J 2, such as loggers, appenders, and layouts. A basic log4j2.properties file starts with a name, optional properties to be used in other parts of the file, and appender declarations.

name=PropertiesConfig
property.filename = logs
appenders = console, file
. . .

The preceding code declares two appenders, named console and file. Next, let’s configure both the appenders to write log messages to the console and a file. The configuration code for the appenders is 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

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

In the code above we configured two appenders: One to write log messages to the console and the other to a log file. Both the appenders use pattern layouts that are configurable with conversion pattern strings to format log messages. The appender.console.layout.pattern property specifies the pattern string. You can learn more about the pattern layout and conversion pattern strings here. For the file appender, we used the appender.file.fileName property to specify the name and location of the log file that Log4J 2 will generate. Here, notice the ${filename} declaration that we used as a substitution for the property.filename property we declared earlier.

Next we will configure the loggers, starting from the root logger.

. . .
rootLogger.level = debug
rootLogger.appenderRefs = stdout
rootLogger.appenderRef.stdout.ref = STDOUT
. . .

In the code above, we configured the root logger to log debug and its lower level messages to the console (stdout). When we run the Log4J2PropertiesConfTest test class, the output in the IntelliJ console will be similar to this.
Log4J 2 Messages in InteliJ Console

The complete log4j2.properties file is this.

log4j2.properties

   //name=PropertiesConfig
property.filename = logs
appenders = console, file

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

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

loggers=file
logger.file.name=guru.springframework.blog.log4j2properties
logger.file.level = debug
logger.file.appenderRefs = file
logger.file.appenderRef.file.ref = LOGFILE

rootLogger.level = debug
rootLogger.appenderRefs = stdout
rootLogger.appenderRef.stdout.ref = STDOUT

When we run the Log4J2PropertiesConfTest test class now, log messages will be sent to the logs/propertieslogs.log by the file logger and additively to the console by the root logger. The following figure shows the log messages sent to the file and console in IntelliJ.

Log4J 2 Output in IntelliJ

In the example above, it is due to logger additivity that caused log messages to be sent to the file by the logger and additively to the console by the root logger. You can override this default behavior by setting the additivity flag of a logger to false.

. . .
logger.file.additivity = false
. . .

The property above configures our file appender so that it is no longer additive. Thus, log messages will only be sent to the file.

Appender additivity can be somewhat confusing. I suggest reviewing the Log4J 2 documentation on the subject, where they have some good examples how this works.

Summary

Using properties file is one of the several options you have to configure Log4J 2. Log4J 2 is gradually moving to XML configuration and the new JSON and YAML configurations. Properties configuration cannot handle some advanced features, such as custom error handlers, time-based rolling policies, nested appenders, and special types of appenders, such as async appenders. However, properties configuration is still being extensively used. Often you don’t need many of the more advanced logging features of Log4J 2. So you’re fine using the simplicity of the properties file configuration.

In future posts, I will cover using other configuration options for Log4J 2. This is to address logging configurations with more complex requirements.

Spring Framework 5
Become a Spring Framework Guru with my Spring Framework 5: Beginner to Guru course!

 

About jt

    You May Also Like

    34 comments on “Log4J 2 Configuration: Using Properties File

    1. April 7, 2016 at 5:19 pm

      How to configure multiple packages with ‘logger.rolling.name’ with in this properties file for the same rolling appender? I have tried a lot but could not able to configure. when I add multiple entries it is considering only the last entry and ignoring other ‘logger.rolling.name’ entries.

      Reply
      • April 8, 2016 at 4:37 am

        Try this.

        loggers=file1,file2
        logger.file1.name=guru.springframework.blog.log4j2properties
        logger.file1.level = debug
        logger.file1.appenderRefs = file
        logger.file1.appenderRef.file.ref = LOGFILE
        logger.file2.name=guru.springframework.blog.example
        logger.file2.level = error
        logger.file2.appenderRefs = file
        logger.file2.appenderRef.file.ref = LOGFILE

        It works for file appender. Should work for rolling file too.

        Reply
        • August 5, 2019 at 5:29 am

          Hi Ximanta,
          Im not used to configuring loggers. However, i felt it was very convenient to enter the logger entry in a single line as done for log4j. Whereas, in log4j2 we have to specify a whole block of config.
          Ex:- In log4j we could x.y.z = debug,file,console to log debug statements of x.y.z
          whereas in log4j2 we have to :-
          logger.file2.name=x.y.z
          logger.file2.level = debug
          logger.file2.appenderRefs = file
          logger.file2.appenderRef.file.ref = LOGFILE

          Reply
    2. April 8, 2016 at 5:20 pm

      Thank you very much Ximanta, it is working fine in this way.

      If you don’t mind I have one more question here: without declaring the log file path/name inside the properties file like ‘property.filename’ can’t we use the JVM/run-time arguments instead? I have tried but could not able to use them.

      Reply
      • April 9, 2016 at 1:20 am

        Update the current appender.file.fileName property

        To:

        appender.file.fileName=${sys:logfile.name}

        Run application passing the value as JVM argument. For example:

        -Dlogfile.name=logs/yakam.log

        You should get a log file with your name in the logs directory.

        Reply
        • July 24, 2016 at 1:03 pm

          Hi Ximanta,

          How can we set default value along with system properties.

          Say for example, If -Dlogfile.name not set I need to use some preconfigured default values?

          Is there way along with system property we can define dafault?

          Thanks,
          Arun.

          Reply
    3. April 11, 2016 at 9:47 am

      Great. Thanks again, working perfectly.

      Reply
    4. April 13, 2016 at 9:02 am

      Hi,
      I have a problem writing to the file. The file is created in the logs folder but nothing is written.
      I don’t understand this property: logger.file.name=guru.springframework.blog.log4j2properties What value am I supposed to give with different package structure. I don’t understand what it refers to.

      Thanks,

      Reply
      • April 13, 2016 at 9:24 am

        That property just sets the filename for the appender to use. If you’re not getting an log messages, but a file, its likely you have a problem elsewhere in your configuration.

        Reply
    5. April 13, 2016 at 5:59 pm

      Hi JT,
      Thanks for your answer. In fact I am getting the console logging, the file is created but the logs are not written in the file. I have double checked my configuration but It still doesn’t work. I must be doing something wrong.

      Thanks anyway,

      Reply
      • April 13, 2016 at 8:10 pm

        Check the package of your logger class (The class containing logging code.)

        logger.file.name should point to it.

        In the example, the class is Log4J2PropertiesConf and the package is guru.springframework.blog.log4j2properties;

        Therefore:

        logger.file.name=guru.springframework.blog.log4j2properties

        This line configures all loggers of the guru.springframework.blog.log4j2properties package and its subpackages, say guru.springframework.blog.log4j2properties.asubpackage

        Reply
        • November 6, 2020 at 8:11 am

          can you please solve my problem mentioned below?

          Reply
      • June 18, 2020 at 2:55 am

        I am facing the same issue. Were you able to figure what caused this? I am using log4j2.properties file.

        Reply
    6. April 14, 2016 at 1:54 am

      Hi Ximanta,

      Thanks for the explanation, everything is working fine now.

      Cheers

      Reply
    7. June 3, 2016 at 6:24 am

      What is the difference between ” logger.file.level = debug and rootLogger.level = debug” ?

      Reply
      • June 15, 2016 at 12:20 am

        If you look carefully at the code, note that

        logger.file.level = debug is configured for the logger of the guru.springframework.blog.log4j2properties package.

        But, in our application, we might not configure all loggers individually. Such loggers will inherit the root logger properties including its level. We specified the level as debug, as shown below.

        rootLogger.level = debug

        Reply
    8. June 15, 2016 at 6:49 am

      Thank you ….I understood now

      Reply
    9. July 25, 2016 at 1:51 am

      Hi,

      I am looking for system property input with default value setup for log path.

      For eg., ${sys:log.path} not set in system property, How we can set the default value?

      Reply
    10. July 25, 2016 at 2:26 am

      I am looking for system property input with default value setup for log path.
      For eg., ${sys:logfile.name} not set in system property, How we can set the default value?

      Reply
    11. January 6, 2017 at 12:42 am

      Hi ,
      I am refering the code above,
      Console Appender is working fine for me
      But for File Appender is not created

      I have kept the logger.file.name = (Package which is using logging)

      Reply
    12. February 26, 2018 at 5:43 pm

      Thanks so much for this concise explanation. This helped me tremendously. I always find code examples to be the best way to learn these things.

      Reply
    13. May 31, 2018 at 2:10 am

      I had to add following 2 dependencies for my program to work

      org.slf4j
      slf4j-api

      org.apache.logging.log4j
      log4j-slf4j-impl

      still it is not able to read log4j2.properties file. it was using default configuration

      I had to add following line in the application.properties file to work

      logging.config=src/main/resources/log4j2.properties

      where I am wrong?
      why it is not automatically detecting the log4j2.properties

      Reply
    14. June 15, 2018 at 5:57 pm

      Can you configure async appenders this way? or do they have to be one of the more complicated formats? if not, can the more complicated formats be parameterized with properties?

      Reply
    15. July 27, 2018 at 8:25 am

      Hi! Is there any way to change the name of log4j.properties file?

      Reply
    16. August 2, 2018 at 7:41 am

      Hi,

      I also facing the same issue like file is creating but logs are not written in to the file as i am following same as above even not working.

      Please find my code on below url:

      https://stackoverflow.com/questions/51649986/spring-boot-log4j2-properties-creating-log-files-but-not-writing-the-logs-in-f?noredirect=1#comment90268058_51649986

      Please help on this.

      Reply
    17. October 5, 2018 at 8:38 am

      i Have setup of project which is getting all services log in single file how can i create different log file of each service

      Reply
    18. May 24, 2019 at 9:07 am

      If want to print values for appender.file.name then how to do in Java code and also suppose want to update existing value with new.

      Please suggest

      Reply
    19. November 6, 2020 at 8:00 am

      Generally how to create multipe logs files through log4j2.properties .

      Here we have property,

      appender.file.fileName=${filename}/propertieslogs.log

      the above property describes only one log file. Now, how to create multiple log files and persist logs into those log files.

      Reply
    20. December 29, 2020 at 7:45 am

      Hi,
      I have copied the code as mentioned above and changed the value for as below inlo4j2.properties file
      logger.file.name=cucumberUtilities

      no log folder created after run of log4J class and in console only Error & Fatal messages are displaying , could you pls help here.

      Reply

    Leave a Reply

    Your email address will not be published. Required fields are marked *

    This site uses Akismet to reduce spam. Learn how your comment data is processed.