Lazy logging with log4j2 in Java

The purpose of logging is to provide information about what is happening in the system, which requires including information about the objects being manipulated. In this blog post I will show you how can we achieve lazy logging with log4j 2.x framework.

In Log4j 1.x this could be accomplished by doing

logger.debug("Welcome to " + user.getName() );
Code language: Java (java)
https://gist.github.com/sureshgadupu/8528109596f017bbfdf44462aa0b9c82

The Problem with the above statement is even if we are using “ERROR” level in the logging statement is evaluated which consumes some time. Imagine for debugging purpose if we are logging 100 objects it will consume even more time even though it won’t logged.

To overcome the above problem , we can explicitly check the log level enabled and then evaluate the statement like below.

if (logger.isDebugEnabled()) {
    logger.debug("Welcome to " + user.getName() );
}Code language: Java (java)
https://gist.github.com/sureshgadupu/d891cde3565041895ac61d611e56168b

Problem with above statements in log level is being checked twice ( in Line 1 & 2) and if we have many log statements like above code looks cumbersome.

We can overcome the problem using log4j version 2 and Java 8 by lazily logging the log statements without explicitly checking the log level.

Required softwares

  • JDK 1.8+
  • Maven 3.0+
  • Log4j2 2.4+
  • Eclipse/IntelliJ Idea

Create Sample application

Open a command prompt and go to your workspace directory and use following maven command to create a Java project

mvn archetype:generate -DgroupId=com.sureshtech -DartifactId=lazy-logging -DarchetypeGroupId=com.thepracticaldeveloper -DarchetypeArtifactId=archetype-java-basic-tpd -DarchetypeVersion=1.0.0
Code language: Java (java)
https://gist.github.com/sureshgadupu/d4cc68ef1508cf9b3d2c2aaefd310756

Maven command will ask for confirmation before creating project. If the project details are correct type “Y” for creating the project.

Now import the project into your workspace. For steps to import maven project into eclipse IDE, please visit my previous blog post

Adding lo4j2 dependencies

First we will add the log4j2 maven dependencies in pom file. Add the following log4j2 dependencies to pom.xml

<dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>2.14.1</version>
      </dependency>
      <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.14.1</version>
      </dependency>Code language: Java (java)
https://gist.github.com/sureshgadupu/48dfd41b2f51ec4bc8af0438740c4ebf

Let’s add log4j2 xml configuration file to project for logging.Add the log4j2.xml file in src/main/resources folder

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
	<Appenders>
		<Console name="STDOUT" target="SYSTEM_OUT">
			<PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
		</Console>
	</Appenders>
	<Loggers>
		<Logger name="lazy-logger" level="info"/>
		<Root level="info">
			<AppenderRef ref="STDOUT"/>
		</Root>
	</Loggers>
</Configuration>Code language: Java (java)
https://gist.github.com/sureshgadupu/ce894f17c0d2f0a7c8bbfc39d6f30ec3

Now let’s initialize the logger in App.java class and add some log statements in the class.Since lazy-looger log level is set to info. Let’s add few debug and info statements. I have added log statements getName method of User class

package com.sureshtech;

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

public class App 
{
    private static final Logger logger = LogManager.getLogger("lazy-logger");
	
	
    public static void main( String[] args )
    { 
    	User user = new User();
    	
    	user.setId(1);    	
    	user.setName("Test");   	
    	
    	
    	logger.debug("Welcome to {}!", user.getName() );
    	
    	logger.info("Welcome to {}!",user.getName() );
       
       
    }
}Code language: Java (java)
https://gist.github.com/sureshgadupu/d0392ff113074513ac3a703fcca3ccba

Now if you run App.java class, you will see the following log statements. In the below image you can observe that getName is called logged twice ( one for info and one for debug statement) even though the log level is set to.INFO That means we are facing same problem as log4j 1.x

With the introduction of lambda expressions in Jdk1.8 , log4j2 added support for lambda is logging which gets evaluated lazyily.

Let’s change the log statements with lambda expressions and run the program again.

https://gist.github.com/sureshgadupu/3d91083dcc0534c9bf981ba5b5404d6a

Now let’s check the logs again. Magically getName is called logged only once. Using lambdas in log statements will result lazy calls to methods. In this case since log level is set to INFO only info log statements are evaluated

lazy logging

You can download the source code for this blog post from GitHub

Similar Posts