Wednesday, August 7, 2019

A Spring Boot based Log4j2 starter project


Spring Boot uses Logback as a default logging solution. In order to switch to Log4j2, there are some configurations that has to be made.

The following customized configurations provide the following features:

A Maven POM for a Spring Boot starter project
Logstash layout dependency for JSon log files to feed into ELK
Log4j configuration with MDC support
Log4j configuration produces multiple log files


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.urcorp</groupId>
    <artifactId>app-springboot-parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>app-log4j2-starter</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>app-log4j2-starter</name>
  <description>Log4j2 starter</description>

  <properties>
    <log4j2-logstash-layout.version>0.19</log4j2-logstash-layout.version>
  </properties>

  <dependencies>
    <!-- logging -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-log4j2</artifactId>
    </dependency>

    <!-- logstash layout -->
    <dependency>
      <groupId>com.vlkan.log4j2</groupId>
      <artifactId>log4j2-logstash-layout</artifactId>
      <version>${log4j2-logstash-layout.version}</version>
    </dependency>
  </dependencies>

  <profiles>
    <profile>
      <id>local</id>
      <activation>
        <os>
          <family>windows</family>
        </os>
      </activation>
      <properties>
        <log.file.location>C:/app/logs</log.file.location>
      </properties>
    </profile>
    <profile>
      <id>server</id>
      <activation>
        <os>
          <family>!windows</family>
        </os>
      </activation>
      <properties>
        <log.file.location>/app/logs</log.file.location>
      </properties>
    </profile>
  </profiles>
</project>



log4j.xml


