Springboot中log4j2使用小结

说起Java中的日志组件,jcl(Jakarta Commons Logging)、jul(Java Util Logging)、log4j、slf4j、logback、log4j2这些耳熟能详组件。不得不提到一个人,那就是Ceki Gülcü这位大神,是log4j、slf4j、logback的作者。他冷酷无情的几乎包揽了整个Java的日志组件,努力改进日志记录器组件,连sun官方的日志组件方案jul也不得不甘拜下风。有兴趣可以看看《Java日志系统历史从入门到崩溃》一文。

好了,我感觉log4j2诞生是要终结和一统这一切,其实slf4j已经做到了。那么选择log4j2的理由是什么?那只能因为性能改进。在多线程方案中,与Log4j 1.x和Logback相比,异步Logger的吞吐量高18倍,延迟降低了几个数量级。请参见Log4j2异步日志记录性能

好了,在了解一点点背景和目标的后,我们本着“用就是了”的原则直奔主题。

注意,这里是在spring boot 框架下使用log4j2组件的常用配置。

引入log4j2依赖

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

排除log4j 1.x

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-logging</artifactId>
  <version>2.2.2.RELEASE</version>
  <exclusions>
    <exclusion>
      <groupId>*</groupId>
      <artifactId>*</artifactId>
    </exclusion>
  </exclusions>
</dependency>

注意log4j、slf4j、jcl的桥接器

因为很多其他组件绑定了各种的日志组件,所以配置桥接器是必要的,把不同日志统一接入log4j2的实现上来。

这个spring-boot-starter-log4j2已经配置好了,可以去pom里看一下:

<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-slf4j-impl</artifactId>
  <version>2.12.1</version>
  <scope>compile</scope>
</dependency>
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-core</artifactId>
  <version>2.12.1</version>
  <scope>compile</scope>
</dependency>
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-jul</artifactId>
  <version>2.12.1</version>
  <scope>compile</scope>
</dependency>
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>jul-to-slf4j</artifactId>
  <version>1.7.29</version>
  <scope>compile</scope>
</dependency>

配置文件

配置文件的名称叫log4j2.xml或者是log4j2-spring.xml都可以,一般放置在resources下。

如果使用其他位置或名称,在application.yml中指定一下即可:

logging:
  config: classpath:log4j2.xml

典型配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<Configuration monitorInterval="60">
    <!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
    <!--变量配置-->
    <properties>
      	<!-- 定义日志存储的默认路径,可用-Dlog.path参数覆盖 -->
        <property name="FILE_PATH" value="${sys:log.path:-/path/logs}"/>
        <property name="FILE_NAME" value="app_name"/>
        <!--输出日志的格式-->
        <!-- 格式化输出:%date表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %msg:日志消息,%n是换行符-->
        <!-- %logger{36} 表示 Logger 名字最长36个字符 -->
        <property name="LOG_PATTERN"
                  value="%date{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"/>
    </properties>
    <Appenders>
        <!-- 控制台日志,一般本地调试时开启 -->
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="${LOG_PATTERN}"/>
        </Console>
        <!--文件日志,会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,适合临时测试用-->
        <File name="Filelog" fileName="${FILE_PATH}/app_name.log" append="false">
          <PatternLayout pattern="${LOG_PATTERN}"/>
        </File>
      	<!-- 滚动日志,切分的日志如:${FILE_PATH}/info/2020-03-28/app_name-info-2020-03-28-23_1.log.gz -->
        <!-- 主日志文件位于:${FILE_PATH}/app_name-info.log --> 
        <!-- 这个会打印出info及高于其级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
      	<!-- 文件后缀配置为gz开启gzip压缩,配置为zip开启zip压缩,log后缀不压缩 -->
        <RollingFile name="RollingFileInfo" fileName="${FILE_PATH}/${FILE_NAME}-info.log"
                     filePattern="${FILE_PATH}/info/%d{yyyy-MM-dd}/${FILE_NAME}-info-%d{yyyy-MM-dd-HH}_%i.log.gz">
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
                <!-- interval属性用来指定滚动时间间隔 -->
              	<!-- 间隔单位由filePattern 中的时间模板最小单位决定,目前是1小时(HH) -->
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                <!-- size属性用来文件达到多大触发切分 -->
                <SizeBasedTriggeringPolicy size="1000MB"/>
            </Policies>
            <!-- DefaultRolloverStrategy 同一文件夹下多少个文件开始滚动覆盖,默认为7个 -->
            <!-- 对应于filePattern中的%i -->
            <DefaultRolloverStrategy max="100"/>
        </RollingFile>
        <!-- 滚动日志,切分的日志如:${FILE_PATH}/error/2020-03-28/app_name-error-2020-03-28_1.log.gz -->
      	<!-- 主日志文件位于:${FILE_PATH}/app_name-error.log -->
				<!-- 这个会打印出所有的error及高于其级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
        <RollingFile name="RollingFileError" fileName="${FILE_PATH}/${FILE_NAME}-error.log"
                     filePattern="${FILE_PATH}/error/%d{yyyy-MM-dd}/${FILE_NAME}-error-%d{yyyy-MM-dd}_%i.log.gz">
            <!--只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
              	<!-- 间隔单位由filePattern 中的时间模板最小单位决定,目前是1天(dd) -->
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                <SizeBasedTriggeringPolicy size="1000MB"/>
            </Policies>
            <DefaultRolloverStrategy max="100"/>
        </RollingFile>
    </Appenders>

    <Loggers>
        <Root level="INFO">
          	<!-- 节点可以PascalCase也可以是kebab-case,这里是演示,实际用时最好一致 -->
            <appender-ref ref="Console"/>
            <AppenderRef ref="RollingFileInfo"/>
            <AppenderRef ref="RollingFileError"/>
        </Root>
        <!-- 节点大小写都可以识别,这里是演示,实际用时最好一致 -->
        <!-- 开启mybatis包的DEBUG级别输出 -->
        <logger name="org.mybatis" level="debug" />
      	<!-- 关闭io.micrometer.elastic的所有日志输出 -->
        <Logger name="io.micrometer.elastic" level="OFF"/>
        <!-- 开启RocketmqClient的WARN级别输出到单独的文件 -->
        <!-- additivity设为false,则子Logger只会在自己的appender里输出,而不会在父Logger的appender里输出 -->
      	<Logger name="RocketmqClient" level="WARN" additivity="false">
            <AppenderRef ref="Filelog"/>
        </Logger>
    </Loggers>
</Configuration>

这里是收集整理了下常用配置,至于异步Appender以及各种特性未做收纳,可以研读下官方文档,非常详细。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值