Search code examples
jsonspring-bootlogginglog4j2logback

Migrating from log4j2 to logback


I am currently migrating logging feature from log4j2 to logback. I have some doubtful situations in the migration process. My doubts are related to JSON format conversions. First of all I will list down example code snippets from my logging module.

Log4j2

pom file

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>net.logstash.log4j</groupId>
    <artifactId>jsonevent-layout</artifactId>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <scope>test</scope>
</dependency>

log4j2.xml file (Only JSON appender)

<RollingFile name="RollingFile" fileName="logFolder/jsonLog.json"
             filePattern="logFolder/%d{yyyyMMdd}_jsonLog-%i.json" >
    <JsonLayout properties="true" compact="true" eventEol="true">
        <KeyValuePair key="timestamp" value="$${date:yyyy-MM-dd'T'HH:mm:ss.SSSX}" />
    </JsonLayout>
    <Policies>
        <TimeBasedTriggeringPolicy />
        <SizeBasedTriggeringPolicy size="5 MB" />
    </Policies>
    <DefaultRolloverStrategy max="5"/>
</RollingFile>

Output JSON log

{
   "instant":{
      "epochSecond":1635493457,
      "nanoOfSecond":835332800
   },
   "thread":"background-preinit",
   "level":"INFO",
   "loggerName":"org.hibernate.validator.internal.util.Version",
   "message":"HV000001: Hibernate Validator 6.1.7.Final",
   "endOfBatch":false,
   "loggerFqcn":"org.hibernate.validator.internal.util.logging.Log_$logger",
   "contextMap":{
      
   },
   "threadId":17,
   "threadPriority":5,
   "timestamp":"2021-10-29T13:14:17.835+05"
}

Due to the above default implementation I get this JSON formatted file.

Logback

pom file

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-core</artifactId>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.8</version>
</dependency>
<dependency>
    <groupId>ch.qos.logback.contrib</groupId>
    <artifactId>logback-json-classic</artifactId>
</dependency>
<dependency>
    <groupId>ch.qos.logback.contrib</groupId>
    <artifactId>logback-jackson</artifactId>
</dependency>

logback.xml file (Only JSON appender)

<appender name="JSON" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>logFolder/${DATE}_jsonlog.json</file>
    <append>true</append>
    
    <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
        <fileNamePattern>logFolder/${DATE}_jsonlog-%i.json</fileNamePattern>
    </rollingPolicy>

    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
        <maxFileSize>1MB</maxFileSize>
    </triggeringPolicy>

    <layout class="ch.qos.logback.contrib.json.classic.JsonLayout">
        <jsonFormatter class="ch.qos.logback.contrib.jackson.JacksonJsonFormatter">
            <prettyPrint>false</prettyPrint>
        </jsonFormatter>
        <timestampFormat>yyyy-MM-dd' 'HH:mm:ss.SSS</timestampFormat>
        <appendLineSeparator>true</appendLineSeparator>
    </layout>
</appender>

Output JSON log

{
   "timestamp":"2022-02-01 08:48:57.863",
   "thread":"background-preinit",
   "level":"INFO",
   "loggerName":"org.hibernate.validator.internal.util.Version",
   "message":"HV000001: Hibernate Validator 6.1.7.Final"
}

As seen above with default configuration of both log4j2 and logback, outcome of the JSON is different. I want to get the same JSON format from log4j2 while using logback.

According to my own research I did found out that I can write a class extending from JacksonJsonFormatter and override method toJsonString. There I can do the changes to the JSON keys and add values.

However, is there any convenient way of doing that without writing a separate class. With using logback I want to get the threadId, threadPriority etc. I want to do that only using logback.xml. In log4j2 I didn't have to write a separate class to get the JSON file I currently get and I hope logback also supports doing that in another way. Can anyone please help me to figure out this and thank you in advance.


Solution

  • The migration from log4j to logback is done now. I was able to do that easily and it is not possible to get the default JSON format of log4j to logback because the defaults in logback is different. To change the to JSON format in logback either I have to modify the logback.xml file or add an extra class for that.