在spring boot应用中启用log4j2

1,012 阅读1分钟

在spring boot应用中启用log4j2

Spring boot的默认日志实现是使用的 Logback,默认日志级别是Info.

所以,最先一步就是排除掉spring boot带的日志实现.

      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-data-mongodb</artifactId>
          <exclusions>
              <exclusion>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-logging</artifactId>
              </exclusion>
          </exclusions>
      </dependency>

使用spring boot starter时,会自动引入spring-boot-starter-logging,其内容会包括:

  <dependencies>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.2.3</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-to-slf4j</artifactId>
      <version>2.13.3</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>jul-to-slf4j</artifactId>
      <version>1.7.30</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>

接着导入log4j 2的目标版本

      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-log4j2</artifactId>
          <version>2.3.4.RELEASE</version>
      </dependency>

日志配置

在classpath下配置一个名为log4j2.xml的配置文件,spring会检测到并导入.

也可以在application.yaml文件中指定:

logging:
  config: classpath:log4j2.xml

我的配置文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration monitorInterval="5">
    <!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
​
    <!--变量配置-->
    <Properties>
<!--         格式化输出:%date表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %m:日志消息,%n是换行符-->
<!--        %c 输出类详情 %M 输出方法名 %pid 输出pid  %line 日志在哪一行被打印 -->
        <!-- %logger{80} 表示 Logger 名字最长80个字符 -->
<!--        value="${LOCAL_IP_HOSTNAME} %date [%p] %C [%thread] pid:%pid line:%line %throwable %c{10} %m%n"/>-->
        <property name="LOG_PATTERN"
                  value="%highlight{%date [%-5p] [TD:%X{traceId}] %c{9.9./} %M [%thread] pid:%pid-%line %throwable %m  %n}{FATAL=red, ERROR=red, WARN=yellow,TRACE=blue}"/>
        <!--        读取application.yaml文件中设置的日志路径 logging.file.path-->
        <property name="FILE_PATH" value="${sys:LOG_PATH}"/>
        <property name="FILE_STORE_MAX" value="10MB"/>
        <property name="FILE_WRITE_INTERVAL" value="1"/>
        <property name="LOG_MAX_HISTORY" value="60"/>
        <!--        <property name="CONSOLE_LOG_PATTERN" value="%highlight{[%p] %-d{yyyy-MM-dd HH:mm:ss} &ndash;&gt; %l%n[message] %msg%n}{FATAL=red, ERROR=red, WARN=yellow, INFO=cyan, DEBUG=cyan,TRACE=blue}"/>-->
        <!--        value="%r [%t] %p %c %x - %m%n"/>&ndash;&gt;-->
        <property name="CONSOLE_LOG_PATTERN"
                  value="%highlight{%date [%-5p] [TD:%X{traceId}] %c{9.9./} %M [%thread] pid:%pid-%line %throwable %m  %n}{FATAL=red, ERROR=red, WARN=yellow,TRACE=blue}"/>
    </Properties>
​
    <appenders>
        <!--        <SMTP name="Mail" subject="Error Log" to="23333333@qq.com" from="666666@qq.com"-->
        <!--              smtpHost="smtp.qq.com"  smtpDebug="true" smtpProtocol="smtps" smtpUsername="666666@qq.com"-->
        <!--              smtpPassword="giyzthpqvzbhbber" smtpPort="465" bufferSize="50" >-->
        <!--        </SMTP>-->
​
        <!-- 控制台输出 -->
        <console name="Console" target="SYSTEM_OUT">
            <!--输出日志的格式-->
            <PatternLayout pattern="${CONSOLE_LOG_PATTERN}"/>
            <!--控制台只输出level及其以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
        </console>
​
        <!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
        <RollingRandomAccessFile name="RollingFileInfo" fileName="${FILE_PATH}/info.log"
                                 filePattern="${FILE_PATH}/INFO-%d{yyyy-MM-dd}_%i.log.gz">
            <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
                <!--interval属性用来指定多久滚动一次,默认是1 hour-->
                <TimeBasedTriggeringPolicy interval="${FILE_WRITE_INTERVAL}"/>
                <SizeBasedTriggeringPolicy size="${FILE_STORE_MAX}"/>
            </Policies>
            <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
            <DefaultRolloverStrategy max="${LOG_MAX_HISTORY}"/>
        </RollingRandomAccessFile>
​
        <!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
        <RollingRandomAccessFile name="RollingFileDebug" fileName="${FILE_PATH}/debug.log"
                                 filePattern="${FILE_PATH}/DEBUG-%d{yyyy-MM-dd}_%i.log.gz">
            <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
                <!--interval属性用来指定多久滚动一次,默认是1 hour-->
                <TimeBasedTriggeringPolicy interval="${FILE_WRITE_INTERVAL}"/>
                <SizeBasedTriggeringPolicy size="${FILE_STORE_MAX}"/>
            </Policies>
            <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
            <DefaultRolloverStrategy max="${LOG_MAX_HISTORY}"/>
        </RollingRandomAccessFile>