<?xml version="1.0" encoding="UTF-8"?>
<Configuration xmlns:xi="http://www.w3.org/2001/XInclude" status="DEBUG" name="log4j2-ur-app" monitorInterval="30">
  <Properties>
    <Property name="logPath">${log.file.location}</Property>
    <Property name="text.log.pattern">%d{yyyy-MM-HH:mm:ss.SSS} [%t - %X{HOSTNAME,APPLICATION,CORRELATION_ID,MESSAGE_ID}] %highlight{%level}{FATAL=bg_red, ERROR=red, WARN=yellow, INFO=green, DEBUG=blue} %c{3} - %m%n</Property>
  </Properties>

  <Appenders>
    <Console name="console" target="SYSTEM_OUT">
      <PatternLayout pattern="${text.log.pattern}" />
    </Console>

    <RollingFile name="serverJson" fileName="${logPath}/server.json"
      filePattern="${logPath}/server_%d{yyyy-MM-dd}.%i.json">
      <LogstashLayout dateTimeFormatPattern="yyyy-MM-dd'T'HH:mm:ss.SSSZZZ"
        templateUri="classpath:LogstashJsonEventLayoutV1.json" prettyPrintEnabled="false" stackTraceEnabled="true" />
      <xi:include href="log4j2-policies.xml" />
      <xi:include href="log4j2-rolloverStrategies.xml" />
    </RollingFile>

    <RollingFile name="serverText" fileName="${logPath}/server.log"
      filePattern="${logPath}/server_%d{yyyy-MM-dd}.log">
      <PatternLayout pattern="${text.log.pattern}" />
      <xi:include href="log4j2-policies.xml" />
      <xi:include href="log4j2-rolloverStrategies.xml" />
    </RollingFile>

    <RollingFile name="exceptionText" fileName="${logPath}/exception.log"
      filePattern="${logPath}/exception_%d{yyyy-MM-dd}.log">
      <Filters>
        <ThresholdFilter level="WARN" onMatch="ACCEPT" />
      </Filters>
      <PatternLayout pattern="${text.log.pattern}" />
      <xi:include href="log4j2-policies.xml" />
      <xi:include href="log4j2-rolloverStrategies.xml" />
    </RollingFile>

    <RollingFile name="eventText" fileName="${logPath}/event.log"
      filePattern="${logPath}/event_%d{yyyy-MM-dd}.log">
      <PatternLayout pattern="${text.log.pattern}" />
      <xi:include href="log4j2-policies.xml" />
      <xi:include href="log4j2-rolloverStrategies.xml" />
    </RollingFile>

    <RollingFile name="statsText" fileName="${logPath}/stats.log"
      filePattern="${logPath}/stats_%d{yyyy-MM-dd}.log">
      <PatternLayout pattern="${text.log.pattern}" />
      <xi:include href="log4j2-policies.xml" />
      <xi:include href="log4j2-rolloverStrategies.xml" />
    </RollingFile>

    <RollingFile name="perfText" fileName="${logPath}/perf.log"
      filePattern="${logPath}/perf_%d{yyyy-MM-dd}.log">
      <PatternLayout pattern="${text.log.pattern}" />
      <xi:include href="log4j2-policies.xml" />
      <xi:include href="log4j2-rolloverStrategies.xml" />
    </RollingFile>

    <RollingFile name="sqlText" fileName="${logPath}/sql.log"
      filePattern="${logPath}/sql_%d{yyyy-MM-dd}.log">
      <PatternLayout pattern="${text.log.pattern}" />
      <xi:include href="log4j2-policies.xml" />
      <xi:include href="log4j2-rolloverStrategies.xml" />
    </RollingFile>
  </Appenders>

  <Loggers>
    <Root level="info" additivity="false">
      <AppenderRef ref="console" />
      <AppenderRef ref="serverText" />
      <AppenderRef ref="serverJson" />
      <AppenderRef ref="exceptionText" />
    </Root>

    <logger name="EVENT" level="info" additivity="false">
      <AppenderRef ref="eventText" />
      <AppenderRef ref="console" />
    </logger>
    <logger name="STATISTICS" level="info" additivity="false">
      <AppenderRef ref="statsText" />
    </logger>
    <logger name="PERFORMANCE" level="info" additivity="false">
      <AppenderRef ref="perfText" />
    </logger>

    <logger name="SQL" level="info" additivity="false">
      <AppenderRef ref="sqlText" />
      <AppenderRef ref="console" />
    </logger>
    <logger name="com.zaxxer.hikari" level="debug" additivity="false">
      <AppenderRef ref="sqlText" />
    </logger>
    <logger name="java.sql" level="debug" additivity="false">
      <AppenderRef ref="sqlText" />
    </logger>
    <logger name="org.apache.ibatis" level="debug" additivity="false">
      <AppenderRef ref="sqlText" />
    </logger>
    <logger name="org.mybatis" level="debug" additivity="false">
      <AppenderRef ref="sqlText" />
    </logger>
    <logger name="com.urcorp.dao.generated.mapper" level="trace" additivity="false">
      <AppenderRef ref="sqlText" />
    </logger>
    <logger name="org.springframework.jdbc.core" level="trace" additivity="true">
      <AppenderRef ref="sqlText" />
    </logger>
  </Loggers>

</Configuration>


log4j2-policies.xml


<?xml version="1.0" encoding="UTF-8"?>
<Policies>
  <OnStartupTriggeringPolicy />
  <SizeBasedTriggeringPolicy size="300 MB" />
  <TimeBasedTriggeringPolicy interval="1"
    modulate="true" />
</Policies>


log4j2-rolloverStrategies.xml


<?xml version="1.0" encoding="UTF-8"?>
<DefaultRolloverStrategy>
  <Delete basePath="${logPath}" maxDepth="2">
    <IfFileName glob="*.(json|log)" />
    <IfLastModified age="7d" />
  </Delete>
</DefaultRolloverStrategy>




package com.urcorp.common.logging;

public enum LogFileTypes {
  EXCEPTION("EXCEPTION."),
  EVENT("EVENT."),
  PERFORMANCE("PERFORMANCE."),
  SERVER("SERVER."),
  SQL("SQL."),
  STATISTICS("STATISTICS.");

  private final String group;

  private LogFileTypes(final String group) {
    this.code = group;
  }

  public String group() {
    return group;
  }
}





No comments:

Post a Comment