您的当前位置:首页正文

springboot 日志管理之 log4j2

2024-11-25 来源:个人技术集锦
1、log4j2 简介

        Apache Log4j2是对Log4j的升级,它比其前身Log4j 1.x提供了重大改进,并提供了Logback中可用的许多改进,同时修复了Logback架构中的一些问题。被誉为是目前最优秀的Java日志框架。

2、项中引入 log4j2 的方式
2.1、springboot 项目中
<!-- spring-boot-starter 默认引入logback 需要排除 -->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter</artifactId>
   <exclusions><!-- SpringBoot 默认携带自身的 log 日志功能,去掉默认配置 -->
      <exclusion>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-logging</artifactId>
      </exclusion>
   </exclusions>
</dependency>

<!-- 引入 log4j2 依赖 -->
<dependency> 
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
2.2、普通 java 项目中
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.6.2</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.6.2</version>
</dependency>
<!---------------log4j与slf4j集成----------------->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.21</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.6.2</version>
</dependency>
3、在项目中指定 log4j2 的配置文件
logging:
  config: classpath:my_log4j2.xml
4、log4j2 配置文件详解
4.1、configuration 标签
<configuration status="WARN" monitorInterval="30">
status:记录到控制台的内部Log4j事件的级别。此属性的有效值为 trace, debug, info, warn, error, fatal”。

monitorInterval: 从文件配置后,Log4j能够自动检测对配置文件的更改并自行重新配置。以便仅在至少30秒之后检查配置文件的更改。默认为5秒。
4.2、Properties 标签

        Properties 标签定义全局属性,name属性必须存在且唯一,允许使用${name}来引用该变量。

<Properties>
    <Property name="LOG_HOME">../logs/xxx</Property>
</Properties>
4.3、Appenders 标签
4.3.1、日志输出到控制台(Console 标签)

有几个参数:

name:指定Appender的名字;

target:SYSTEM_OUT 或 SYSTEM_ERR,一般只设置默认:SYSTEM_OUT;

PatternLayout:输出格式,不设置默认为:%m%n。

<!--Console:日志输出到控制台标准输出 -->
<Console name="Console" target="SYSTEM_OUT">
<!-- 添加过滤器,只接受程序中DEBUG级别的日志进行处理-->
  <ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/>
<!--pattern:日期,线程名,日志级别,日志名称,日志信息,换行 -->
  <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level [%L] - %msg%n" />
</Console>
4.3.2、日志输出到文件(File 标签)

有以下几个参数:

name:指定Appender的名字;

fileName:指定输出日志的目的文件带全路径的文件名;

append:是否追加,默认为

PatternLayout:输出格式,不设置默认为:%m%n。

<File name="log" fileName="log/test.log" append="false">
   <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
</File>
4.3.3、滚动日志输出到文件(RollingFile 标签)

有以下几个参数:

name:指定Appender的名字。

fileName:指定输出日志的目的文件带全路径的文件名。

PatternLayout:输出格式,不设置默认为:%m%n。

filePattern:指定新建日志文件的名称格式。

Policies:指定滚动日志的策略,就是什么时候进行新建日志文件输出日志。

   TimeBasedTriggeringPolicy:Policies 子节点,基于时间的滚动策略,interval 属性用来指定多久滚动一次,默认是 1 小时。modulate=true用来对备份日志的生成时间纠偏,纠偏以0为基准进行,"0+interval"决定启动后第一次备份时间;

   SizeBasedTriggeringPolicy:Policies 子节点,基于指定文件大小的滚动策略,size 属性用来定义每个日志文件的大小;

   DefaultRolloverStrategy:用来指定同一个文件夹下最多有几个日志文件时开始删除最旧的,创建新的(通过 max 属性)。