​
        <!-- 这个会打印出所有的warn及以上级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
        <RollingRandomAccessFile name="RollingFileWarn" fileName="${FILE_PATH}/warn.log"
                                 filePattern="${FILE_PATH}/WARN-%d{yyyy-MM-dd}_%i.log.gz">
            <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
                <!--interval属性用来指定多久滚动一次,默认是1 hour-->
                <TimeBasedTriggeringPolicy interval="${FILE_WRITE_INTERVAL}"/>
                <SizeBasedTriggeringPolicy size="${FILE_STORE_MAX}"/>
            </Policies>
            <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
            <DefaultRolloverStrategy max="${LOG_MAX_HISTORY}"/>
        </RollingRandomAccessFile>
​
        <!-- 这个会打印出所有的error及以上级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
        <RollingRandomAccessFile name="RollingFileError" fileName="${FILE_PATH}/error.log"
                                 filePattern="${FILE_PATH}/ERROR-%d{yyyy-MM-dd}_%i.log.gz">
            <!--只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
                <!--interval属性用来指定多久滚动一次,默认是1 hour-->
                <TimeBasedTriggeringPolicy interval="${FILE_WRITE_INTERVAL}"/>
                <SizeBasedTriggeringPolicy size="${FILE_STORE_MAX}"/>
            </Policies>
            <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
            <DefaultRolloverStrategy max="${LOG_MAX_HISTORY}"/>
        </RollingRandomAccessFile>
​
    </appenders>
​
    <!--Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。-->
    <!--然后定义loggers,只有定义了logger并引入的appender,appender才会生效-->
    <loggers>
​
        <!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
        <logger name="org.mybatis" level="info" additivity="false">
            <AppenderRef ref="Console"/>
        </logger>
        <!--监控系统信息-->
        <!--若是additivity设为false,则 子Logger 只会在自己的appender里输出,而不会在 父Logger 的appender里输出。-->
        <Logger name="org.springframework" level="info" additivity="false">
            <AppenderRef ref="Console"/>
        </Logger>
​
        <!--        <Logger name="mail" level="error" additivity="false">-->
        <!--            <AppenderRef ref="Mail"/>-->
        <!--        </Logger>-->
​
        <AsyncLogger name="AsyncLogger" level="debug" additivity="false">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="RollingFileDebug"/>
            <AppenderRef ref="RollingFileInfo"/>
            <AppenderRef ref="RollingFileWarn"/>
            <AppenderRef ref="RollingFileError"/>
        </AsyncLogger>
​
        <root level="trace">
            <appender-ref ref="Console"/>
            <appender-ref ref="RollingFileDebug"/>
            <appender-ref ref="RollingFileInfo"/>
            <appender-ref ref="RollingFileWarn"/>
            <appender-ref ref="RollingFileError"/>
            <!--            <appender-ref ref="Mail"/>-->
        </root>
    </loggers></configuration>

需要特别说明的一些点:

     <property name="CONSOLE_LOG_PATTERN"
                      value="%highlight{%date [%-5p] [TD:%X{traceId}] %c{9.9./} %M [%thread] pid:%pid-%line %throwable %m  %n}{FATAL=red, ERROR=red, WARN=yellow,TRACE=blue}"/>
        </Properties>
`%highlight{输出的内容}{FATAL=red, ERROR=red, WARN=yellow,TRACE=blue}`高亮输出,第二个大括号中指定不同级别日志的颜色.

更多详细的设置可以参考官网.

ps:颜色设置在windows平台上无法正常使用的情况:

在启动时加入参数-Dlog4j.skipJansi=false

IDEA中如下设置:

image.png

java -jar命令使用时:

   java -jar app.jar -Dlog4j.skipJansi=false

读取application.yml中的配置

    <property name="FILE_PATH" value="${sys:LOG_PATH}"/>

application.yml文件内容

    logging:
      config: classpath:log4j2.xml
      file:
        path: ${LOG_HOME_PATH:/logs/java}/${spring.application.name}

sys:LOG_PATH 的值即为${LOG_HOME_PATH:/logs/java}/${spring.application.name};

这样就可以让不同项目的日志根据项目名将日志存放在不同的地方.

通过Java应用的system property来设置和读取值

`sys:var`取值的方式其实是取的jvm的property.可以在代码中使用`System.setProperty(key,val)`设置,然后在log4j2.xml中使用

`sys:key`获取值.

效果

image.png