log4j2的使用

Log4j2

概述

Apache Log4j 2是对Log4j的升级版,参考了logback的一些优秀的设计,并且修复了一些问题,因此带来了一些重大的提升,主要有:

  • 异常处理,在logback中,Appender中的异常不会被应用感知到,但是在log4j2中,提供了一些异常处理机制。
  • 性能提升, log4j2相较于log4j 和logback都具有很明显的性能提升,后面会有官方测试的数据。
  • 自动重载配置,参考了logback的设计,当然会提供自动刷新参数配置,最实用的就是我们在生产上可以动态的修改日志的级别而不需要重启应用。
  • 无垃圾机制,log4j2在大部分情况下,都可以使用其设计的一套无垃圾机制,避免频繁的日志收集导致的jvm gc。

官网https://logging.apache.org/log4j/2.x/

log4j2有自己的一套门面,也同时是一套实现。可以使用log4j2作为门面,然后使用log4j2作为实现。

但是目前使用最多的还是log4j2作为日志实现,因为log4j2的性能非常好,未来slf4j + log4j2是趋势,即项目使用slf4j作为日志门面,log4j2作为日志实现。

使用log4j2作为门面

目前市面上最主流的日志门面就是SLF4J,虽然Log4j2也是日志门面,因为Log4j2的日志实现功能非常强 大,性能优越。所以大家一般还是将Log4j2看作是日志的实现,Slf4j + Log4j2应该是未来的大势所趋。

image-20230528200425468

使用

  1. 导入依赖
<!-- Log4j2 门面API-->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.11.1</version>
</dependency>
<!-- Log4j2 日志实现 -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.11.1</version>
</dependency>
</dependencies>
  1. Java 代码

首先是获取Logger对象

private static Logger logger = LogManager.getLogger(xxx.class);

接下来直接使用即可,来演示一下没有配置文件的硬编码程序

Logger logger = LogManager.getLogger(testLog4j2.class);
logger.trace("我是TRACE级别的日志");
logger.debug("我是DEBUG级别的日志");
logger.info("我是INFO级别的日志");
logger.warn("我是WARN级别的日志");
logger.error("我是ERROR级别的日志");
logger.fatal("我是FATAL级别的日志");

这样运行之后,会看到只有error和fatal的日志信息输出出来了,Log4j2默认的日志级别是ERROR(因为缺省配置文件的优先级默认为Error)

日志级别

在Log4j2中,定义了6个日志级别

级别有小到大排序为:trace<debug<info<warn<error<fatal

  • trace: 程序追踪级别,一般不用
  • debug: 调试的日志信息,一般作为最低级别的日志信息使用
  • info: 输出一下你感兴趣的或者重要的信息,这个用的最多了。
  • warn: 警告日志信息,警告不是错误,程序依然能正常运行。
  • error: 错误信息,程序仍然会继续运行
  • fatal: 级别最高的日志信息,这种级别的日志应当终止停止程序了

日志级别只起信息一个标识作用,真正的处理需要视情况而定。

配置文件

log4j2的配置文件名称是log4j2.xml

<?xml version="1.0" encoding="UTF-8" ?>
<configuration status="warn" monitorInterval="5">

    <!--定义Log4j2的组件-->
    <Appenders>
        <!--        定义控制台输出的组件-->
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] [%-5level] %c{36}:%L --- %m%n"/>
        </Console>

        <!--        定义文件输出的组件-->
        <File name="file" fileName="D:/LOGS/myfile.log">
            <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l %c{36} - %m%n"/>
        </File>

        <!--        定义一个文件输出日志组件-->
        <RandomAccessFile name="accessFile" fileName="D:/LOGS/myAcclog.log">
            <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l %c{36} - %m%n"/>
        </RandomAccessFile>

        <!--        定义一个可滚动的文件输出日志组件-->
        <RollingFile name="rollingFile" fileName="D:/LOGS/myrollog.log"
                     filePattern="D:/LOGS/$${date:yyyy-MM-dd}/myrollog-%d{yyyy-MM-dd-HH-mm}-%i.log">
            <ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l %c{36} - %msg%n"/>
            <Policies>
                <OnStartupTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="10 MB"/>
                <TimeBasedTriggeringPolicy/>
            </Policies>
            <DefaultRolloverStrategy max="30"/>
        </RollingFile>

    </Appenders>

    <Loggers>
        <!--        设置日志级别是TRACE,等于以及高于此级别的日志才会输出-->
        <Root level="trace">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="file"/>
            <AppenderRef ref="accessFile"/>
            <AppenderRef ref="rollingFile"/>
        </Root>
    </Loggers>
</configuration>

导入配置文件后,再运行上面的测试程序,会看到控制台输出

image-20230105225942645

还可以看到文件日志

image-20230105230521216

image-20230105230523783

配置文件详解

参考文章:https://juejin.cn/post/6972538940855173151

Log4j 2.x版本不再支持像1.x中的.properties后缀的文件配置方式,2.x版本配置文件后缀名只能为".xml",“.json"或者”.jsn"。

常用的是XML格式的配置文件。

我们在日常开发中,使用XML类型的配置文件,注意log4j2的配置文件名必须是log4j2.xml

<configuration>