<!--RollingFile:日志输出到文件,下面的文件都使用相对路径 -->
<!--fileName:当前日志输出的文件名称 -->
<!--filePattern:备份日志文件名称,备份目录为logs下面以年月命名的目录,备份时使用gz格式压缩 -->
<RollingFile name="RollingFile" fileName="${LOG_HOME}/${FILE_NAME}.log"
   filePattern="${LOG_HOME}/$${date:yyyy-MM}/${FILE_NAME}-%d{yyyy-MM-dd}-%i.log.gz">
   <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level [%L] - %msg%n" />
       <!--Policies:触发策略决定何时执行备份 -->
   <Policies>
       <!--TimeBasedTriggeringPolicy:日志文件按照时间备份 -->
       <!--interval:每1天生成一个新文件,时间单位需要结合filePattern时间%d{yyyy-MM-dd} -->
       <!--同理,如果要每1小时生成一个新文件,则改成%d{yyyy-MM-ddHH} -->
<!--modulate:对备份日志的生成时间纠偏,纠偏以0为基准进行,"0+interval"决定启动后第一次备份时间 -->
       <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
       <!--SizeBasedTriggeringPolicy:日志文件按照大小备份 -->
       <!--size:指定日志文件最大为100MB,单位可以为KB、MB或GB -->
       <SizeBasedTriggeringPolicy size="100MB"/>
    </Policies>
    <!-- DefaultRolloverStrategy:翻转策略决定如何执行备份 -->
<!--max:最多保存5个备份文件,结合时间使用后,在每个时间段内最多有5个备份,多出来的会被覆盖 -->
    <!-- compressionLevel:配置日志压缩级别,范围0-9,0不压缩,1压缩速度最快,9压缩率最好,目前只对于zip压缩文件类型有效 -->
    <DefaultRolloverStrategy max="5" compressionLevel="1">
        <!--Delete: 删除匹配到的过期备份文件 -->
        <!--maxDepth: 由于备份文件保存在${LOG_HOME}/$${date:yyyy-MM},所以目录深度设置为2 -->
        <Delete basePath="${LOG_HOME}" maxDepth="2">
            <!--IfFileName:匹配文件名称 -->
            <!--glob:匹配2级目录深度下的以.log.gz结尾的备份文件 -->
            <IfFileName glob="*/*.log.gz" />
            <!--IfLastModified:匹配文件修改时间 -->
            <!--age:匹配超过180天的文件,单位D、H、M、S分别表示天、小时、分钟、秒-->
            <IfLastModified age="180D" />
        </Delete>
    </DefaultRolloverStrategy>
</RollingFile>
4.4、loggers 节点

        常见的有两种:Root 和 Logger。

4.4.1、root 标签

        Root 节点用来指定项目的根日志,如果没有单独指定 Logger,那么就会默认使用该 Root 日志输出。

  level:日志输出级别;

  AppenderRef:Root 的子节点,用来指定该日志输出到哪个 Appender。

4.4.2、logger 标签

        Logger 节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。

        level:日志输出级别;

        name:用来指定该 Logger 所适用的类或者类所在的包全路径,继承自Root节点;        

        AppenderRef:Logger 的子节点,用来指定该日志输出到哪个 Appender,如果没有指定,就会默认继承自 Root。如果指定了,那么会在指定的这个 Appender 和 Root 的 Appender 中都会输出,此时我们可以设置 Logger 的 additivity="false" 只在自定义的 Appender 中进行输出。

4.5、Filter 标签

         允许在以下四个位置中指定过滤器:由全局到局部依次是 configuration,Logger ,Appender ,Appender Reference。注意:全局 Filter 标签 Filters 放在 properties 标签之后。

常用的 filter:

1)、CompositeFilter : 组合模式,用以向外界提供统一的访问接口。
2)、ThresholdFilter : 这个Filter负责按照所配置的日志级别过滤日志,等于或超出所配置级别的日志将返回onMatch结果。
3)、 LevelRangeFilter : 这个Filter也是负责按照日志级别过滤日志,只是相比较于ThresholdFilter,它比较的是指定区间范围。这里有一个需要密切注意就是其两个参数minLevel,maxLevel的配置;如果想要只保留WARN到ERROR级别的日志,那么应该如下配置:

<!-- 危险级别高的等级配置 作为minLevel的值 -->
<LevelRangeFilter minLevel="ERROR" maxLevel="WARN" onMatch="ACCEPT">
</LevelRangeFilter>

4)、 DynamicThresholdFilter :这个Filter允许依据ThreadContext中是否存在特定的某些值,以及日志级别来过滤LOG。
 

<Configuration status="TRACE" monitorInterval="5" packages="com.kanq.extend.cat.log4j2">
   <Filters>
   <!-- 全局级别Filter -->
   <LevelRangeFilter minLevel="DEBUG" maxLevel="ERROR" onMatch="DENY"></LevelRangeFilter>
   </Filters>
  <Appenders>
    <RollingFile name="RollingFile" fileName="logs/app.log"
                 filePattern="logs/app-%d{MM-dd-yyyy}.log.gz">
      <!-- Appender级别的Filter -->
      <BurstFilter level="INFO" rate="16" maxBurst="100"/>
      <PatternLayout>
        <pattern>%d %p %c{1.} [%t] %m%n</pattern>
      </PatternLayout>
      <TimeBasedTriggeringPolicy />
    </RollingFile>
  </Appenders>    
  <Loggers>
     <!-- Logger级别的Filter -->
    <Root level="error">
      <MapFilter onMatch="ACCEPT" onMismatch="NEUTRAL" operator="or">
        <KeyValuePair key="eventId" value="Login"/>
        <KeyValuePair key="eventId" value="Logout"/>
      </MapFilter>
    </Root>
    <Logger name="TestJavaScriptFilter" level="trace" additivity="false">
       <!-- AppenderRef级别的Filter -->
      <AppenderRef ref="List">
        <ScriptFilter onMatch="ACCEPT" onMisMatch="DENY">
          <ScriptRef ref="filter.js" />
        </ScriptFilter>
      </AppenderRef>
    </Logger>
  </Loggers>
</Configuration>
4.6、指定使用的激活环境

        在某个 appender 上添加 SpringProfile 标签,设置使用当前 appender 的激活环境。

<SpringProfile name="dev | staging">
   <Console name="Out">
      <PatternLayout pattern="%m%n"/>
   </Console>
</SpringProfile>
5、log4j2-spring.xml 文件
<?xml version="1.0" encoding="UTF-8" ?>
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration status="debug"  monitorInterval="5">
    <!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
    <!--变量配置-->
    <Properties>
    <!-- 格式化输出:%date表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %msg:日志消息,%n是换行符-->
        <!-- %logger{36} 表示 Logger 名字最长36个字符
        %date{YYYY:MM:dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} %l - %msg%n -->
        <property name="LOG_PATTERN" value="%date{YYYY:MM:dd HH:mm:ss.SSS} [%thread] %-5level %l -%M - %msg%n"/>
        <!-- 定义日志存储的路径 -->
        <property name="FILE_PATH" value="D:\logs"/>
    </Properties>

    <appenders>
        <!--控制台日志输出-->
        <console name="Console" target="SYSTEM_OUT">
            <!--运行日志输入文件-->
            <!--<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>-->
            <!--日志的格式-->
            <PatternLayout pattern="${LOG_PATTERN}"/>
           <!--控制台只输出level及其以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <!--控制台输出日志格式-->
