Log4j2 in Spring boot
Tags: springboot, debugging, security
Published: 2024-01-22 05:02:27

In the dynamic world of fintech, where thousands of transactions per hour demand seamless operations, backend engineers play a pivotal role in ensuring systems' high availability and reliability. One indispensable tool in their arsenal is comprehensive logging, which serves as the backbone for identifying, troubleshooting, and optimizing critical financial applications. Detailed logs can help trace the execution flow, pinpoint errors, and understand the context of unexpected behaviors. Not only do these logs help to monitor performance, auditing system health checks. Thus I was tasked to implement log4j. The implementation details are below.

**Dependency**

```
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</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>
   <version>2.5.5</version>
  </dependency>

  <dependency>
   <groupId>org.apache.logging.log4j</groupId>
   <artifactId>log4j-layout-template-json</artifactId>
   <version>2.14.1</version>
  </dependency>
  <dependency>
   <groupId>net.logstash.logback</groupId>
   <artifactId>logstash-logback-encoder</artifactId>
   <version>6.6</version>
  </dependency>
```
**The Usage of logs**

```
LoggerFactory.getLogger(getClass()).info(message);
LoggerFactory.getLogger(getClass()).debug(message);
LoggerFactory.getLogger(getClass()).error(message);
```
**Add an XML file named logback.xml like below
**

```
<configuration>
    <appender name="jsonConsoleAppender" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
    </appender>
    <appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
            <providers>
                <timestamp/>
                <pattern>
                    <pattern>
                        {
                        "level": "%level",
                        "logger": "%logger",
                        "message": "%message"
                        }
                    </pattern>
                </pattern>
            </providers>
        </encoder>

        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>ms-identity-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxFileSize>1GB</maxFileSize>
            <cleanHistoryOnStart>false</cleanHistoryOnStart>
        </rollingPolicy>
    </appender>


    <root level="INFO">
        <appender-ref ref="jsonConsoleAppender"/>
        <appender-ref ref="RollingFile" />

    </root>
</configuration>
```
**If you want to store logs in files.
**

```
<configuration>
    <appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
            <providers>
                <timestamp/>
                <pattern>
                    <pattern>
                        {
                        "level": "%level",
                        "logger": "%logger",
                        "message": "%message"
                        }
                    </pattern>
                </pattern>
            </providers>
        </encoder>

        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>application-name-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxFileSize>1GB</maxFileSize>
            <cleanHistoryOnStart>false</cleanHistoryOnStart>
        </rollingPolicy>
    </appender>

    <root level="INFO">
        <appender-ref ref="RollingFile" />
    </root>
</configuration>
```

**Store logs in DB
**

```
   CREATE TABLE `logging` (
  `EVENT_ID` int(11) NOT NULL AUTO_INCREMENT,
  `EVENT_DATE` datetime DEFAULT NULL,
  `LEVEL` varchar(45) DEFAULT NULL,
  `LOGGER` varchar(45) DEFAULT NULL,
  `MSG` varchar(45) DEFAULT NULL,
  `THROWABLE` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`EVENT_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
```

```
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
 <Appenders>
  <Console name="Console" target="SYSTEM_OUT">
   <PatternLayout
    pattern="%d{HH:mm:ss.SSS} $${env:JournalDevVar} $${env:JournalDevSecondVar} [%t] %-5level %logger{36} - %msg%n" />
  </Console>
  <JDBC name="databaseAppender" tableName="journaldev.logging">
   <DataSource jndiName="java:/comp/env/jdbc/JournalDevDB" />
   <Column name="EVENT_DATE" isEventTimestamp="true" />
   <Column name="LEVEL" pattern="%level" />
   <Column name="LOGGER" pattern="%logger" />
   <Column name="MSG" pattern="%message" />
   <Column name="THROWABLE" pattern="%ex{full}" />
  </JDBC>
 </Appenders>
 <Loggers>
  <Root level="ERROR">
   <AppenderRef ref="Console" />
  </Root>
  <logger name="com" level="TRACE" additivity="false">
   <AppenderRef ref="databaseAppender" />
  </logger>
  <logger name="com.journaldev" additivity="false">
   <AppenderRef ref="databaseAppender" />
  </logger>
 </Loggers>
</Configuration>
```