Spring Boot 使用 Log4j2

Java 中比较常用的日志工具类,有 Log4j、SLF4j、Commons-logging(简称 jcl)、Logback、Log4j2(Log4j 升级版)、Jdk Logging。

Spring Boot 默认使用 Logback,但相比较而言,Log4j2 在性能上面会更好。

Spring Boot(版本1.5.10.RELEASE)中使用 Log4j2 非常简单,添加如下依赖:

<!-- Exclude Spring Boot's Default Logging -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter</artifactId>
	<exclusions>
		<exclusion>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-logging</artifactId>
		</exclusion>
	</exclusions>
</dependency>

<!-- Add Log4j2 Dependency -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

<!-- Needed for Async Logging with Log4j 2 -->
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>3.3.6</version>
</dependency>

<!-- 使用 jsonLayout 必须依赖 jackson -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.7.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.7.4</version>
</dependency>

然后在src/main/resources中添加log4j2.xml配置文件(Spring Boot 还会识别log4j2.jsonlog4j2.yaml):

<?xml version="1.0" encoding="UTF-8"?>
<!-- status 表示 log4j2 本身的日志信息打印级别,和下面的 level,不是一个概念 -->
<!--TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF-->
<Configuration status="OFF" monitorInterval="30">
    <Properties>
        <Property name="LOG_PATTERN">
            %d{yyyy-MM-dd HH🇲🇲ss.SSS} %5p ${hostName} -&#45;&#45; [%15.15t] %-40.40c{1.} : %m%n%ex
        </Property>
        <Property name="LOG_FILE_PATH">/var/log/spring-boot-log4j2</Property>
    </Properties>
    <Appenders>
        <Console name="ConsoleAppender" target="SYSTEM_OUT" follow="true">
            <PatternLayout pattern="${LOG_PATTERN}"/>
        </Console>
        <!-- Rolling File Appender -->
        <RollingFile name="FileAppender" fileName="${LOG_FILE_PATH}/spring-boot-log4j2-demo.log"
                     filePattern="${LOG_FILE_PATH}/spring-boot-log4j2-demo-%d{yyyy-MM-dd}-%i.log">
            <PatternLayout>
                <Pattern>${LOG_PATTERN}</Pattern>
            </PatternLayout>
            <!--<JsonLayout complete="false" compact="true">
                <KeyValuePair key="timestamp" value="$${date:yyyy-MM-dd'T'HH🇲🇲ss.SSSZ}" />
            </JsonLayout>-->
            <Filters>
                <!-- 只记录 ERROR 级别日志信息,程序打印的其他信息不会被记录 -->
                <!-- 此 level 设置的日志级别,是过滤日志文件中打印出的日志信息,和 Root 的 level 有所区别 -->
                <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY" />
            </Filters>
            <Policies>
                <SizeBasedTriggeringPolicy size="10MB" />
                <!-- 每天创建一个日志文件 -->
                <TimeBasedTriggeringPolicy interval="1" />
            </Policies>
            <DefaultRolloverStrategy max="10"/>
        </RollingFile>
    </Appenders>
    <Loggers>
        <!-- 用来单独指定日志的形式,比如要为指定包下的 class 指定不同的日志级别等。 -->
        <!--<Logger name="com.easyjijin.demo.springbootlog4j2" level="debug" additivity="false">
            <AppenderRef ref="ConsoleAppender" />
            <AppenderRef ref="FileAppender"/>
        </Logger>-->
    <span class="hljs-comment">&lt;!-- AsyncRoot - 异步记录日志 - 需要LMAXDisruptor的支持 --&gt;</span>
    <span class="hljs-comment">&lt;!-- &lt;AsyncRootlevel="info" additivity="false"&gt;
      &lt;AppenderRef ref="Console"/&gt;
      &lt;AppenderRef ref="FileAppender"/&gt;
    &lt;/AsyncRoot&gt; --&gt;</span>

    <span class="hljs-comment">&lt;!-- All &lt; Trace &lt; Debug &lt; Info &lt; Warn &lt; Error &lt; Fatal &lt; OFF. --&gt;</span>

     <!-- 程序会打印高于或等于所设置级别的日志,设置的日志等级越高,打印出来的日志就越少。-->
<!-- 此 level 设置的日志级别,是过滤项目中输出的日志信息,和 ThresholdFilter 的 level 有所区别 -->
<Root level="ERROR">
<AppenderRef ref="ConsoleAppender" />
<AppenderRef ref="FileAppender"/>
</Root>
</Loggers>
</Configuration>

这边需要注意几个日志的级别:

  • Configuration status="OFF":这个status配置的是,Log4j2 组件本身日志级别,指的是如果 Log4j2 本身出错,打印出的日志级别配置。
  • Root level="ERROR":这个level配置的是,程序输入的日志级别,对应log.error("this is a error"),程序会打印高于或等于所设置级别的日志。
  • ThresholdFilter level="ERROR":这个level配置的是,输出到日志文件(或是其他)的日志日志级别,也就是在日志文件只输出ERROR级别的日志,其他无关信息不输出。

在程序中使用 Log4j2 打印日志信息:

@SpringBootApplication
public class Log4j2DemoApplication implements ApplicationRunner {
    private static final Logger logger = LogManager.getLogger(Log4j2DemoApplication.class);
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> {
    SpringApplication.run(Log4j2DemoApplication.class, args);
}

<span class="hljs-meta">@Override</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">run</span><span class="hljs-params">(ApplicationArguments applicationArguments)</span> <span class="hljs-keyword">throws</span> Exception {
    logger.debug(<span class="hljs-string">"Debugging log"</span>);
    logger.info(<span class="hljs-string">"Info log"</span>);
    logger.warn(<span class="hljs-string">"Hey, This is a warning!"</span>);
    logger.error(<span class="hljs-string">"Oops! We have an Error. OK"</span>);
    logger.fatal(<span class="hljs-string">"Damn! Fatal error. Please fix me."</span>);
}

}

或者使用Lombok,可以更方便的使用 Log4j2,需要添加依赖:

<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
</dependency>

使用代码:

import lombok.extern.log4j.Log4j2;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Log4j2
@RestController
public class HelloController {

<span class="hljs-meta">@RequestMapping("/home")</span>
<span class="hljs-keyword">public</span> String <span class="hljs-title function_">home</span><span class="hljs-params">()</span> {

    log.error(<span class="hljs-string">"Hi ! We have an Error. Hello World"</span>);

    <span class="hljs-keyword">return</span> <span class="hljs-string">"Hello World ----spring-boot-log4j2"</span>;
}

}

注意:如果 IDEA 报错(找不到log),IDEA 设置中添加 Lombok 插件,即可。

参考资料: