【Java日志系列】Log4j2日志框架

目录

前言

一、Log4j2简介与特征

二、快速入门

[三、SLF4j + Log4j2组合](#三、SLF4j + Log4j2组合)

四、配置文件

五、异步日志

[1. AsyncAppender方式](#1. AsyncAppender方式)

[2. AsyncLogger方式](#2. AsyncLogger方式)

总结


前言

在当今的软件开发领域中,日志记录是调试、监控和审计应用程序不可或缺的一部分。高效的日志记录不仅能帮助开发者理解程序的运行流程,还能在运行时出现问题时提供重要的线索。Apache Log4j 2 是一款广受欢迎的日志框架,它在 Log4j 1.x 的基础上进行了重大改进,并且相较于其他流行的框架如 Logback 也提供了更多的优化。本文旨在介绍 Log4j 2 的主要特点和如何使用它来增强应用程序的日志能力。

一、Log4j2简介与特征

Apache Log4j 2 是对Log4j的升级,它比其前身Log4j 1.x 提供了重大改进,并提供了Logback中可用的许多改进,同时秀修复了Logback架构中的一些问题。Log4j2包含如下特征:

  • 性能提升:Log4j2包含基于LMAX Disruptor库的下一代异步记录器。在多线程场景中,异步记录器的吞吐量比Log4j 1.x 和Logback高18倍,延迟低。
  • 自动重新加载配置:与Logback一样,Log4j2可以在修改时自动重新加载其配置。与Logback不同,它会在重新配置发生时不会丢失日志事件。
  • 高级过滤:与Logback一样,Log4j2支持基于Log事件中的上下文数据,标记,正则表达式和其他组件进行过滤。此外,过滤器还可以与记录器进行关联。与Logback不同,Log4j2可以在任何这些情况下使用通用的Filter类。
  • 插件架构:Log4j2使用插件模式配置组件。因此,无需编写代码来创建和配置Appender,Layout,Pattern Converter等。在配置了的情况下,Log4j自动识别插件并使用它们。
  • 无垃圾机制:在稳态日志记录期间,Log4j2在独立应用程序中是无垃圾的,在Web应用程序中是低垃圾。这减少了垃圾收集器的压力,并且可以提供过更好的相应性能。

二、快速入门

首先,我们需要导入Log4j2的依赖

XML 复制代码
<!-- log4j2日志门面 -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.23.1</version>
</dependency>
<!-- log4j2日志实现 -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.23.1</version>
</dependency>

Log4j2和Log4j提供了相同的日志级别输出,默认为Error级别的打印。快速入门的示例代码打印结果如下图所示:

三、SLF4j + Log4j2组合

为了实现SLF4j + Log4j2的组合,我们需要导入SLF4J日志门面的核心依赖以及桥接器,具体如下:

XML 复制代码
        <!-- slf4j日志门面核心依赖 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
        </dependency>
        <!-- 适配器 -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.12.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.12.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.12.1</version>
        </dependency>

在这里,使用适配器后,slf4j门面调用的实际上是log4j2的门面,再由log4j2门面调用log4j2的实现。 测试用例的打印效果如下图所示:

四、配置文件

Log4j2是参考Logback创作出来的,所以配置文件也是使用xml,Log4j2同样也是加载类路径(resources)下的log4j2.xml文件中的配置。下面是一个简单的控制台输出配置:

XML 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<Configuration>
   <Appenders>
       <Console name="consoleAppender" target="SYSTEM_ERR">

       </Console>
   </Appenders>

    <Loggers>
        <Root level="trace">
            <AppenderRef ref="consoleAppender" />
        </Root>
    </Loggers>
</Configuration>

根标签,所有日志相关信息,都是在根标签中进行配置,<Configuration> status="debug" ></Configuration>。在根标签中,可以加属性status="debug",表示日志框架本身的日志输出级别。monitorInterval="数值"表示自动加载配置文件的间隔时间。

此外,我们可能需要将日志输出到文件中,或者是根据文件的时间或者大小进行一个滚动,下面是对文件输出的相关配置示例:

XML 复制代码
 <properties>
       <property name="logDir">log</property>
</properties>

<Appenders>     

       <!-- 配置文件输出 -->
       <File name="fileAppender" fileName="${logDir}/log4j2.log">
           <PatternLayout pattern="%m%n"/>
       </File>

        <!--
        $${date:yyyy-MM-dd}:根据日期当天,创建一个文件夹
        rolling-%d{yyyy-MM-dd}-%i.log:%i表示序号,从0开始,目的是为了让每一份文件名不会重复
        -->
       <RollingFile name="rollingFile" fileName="${logDir}/rolling.log"
        filePattern="${logDir}/$${date:yyyy-MM-dd}/rolling-%d{yyyy-MM-dd}-%i.log">
           <PatternLayout pattern="%m%n"/>
           <Policies>
               <!-- 在系统启动时,触发拆分规则,产生一个日志文件 -->
               <OnStartupTriggeringPolicy />
               <!-- 按照文件的大小进行拆分 -->
               <SizeBasedTriggeringPolicy size="10KB" />
               <!-- 按时间节点进行拆分,拆分规则就是filePattern -->
               <TimeBasedTriggeringPolicy />
           </Policies>
           <!-- 在同一目录下,文件的个数限制,如果超出了设置的数值,则根据时间进行覆盖,新的覆盖旧的规则 -->
           <DefaultRolloverStrategy max="30" />
       </RollingFile>

 </Appenders>

有关文件输出等相关配置,更多的信息可以参考下面这篇博客:

一文搞定Log4j2日志配置文件_log4j2配置文件-CSDN博客

五、异步日志

异步日志是Log4j2最大的特色,其性能的提升主要也是从异步日志中受益。Log4j2提供了两种是心啊异步日志的方式,一个是通过AsyncAppender,一个是通过AsyncLogger,分别对应前面我们说的Appender组件和Logger组件。注意这是两种不同的实现方式,在设计和源码上都是不同的体现。

1. AsyncAppender方式

是通过引用别的Appender来是实现的,当有日志事件到达时,会开启另外一个线程来处理它们,需要注意的是,如果在Appender的时候出现异常,对应用来说是无法感知的。AsyncAppender应该在它引用的Appender之后配置,默认使用java.util.concurrent.ArrayBlockQueue实现而不需要其他外部的类库。当使用此Appender的时候,在多线程的环境下需要注意,阻塞队列容易受到锁争用的影响,这可能会对性能产生影响。这时候,我们应该考虑使用无锁的异步记录器(AsyncLogger)。

在使用AsyncAppender的时候,我们首先,需要导入异步日志的依赖:

XML 复制代码
<dependency>
    <groupId>com.lmax</groupId>
    <artifactId>disruptor</artifactId>
    <version>4.0.0</version>
</dependency>

接下来,在我们的Appender标签中,对我们的异步进行一个配置,下面是一个配置的示例:

XML 复制代码
<Appenders>
    <!-- 配置控制台输出 -->
    <Console name="consoleAppender" target="SYSTEM_ERR">

    </Console>

    <!-- 配置异步日志 -->
    <Async name="myAsync">
        <!-- 将控制台的输出做异步的操作 -->
        <AppenderRef ref="consoleAppender" />
    </Async>

</Appenders>

<Loggers>
    <Root level="trace">
       <AppenderRef ref="myAsync" />
     </Root>
</Loggers>

2. AsyncLogger方式

AsyncLogger才是Log4j2实现异步最重要的功能体现,也是官方推荐的异步方式。它可以使用调用Logger.log返回的更快。你可以有两种选择:全局异步和混合异步。

全局异步:所有的日志都异步的记录,在配置文件上不用做任何改动,只需要在resources目录下添加log4j2.component.properties文件,配置如下一行参数即可。

Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector

混合异步:你可以在应用中同时使用同步日志和异步日志,这使得日志的配置方式更加灵活。虽然Log4j2提供以一套异常处理机制,可以覆盖大部分的状态,但是还有一小部分的特殊情况是无法完全处理的,比如我们如果是记录审计日志(特殊情况之一),那么官方就推荐使用同步日志的方式,而对于其他的一些仅仅是记录一个程序日志的地方,使用异步日志将大幅提升性能,减少对应用本身的影响。混合异步的方式需要通过修改配置文件来实现,使用AsyncLogger标记配置。混合异步的配置示例:

XML 复制代码
<Loggers>

   <!--
       includeLocation="false"
       表示去除日志记录中的行号信息,这个行号信息非常的影响日志记录的效率,
       严重的时候可能记录的比同步的日志效率还要低。

       additivity="false"
       表示不继承rootLogger
   -->
        
   <!-- 自定义Logger,让自定义的Logger为异步Logger -->
   <AsyncLogger name="cn.sumou" level="trace"
           includeLocation="false" additivity="false">
         <AppenderRef ref="consoleAppender" />
   </AsyncLogger>

   <Root level="trace">
        <AppenderRef ref="consoleAppender" />
   </Root>
</Loggers>

有关不同的异步日志的性能分析,可以参考这篇博客:log4j2性能分析+原理_log4j2异步日志原理-CSDN博客

总结

我们展示了如何快速开始使用 Log4j 2,以及如何与 SLF4J 结合使用以实现更灵活的日志管理。此外,文章说明了如何配置日志输出至文件及实现日志滚动。最后,我们探讨了 Log4j 2 中异步日志的不同实现方式,包括 AsyncAppenderAsyncLogger。总之,Apache Log4j 2 是一个强大且高效的日志框架,适合不同规模的应用程序。

相关推荐
xlsw_2 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
神仙别闹3 小时前
基于java的改良版超级玛丽小游戏
java
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭3 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
暮湫4 小时前
泛型(2)
java
超爱吃士力架4 小时前
邀请逻辑
java·linux·后端
南宫生4 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
转码的小石4 小时前
12/21java基础
java
李小白664 小时前
Spring MVC(上)
java·spring·mvc
GoodStudyAndDayDayUp4 小时前
IDEA能够从mapper跳转到xml的插件
xml·java·intellij-idea
装不满的克莱因瓶5 小时前
【Redis经典面试题六】Redis的持久化机制是怎样的?
java·数据库·redis·持久化·aof·rdb