学习log4j2的文件配置笔记

本文详细介绍了如何使用SLF4J和Log4j2进行日志配置,包括日志级别、Appender配置(Console、File、RollingFile)、过滤器的使用以及日志过滤策略。通过示例展示了如何设置不同级别的日志输出到不同的文件,并解释了配置文件中各个属性的作用。同时,文章讨论了为什么在代码中使用`getLogger(x.class)`的原因,强调了类与日志关联的重要性。

零、前言

最近做课设想到要用日志来打印输出,因此我想到了log4j2这一个日志实现,虽然这个日志最近爆出了大漏洞。我用的是slf4j作为门面,log4j2作为日志实现。这篇文章只是我简单的学了一下后记录的笔记,如果有错误可以在评论区指出,我看到的话就会修改。




一、配置文件节点解析

来源:https://www.cnblogs.com/hafiz/p/6170702.html

根节点Configuration,有两个属性:

  • status属性:用来指定log4j本身的打印日志的级别。(也就是log4j自身能输出的日志的级别)
    • 日志级别排序:<!-- 日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
  • monitorinterval属性:用于指定log4j自动重新配置的监测间隔时间,单位是s,最小是5s。(这一属性我没用过)

根节点Configuration内有两个节点:

  • Appenders节点:

    • 我的理解是,通过设置一个Appender节点,可以做到过滤,日志输出格式的工作,比如以下是我写的输出到控制台的一个Appender

      •     <Console name="Console" target="SYSTEM_OUT">
                <PatternLayout pattern="[%highlight{%p}{error=red}] [%d{yyyy-MM-dd HH:mm:ss a}]:%l [message] %m%n" />
                <!-- 注意, 这里的过滤不会影响到其它appender -->
                <Filters>
                    <ThresholdFilter level="INFO" onMatch="ACCEPT " onMismatch="DENY" />
                </Filters>
            </Console>
        
    • 常见的有三种子节点:ConsoleRollingFileFile

      • Console节点用来定义输出到控制台的Appender:

        • name属性:指定Appender的名字。

        • target属性:SYSTEM_OUT 或 SYSTEM_ERR,一般只设置默认:SYSTEM_OUT。

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

          • 以下来源https://blog.csdn.net/manmanxiaohui/article/details/79922546
          •     <!-- ========================== 自定义输出格式说明================================ -->
                  <!-- %p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL -->
                  <!-- %r 输出自应用启动到输出该log信息耗费的毫秒数  -->
                  <!-- %c 输出所属的类目,通常就是所在类的全名 -->
                  <!-- %t 输出产生该日志事件的线程名 -->
                  <!-- %m 表示要打印的日志信息 -->
                  <!-- %n 输出一个回车换行符,Windows平台为“/r/n”,Unix平台为“/n” -->
                  <!-- %d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921  -->
                  <!-- %l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。举例:Testlo4.main(TestLog4.java:10)  -->
                  <!-- ========================================================================== -->
            
      • File节点用来定义输出到指定位置的文件的Appender:

        • name属性:指定Appender的名字。
        • fileName属性:指定输出日志的目的文件带全路径的文件名。
        • PatternLayout节点:输出格式,不设置默认为:%m%n。
      • RollingFile节点用来定义超过指定大小自动删除旧的创建新的的Appender(这个我暂时没用上):

        • name属性:指定Appender的名字.

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

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

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

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

          • TimeBasedTriggeringPolicy节点:Policies子节点,基于时间的滚动策略,interval属性用来指定多久滚动一次,默认是1 hour。modulate=true用来调整时间:比如现在是早上3am,interval是4,那么第一次滚动是在4am,接着是8am,12am…而不是7am。

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

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

  • Loggers节点:

    • 常见的有两种:RootLogger
    • Root节点:
      • 用来指定项目的根日志,如果没有单独指定Logger,那么就会默认使用该Root日志输出。
      • level属性:日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF。
      • AppenderRef节点:Root的子节点,用来指定该日志输出到哪个Appender
    • Logger节点:
      • 用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。
      • level属性:日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF。
      • name属性:用来指定该Logger所适用的类或者类所在的包全路径,继承自Root节点。
      • AppenderRef节点:Logger的子节点,用来指定该日志输出到哪个Appender,如果没有指定,就会默认继承自Root。如果指定了,那么会在指定的这个AppenderRootAppender中都会输出,此时我们可以设置Loggeradditivity="false"只在自定义的Appender中进行输出。




二、日志过滤

来源:https://blog.csdn.net/qq_36066039/article/details/100584785?spm=1001.2101.3001.6650.3&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-3.pc_relevant_paycolumn_v2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-3.pc_relevant_paycolumn_v2&utm_relevant_index=6

  • 日志级别:

    • <!-- ALL < TRANCE < DEBUG < INFO < WARN < ERROR < FATAL < OFF-->
    • <ThresholdFilter level="INFO" onMatch="" onMismatch=""/>
      • onMatch:意思是当前级别以及以上要怎么处理:ACCEPT 接收, NEUTRAL 往后走 DENY拒绝
      • onMismatch:意思是当前级别(不包括当前级别)以下要怎么处理:ACCEPT 接收,NEUTRAL 往后走 DENY拒绝
      • (总结:onMatch 是 >= 当前级别 onMismatch 是< 当前级别)
  • 场景一:假如我们想要 INFO级别到ERROR级别之间的输出到控制台,其他的忽略,思路如下分析。

<!-- 经过分析也就是大于等于INFO级别的日志  往后走NEUTRAL进入下一个过滤器其他的拒绝 DENY。然后在下一个过滤器中,我让大于等于FATAL的拒绝DENY,小于的接受ACCEPT。-->
<Filters>
  <ThresholdFilter level="INFO" onMatch="NEUTRAL " onMismatch="DENY"/>
  <ThresholdFilter level="FATAL" onMatch="DENY" onMismatch="ACCEPT"/>
</Filters>

第二种方式实现:让小于FATAL的往后走,其他的拒绝,然后进入下一个过滤器。在下一个过滤器中,让大于等于INFO的接受其他的拒绝。

<Filters>
  <ThresholdFilter level="FATAL" onMatch="DENY" onMismatch="NEUTRAL"/>
  <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
  • 场景二:我需要info之后的日志,忽略掉比info级别小的日志。
    • 这个更简单,直接大于等于info的接受,小于的拒绝。
    • 大于等于:onMath=“ACCEPT” 小于的 onMismatch=“DENY”
<ThresholdFilter level="FATAL" onMatch="ACCEPT" onMismatch="DENY"/>

只要不是截取一个日志级别范围一个过滤器就够了,不需要流动NEUTRAL到第二个过滤器。只有在截取日志级别大于某个级别小于某个级别的时候,才需要两个过滤器。实现方式就是场景一描述的那样。看了这篇文章相信你能彻底掌握。

  • 总结一遍:不要刻意在意 ACCEPT NEUTRAL DENY这三个词的意思,理解的核心在于:onMatch 是匹配到当前级别以及大于当前级别的日志怎么怎么样。onMismatch是当前级别以下的日志不包含当前级别你要怎么处理。 无论是onMatch 还是onMismatch都有三个值。 是往后流动NEUTRAL 还是接受ACCEPT 或者是DENY。

  • 最后,完整的使用是将其加入到Appender下:

    •         <Console name="Console" target="SYSTEM_OUT">
                  <PatternLayout pattern="[%p] [%d{yyyy-MM-dd HH:mm:ss a}]:%l [message] %m%n" />
                  <!-- 注意, 这里的过滤不会影响到其它appender -->
                  <Filters>
                      <ThresholdFilter level="INFO" onMatch="ACCEPT " onMismatch="DENY" />
                  </Filters>
              </Console>
      

三、关于日志级别

来源:https://www.cnblogs.com/hafiz/p/6170702.html

关于日志level。共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF.

  • All:最低等级的,用于打开所有日志记录。
  • Trace:是追踪,就是程序推进以下,你就可以写个trace输出,所以trace应该会特别多,不过没关系,我们可以设置最低日志级别不让他输出。
  • Debug:指出细粒度信息事件对调试应用程序是非常有帮助的。
  • Info:消息在粗粒度级别上突出强调应用程序的运行过程。
  • Warn:输出警告及warn以下级别的日志。
  • Error:输出错误信息日志。
  • Fatal:输出每个严重的错误事件将会导致应用程序的退出的日志。
  • OFF:最高等级的,用于关闭所有日志记录。




四、我的配置

  • 我这里用了slf4j充当门面,然后用了log4j2作为实现:
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.17.1</version>
            <!-- <scope>test</scope> -->
        </dependency>
  • log4j的配置文件,我目前写的一个简单配置:
<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!-- Configuration后面的status, 这个用于设置log4j2自身内部的信息输出, 可以不设置, 当设置成trace时, 你会看到log4j2内部各种详细输出 -->
<Configuration status="OFF">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="[%p] [%d{yyyy-MM-dd HH:mm:ss a}]:%l [message] %m%n" />
            <!-- 注意, 这里的过滤不会影响到其它appender -->
            <Filters>
                <ThresholdFilter level="INFO" onMatch="ACCEPT " onMismatch="DENY" />
            </Filters>
        </Console>
        <!-- 输出到fileName文件的一个appender -->
        <File name="WarnFile" fileName="./src/main/java/com/jie/log/warn.log" append="true">
            <PatternLayout pattern="[%p] [%d{yyyy-MM-dd HH:mm:ss a}]:%l [message] %m%n" />
            <!-- 只接受warn -->
            <Filters>
                <!-- WARN及以上的走下一个过滤器, 以下的全部禁掉 -->
                <ThresholdFilter level="WARN" onMatch="NEUTRAL" onMismatch="DENY" />
                <!-- ERROR及以上的全部禁掉, 以下的全部放行 -->
                <ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="ACCEPT" />
            </Filters>
        </File>
        <File name="ErrorFile" fileName="./src/main/java/com/jie/log/error.log" append="true">
            <PatternLayout pattern="[%p] [%d{yyyy-MM-dd HH:mm:ss a}]:%l [message] %m%n" />
            <!-- 只接收error及以上 -->
            <Filters>
                <ThresholdFilter level="ERROR" onMatch="NEUTRAL" onMismatch="DENY" />
                <ThresholdFilter level="FATAL" onMatch="DENY" onMismatch="ACCEPT" />
            </Filters>
        </File>
    </Appenders>
    <Loggers>
        <!-- 默认的root的logger -->
        <!-- 这里的level是当前级别包括以上的用下面的appender -->
        <Root level="all">
            <!-- 输入到控制台的appender用下面这一个 -->
            <AppenderRef ref="Console" />
            <!-- 将warn输入到warn.log -->
            <AppenderRef ref="WarnFile" />
            <!-- 将error输入到error.log -->
            <AppenderRef ref="ErrorFile" />
        </Root>
    </Loggers>
</Configuration>
  • log4j2只支持xml格式。(log4j倒是支持properties格式)
  • 别人的配置,来源:https://www.cnblogs.com/hafiz/p/6170702.html:
<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration status="WARN" monitorInterval="30">
    <!--先定义所有的appender-->
    <appenders>
    <!--这个输出控制台的配置-->
        <console name="Console" target="SYSTEM_OUT">
        <!--输出日志的格式-->
            <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
        </console>
    <!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,这个也挺有用的,适合临时测试用-->
    <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>
    <!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
        <RollingFile name="RollingFileInfo" fileName="${sys:user.home}/logs/info.log"
                     filePattern="${sys:user.home}/logs/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log">
            <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->        
            <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="100 MB"/>
            </Policies>
        </RollingFile>
        <RollingFile name="RollingFileWarn" fileName="${sys:user.home}/logs/warn.log"
                     filePattern="${sys:user.home}/logs/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log">
            <ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="100 MB"/>
            </Policies>
        <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,这里设置了20 -->
            <DefaultRolloverStrategy max="20"/>
        </RollingFile>
        <RollingFile name="RollingFileError" fileName="${sys:user.home}/logs/error.log"
                     filePattern="${sys:user.home}/logs/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log">
            <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="100 MB"/>
            </Policies>
        </RollingFile>
    </appenders>
    <!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
    <loggers>
        <!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
        <logger name="org.springframework" level="INFO"></logger>
        <logger name="org.mybatis" level="INFO"></logger>
        <root level="all">
            <appender-ref ref="Console"/>
            <appender-ref ref="RollingFileInfo"/>
            <appender-ref ref="RollingFileWarn"/>
            <appender-ref ref="RollingFileError"/>
        </root>
    </loggers>
</configuration>




五、getLogger(x.class)的原因

  • 对于public static final Logger logger = LoggerFactory.getLogger(x.class);,我的建议是只在x里用这个logger,因为假设我在y类里用了这个logger,那么如果我想屏蔽x类的日志,我会顺便屏蔽掉y类的日志。

  • 比如如下例子:

    • public class ServerApplication {
      
          /**
           * 传入class是用于可以过滤这个类的日志
           */
          public static final Logger logger = LoggerFactory.getLogger(ServerApplication.class);
      
          public static void main(String[] args) {
              logger.info("服务器启动.");
              logger.info("服务器关闭.");
          }
      
      }
      
    • public class Other {
      
          private static final Logger logger = LoggerFactory.getLogger(Other.class);
      
          private static final Logger logger1 = LoggerFactory.getLogger(ServerApplication.class);
      
          public static void main(String[] args) {
              ServerApplication.logger.warn("哈哈哈1");
              logger1.warn("哈哈哈2");
              logger.warn("哈哈哈3");
          }
      
      }   
      
    •         <Logger name="com.jie.server.ServerApplication" level="ERROR" additivity="false">
                  <AppenderRef ref="Console" />
              </Logger>
      
  • 运行Other.main的结果:

    • [WARN] [2021-12-30 23:17:45 下午]:com.jie.server.Other.main(Other.java:19) [message] 哈哈哈3
      
  • 我只想屏蔽ServerApplication类的日志的error级别以下的输出,但是运行Other.main后,发现只输出了哈哈哈3,把Other类使用的ServerApplication类的logger的日志输出屏蔽了,因此我不太建议用别的类的Logger。

    • 不过这种方式可能也有其他用处,需要结合实际使用。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值