根标签,有两个属性,有两个子节点<Appenders><Loggers>

  • status,用来指定log4j本身的打印日志的级别,不是我们自定义的程序中的日志级别,是log4j本身日志的级别。
  • monitorInterval,用于指定log4j自动重新配置的检测间隔时间,单位是s,最小是5s。每隔几秒去检测配置文件是否更改,如果更改了就自动重新配置
<Appenders>

这个标签下放的都是日志组件,常见的有三种子节点

<Console>
  • 用来定义日志输出到控制台的组件标签
  • name属性,用来指定标签的名称,方便后面引用
  • target属性,用来指定控制台输出的方式,
    • SYSTEM_OUT是控制台常规输出
    • SYSTEM_ERR是控制台输出报错信息的一种方式,信息显示为红色
  • 子节点<PatternLayout>设置日志信息的输出格式,此标签中使用pattern属性来设置日志的打印格式,需要按照格式化符的规范。关于格式化符,可以看这篇文章https://blog.csdn.net/snail_bi/article/details/103496697
<File>
  • 此标签是用来定义日志文件输出的组件标签
  • name属性
  • fileName属性,设置日志文件的名称(日志文件的路径)
  • 子节点<PatternLayout>设置日志信息格式的标签,使用此标签中的pattern属性来格式化,按照格式化符的规范
<RollingFile>
  • 此标签用来定义滚动日志文件的标签,当日志文件超出某个规则后会自动创建新的日志文件,常用来限制日志文件的大小,当日志文件达到或超过某个大小,自动创建新的日志文件
  • name属性
  • fileName属性:用来指定日志文件名称(带路径名称)
  • filePattern属性:新建的日志文件的名称(带路径名称)
  • 子节点**<PatternLayout>标签**,设置日志信息的格式化
  • 子节点**<Policies>**,滚动日志的策略,当达到什么条件时新建日志文件
    • <Policies>子节点<TimeBasedTriggeringPolicy>标签,基于时间的滚动策略,interval属性用来指定多久滚动一次,默认是1h,modulate=true用来调整时间
    • <Policies>子节点<SizeBasedTriggeringPolicy>基于指定文件大小的滚动策略,size属性用来定义每个日志文件的大小
    • <Policies>子节点<OnStartupTriggeringPolicy>,每次重新启动时触发滚转,但仅当文件大小大于零时才触发。
  • 子节点<DefaultRolloverStrategy>用来指定同一个文件夹下最多有几个日志文件时开始删除最旧的,创建新的(通过max属性)
  • 子节点<ThresholdFilter>标签:level属性表示匹配的日志级别,onMatch属性表示匹配设定的日志级别后是DENY还是ACCEPT,onMismatch属性表示不匹配设定的日志级别是DENY还是ACCEPT还是NEUTRAL。DENY时就会不记录此日志,ACCEPT表示记录此日志,NEUTRAL表示中立。
<Loggers>

常见的子节点有两种:<Root><Logger>.

<Root>

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

  • level属性:设置项目的日志输出级别,共有8个级别,按照从低到高为:Trace < Debug < Info < Warn < Error < Fatal,ALL表示输出所有级别的日志信息都输出,OFF表示关闭项目日志输出功能。
<Logger>

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

  • level属性:日志输出级别,共有8个级别,按照从低到高为:Trace < Debug < Info < Warn < Error < Fatal,ALL表示输出所有级别的日志信息都输出,OFF表示关闭项目日志输出功能。
  • name:用来指定该Logger所适用的类或者类所在的包全路径,继承自Root节点.
<AppenderRef>
  • AppenderRef节点:Root或Logger的子节点,用来指定该日志输出引用哪一个自定义的Appender组件,如果没有指定,就会默认继承自Root。
完善的配置文件

一个比较完善的配置文件,用时直接拿来用

<?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>

Slf4j + log4j2

实际开发中,通常会使用 slf4j + log4j2 进行日志管理;

image-20230528200849400

此时就需要导入slf4j 日志门面、log4j2 适配器、log4j,然后使用 slf4j 方法接口名称来输出日志

<!-- 使用slf4j 作为日志门面 -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.26</version>
</dependency>

<!-- 使用 slf4j - log4j2 的桥接、适配器 -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.9.1</version>
</dependency>

<!-- Log4j2 门面API-->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.11.1</version>
</dependency>

<!-- Log4j2 日志实现 -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.11.1</version>
</dependency>

接下来的SLF4j是一个面向接口的框架,接下来我们在使用时,直接使用SLF4j的接口规范来调用,log4j2是真正底层的实现。

获取Logger对象,使用SLF4j中的工厂

private static final Logger LOGGER = LoggerFactory.getLogger(testSlf4Log4j2.class);

配置文件不用改,仍然是log4j2的配置文件

  private static final Logger LOGGER = LoggerFactory.getLogger(testSlf4Log4j2.class);

  @Test
  public void test(){
//        接下来正常使用即可
      LOGGER.trace("我是一条TRACE级别的日志信息");
      LOGGER.debug("我是一条DEBUG级别的日志信息");
      LOGGER.info("我是一条INFO级别的日志信息");
      LOGGER.warn("我是一条WARN级别的日志信息");
      LOGGER.error("我是一条ERROR级别的日志信息");
  }

image-20230105231534439

注意:引入了SLF4J门面后,所有的规范都是按照SLF4J来的,log4j2才是真正的实现,但是在调用时需要按照SLF4J的规范中的方法来调用,在SLF4J中,日志级别是5个,取消了log4j2中的FATAL级别

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值