<!--<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>-->
        </console>
       
        <!--
        debug 运行时异常日志信息
        -->
        <RollingFile name="debugJournal" fileName="${FILE_PATH}/堆栈日志.log"
                     filePattern="logs/$${date:yyyy-MM-dd}/debug-%d{yyyy-MM-dd}-%i.log">
            <!--文件只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
            <!--日志消息输出格式-->
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <!--日志拆分规则-->
            <Policies>
                <!--在系统启动时,生成一个新的日志文件-->
                <OnStartupTriggeringPolicy/>
                <!--interval属性用来指定多久滚动一次,默认是1 hour-->
                <TimeBasedTriggeringPolicy interval="0.001"/>
                <SizeBasedTriggeringPolicy size="10 Kb"/>
            </Policies>
       <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下10个文件开始覆盖-->
            <DefaultRolloverStrategy max="30"/>
        </RollingFile>
        <RollingFile name="infoJournal" fileName="${FILE_PATH}/运行日志.log"
                    filePattern="logs/$${date:yyyy-MM-dd}/run-%d{yyyy-MM-dd}-%i.log">
            <!--文件只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="fatal" onMatch="ACCEPT" onMismatch="DENY"/>
            <!--日志消息输出格式-->
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <!--日志拆分规则-->
            <Policies>
                <!--在系统启动时,生成一个新的日志文件-->
                <OnStartupTriggeringPolicy/>
                <!--interval属性用来指定多久滚动一次,默认是1 hour-->
                <TimeBasedTriggeringPolicy interval="0.001"/>
                <SizeBasedTriggeringPolicy size="10 KB"/>
            </Policies>
     <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下10个文件开始覆盖-->
            <DefaultRolloverStrategy max="30"/>
        </RollingFile>
    </appenders>
    <!--Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。-->
    <!--然后定义loggers,只有定义了logger并引入的appender,appender才会生效-->
    <loggers>
        <!--过滤掉spring和mybatis的一些无用的信息-->
        <logger name="org.mybatis" level="info" additivity="false">
            <AppenderRef ref="Console"/>
        </logger>
        <!--监控系统信息-->
<!--若是additivity设为false,则子Logger只会在自己的appender里输出,不会在父Logger里输出。-->
        <Logger name="org.springframework" level="info" additivity="false">
            <AppenderRef ref="Console"/>
        </Logger>

        <root level="info">
            <appender-ref ref="Console"/>
            <appender-ref ref="infoJournal"/>
            <appender-ref ref="debugJournal"/>
        </root>
    </loggers>
</configuration>
6、日志配置信息的符号解释
-X号 # X信息输出时左对齐;
 %p # 输出日志信息优先级,即DEBUG,INFO,WARN,ERROR,FATAL,
 %d # 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921
 %r # 输出自应用启动到输出该log信息耗费的毫秒数
 %c # 输出日志信息所属的类目,通常就是所在类的全名
 %t # 输出产生该日志事件的线程名
 %l # 输出日志事件的发生位置,相当于%C.%M(%F:%L)的组合,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main (TestLog4.java:10)
 %x # 输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。
 %% # 输出一个"%"字符
 %F # 输出日志消息产生时所在的文件名称
 %L # 输出代码中的行号
 %m # 输出代码中指定的消息,产生的日志具体信息
 %n # 输出一个回车换行符,Windows平台为"/r/n",Unix平台为"/n"输出日志信息换行

可以在%与模式字符之间加上修饰符来控制其最小宽度、最大宽度、和文本的对齐方式。如:
 1) %20c  # 指定输出全类名最小的宽度是20,如果全类名小于20的话,默认的情况下右对齐。
 2) %-20c # 指定输出全类名最小的宽度是20,如果全类名小于20的话,"-"号指定左对齐。
 3) %.30c # 指定输出全类名最小的宽度是30,如果全类名大于30的话,就会将左边多出的字符截掉,但小于30的话也不会有空格。
 4) %20.30c # 如果全类名小于20就补空格,并且右对齐,如果其名称长于30字符,就从左边较远输出的字符截掉

总结:log4j2 日志框架是基于 log4j 和 logback 的升级,是当前应用最为广泛的一种框架,以上详解足以完成开发需求,更加详细配置请参考:。

        本人是一个从小白自学计算机技术,对运维、后端、各种中间件技术、大数据等有一定的学习心得,想获取自学总结资料(pdf版本)或者希望共同学习,关注微信公众号:it自学社团。后台回复相应技术名称/技术点即可获得。(本人学习宗旨:学会了就要免费分享)

显示全文