Custom conversion characters with Log4j2

In today’s post, I will cover about how to create your own conversion characters with log4j2.

Conversion Character

As we know, logging is a critical part of any application. Without logging it is not able to identify what is going on with the application. Most commonly used framework for logging is Log4j and it is very simple, flexible and it comes with a lot of configuration options like xml based, json based, java based, property file based etc.

When we use Log4j then you might have used following kind of pattern to print the message into file

%d{yyyy-MM-dd}-%t-%x-%-5p-%-10c:%m%n

where:

  • (%) sign is a prefix of any conversion character
  • (-5p) is the format modifier for conversion character p
  • (d, t, x, c, m, n) all are the conversion characters which have special meaning of it. For e.g. m stands for printing message, n stands for new line, c is used for printing the class file name, d is for date along with the patteren specified. To know more click

Apart from that, sometimes we need to log our own custom identifiers in the log file so to do that we generally append custom identifier in the log message and print it along with the message as below:

logger.info("Initiating request for transaction Id: " + transId);

where transId - is a unique identifier for the request

This is what we use to do everywhere whereever we required transaction Id in the log file.

As you can see in above example, there is no specific pattern of identifying transaction id as it is a part of message itself. And everytime we’ll have to append transaction id along with the message. So there should be some mechanism to get rid off it. That’s why custom conversion characters come into the picture.

Create custom conversion character

To create custom conversion characters, firstly create a class which extends LogEventPatternConverter class of log4j2 as below:

package threadminions.logs.interceptor;

import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.pattern.ConverterKeys;
import org.apache.logging.log4j.core.pattern.LogEventPatternConverter;
import org.apache.logging.log4j.core.pattern.PatternConverter;

@Plugin(name = "requestIdInterceptor", category = PatternConverter.CATEGORY)
@ConverterKeys({"requestId", "transId", "txnId", "uniqueId"})
public class RequestIdInterceptor extends LogEventPatternConverter {

    private RequestIdInterceptor(final String name, final String key) {
        super(name, key);
    }

    public static RequestIdInterceptor newInstance(String[] options) {

        return new RequestIdInterceptor("router", "requestId");
    }

    @Override
    public void format(LogEvent logEvent, StringBuilder stringBuilder) {
        Object[] parameters = logEvent.getMessage().getParameters();
        stringBuilder.append(parameters[0]);
    }
}

Above class has following things:

  • @Plugin annotation – which is required to define the category of what you are going to make. In this it has following attributes:
    • name – A random name of your plugin. In my case, it is requestIdInterceptorcategory – Category of pluing type which you are creating. As we are creating conversion characters so it will be PatternConvertor.CATEGORY.
  • @ConverterKeys – This is the main annotation in which specify (,) separated list of keys which will actually be used as conversion characters. In this example, these are {“requestId”, “transId”, “txnId”, “uniqueId”} so when we use any of above keys in log4j2.xml file eveyone has the same value.
  • Create a private constructor of the class having two variables in it as shown in the example.
  • Create a newInstance method having an array of String and calling the private constructor of the class as shown in the example.
  • Override the format method of the LogEventPatternConverter class and append the final value of characters to its stringBuilder object as shown in the example. This value will be the value for our custom converstion characters. In this example, I am getting its value from the first parameter of loggers method as below:
  • That’s all about the steps of creating custom converstion characters. It’s time to use of it.

After creating above class just create log4j2.xml file as below:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration packages="threadminions.logs.interceptor">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yyyy-MM-dd}-%t-%transId-%x-%-5p-%-10c:%m%n"/>
        </Console>

    </Appenders>

    <Loggers>
        <Root level="INFO" additivity="false">
            <AppenderRef ref="Console" level="ALL"/>
        </Root>
    </Loggers>
</Configuration>

It has following things:

  • packages – an attribute having the package name of our custom class. In this example, it is threadminions.logs.interceptor
  • Just define custom conversion character with prefix %transId to use it.

After adding these two things, format method of your class will be invoked automatically and whatever value you will append in this, it will be used for %transId. That’s all about defining custom conversion character.

Just modify the statement of logger as below:

logger.info("Initiating requeset come", transId);

As you can see, we passed transId as a second parameter of method and it will be fetched in format method and will be printed on the console.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s