Java日志框架LOG4J2的介绍和使用

前置知识: 日志门面SLF4J介绍和使用

推荐阅读: Java日志框架Logback介绍和使用

log4j2概述

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

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

Log4j2其实也是一个日志门面,但slf4j已经足够优秀,较少人把Log4j2用作日志门面,通常还是把它当成一个日志实现搭配slf4j使用。

log4j2日志门面

简要介绍一下log4j2作为日志门面的使用

maven依赖:

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

这样使用的就是Log4j2日志门面+本身的实现

public static final Logger LOGGER = LogManager.getLogger(LOG4J2Test.class);

@Test
public void testQuick() {
    LOGGER.fatal("fatal");
    LOGGER.error("error");
    LOGGER.warn("warn");
    LOGGER.info("info");
    LOGGER.debug("debug");
    LOGGER.trace("trace");
}

log4j2+slf4j使用

maven配置

<!-- slf4j日志门面 -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.30</version>
</dependency>
<!-- log4j2适配器 -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.13.0</version>
</dependency>
<!-- log4j2 -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.13.0</version>
</dependency>

这是最简单的写法,log4j-slf4j-impl依赖于log4j-api,它更像是桥接Log4j2日志门面。

使用就是SLF4J的使用方法(假设你没跳前置知识?)

log4j2配置

log4j2默认加载classpath下的log4j2.xml文件中的配置

它和logback实在是太像了,毕竟本来就是抄袭的logback(这是可以说的吗?)

logback的配置见Java日志框架Logback介绍和使用

所以我把配置贴出来应该就能看懂:

<?xml version="1.0" encoding="UTF-8"?>

<!-- status,代表日志框架本身的输出日志级别;monitorInterval,配置为120,单位为秒。类似于logback的scanPeriod -->
<Configuration status="WARN" monitorInterval="120">

    <!-- 类似于logback的property,但是放入了properties节点 -->
    <properties>
        <property name="LOG_HOME">/logs</property>
    </properties>

    <!-- 将所有Appender放入了Appenders节点 -->
    <Appenders>
        <!--Console节点就直接指定了这个appender使用的类是logback自带的,name是自己命名的,target=SYSTEM_OUT表示输出到控制台。-->
        <Console name="Console" target="SYSTEM_OUT">
            <!--pattern和logback几乎也没有区别-->
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] [%-5level] %c{36}:%L --- %m%n"/>
        </Console>

        <!--File节点就直接指定了这个appender使用的类是logback自带的,fileName指定文件路径,可以使用属性值${},append="true"追加到文件末尾-->
        <File name="log" fileName="${LOG_HOME}/test.log" append="true">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] [%-5level] %c{36}:%L --- %m%n"/>
        </File>

        <!--RandomAccessFile,文件随机读写流Appender,比File性能较好-->
        <RandomAccessFile name="log" fileName="${LOG_HOME}/test.log">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] [%-5level] %c{36}:%L --- %m%n"/>
        </RandomAccessFile>

        <!--RollingFile或使用RollingRandomAccessFile,自动拆分的文件随机读写流Appender, filePattern:历史日志封存路径。log4j2也自动识别zip等后缀,表示历史日志需要压缩。-->
        <RollingRandomAccessFile name="File" immediateFlush="true" fileName="${LOG_HOME}/today.log"
                                 filePattern="${LOG_HOME}/$${date:yyyy-MM-dd}/myrollog-%d{yyyy-MM-dd}-%i.log">
            <!-- 和logback的过滤器类似,onMatch、onMismatch可以为NEUTRAL表示中立 -->
            <Filters>
                <!-- 日志级别过滤器 -->
                <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>

            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] [%-5level] %c{36}:%L --- %m%n" />
            <!--
                也可以是类似于logback的HTMLLayout
                <HTMLLayout pattern="%d{HH:mm:ss.SSS}%t%-5level%c{36}%L%m%n" />
            -->

            <!--RollingRandomAccessFile的必配项,TriggeringPolicy(触发策略) -->
            <Policies>
                <!--在系统启动时,触发拆分规则,产生一个新的日志文件-->
                <OnStartupTriggeringPolicy />
                <!--按时间划分日志文件,单位是filePattern中配置的 -->
                <TimeBasedTriggeringPolicy />
                <!--按大小划分日志文件-->
                <SizeBasedTriggeringPolicy size="10 MB" />
            </Policies>

            <!--覆盖策略,限定同一个目录下日志文件的最大数量-->
            <DefaultRolloverStrategy max="20"/>
        </RollingRandomAccessFile>
    </Appenders>

    <!-- 配置Root Logger和自定义logger -->
    <Loggers>
        <Root level="trace">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>

</Configuration>

异步日志

Log4j2提供了AsyncAppender和AsyncLogger,通过BlockingQueue来实现异步。(比logback做的更全面一点)

通常使用AsyncLogger。

使用异步日志需要配置依赖:

<dependency>
    <groupId>com.lmax</groupId>
    <artifactId>disruptor</artifactId>
    <version>3.4.2</version>
</dependency>

使用AsyncAppender

这种方式和logback类似

<Appenders>
    <Async name="Async">
        <AppenderRef ref="file" />
    </Async>
</Appenders>

<Loggers>
    <Root level="trace">
        <AppenderRef ref="Console"/>
        <AppenderRef ref="Async"/>
    </Root>
</Loggers>

使用AsyncLogger

这种方法异步性能更高一点

全局异步

所有日志都异步,在配置文件上不用做任何改动,只需要添加一个log4j2.component.properties配置:

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

混合异步

可以在应用中同时使用同步日志和异步日志,这使得日志的配置方式更加灵活。

需要配置自定义logger:

<Loggers>
    <!-- includeLocation关闭文件信息、行号信息,这些信息影响性能 -->
    <AsyncLogger name="com.rhett.AsyncLogger" level="trace" includeLocation="false" additivity="false"> 
        <AppenderRef ref="file" />
    </AsyncLogger>
</Loggers>

原创文章,作者:彭晨涛,如若转载,请注明出处:https://www.codetool.top/article/java%e6%97%a5%e5%bf%97%e6%a1%86%e6%9e%b6log4j2%e7%9a%84%e4%bb%8b%e7%bb%8d%e5%92%8c%e4%bd%bf%e7%94%a8/

(0)
彭晨涛彭晨涛管理者
上一篇 2020年3月9日
下一篇 2020年3月10日

相关推荐

  • 为什么说Java只有值传递?

    先说一下。。以后可能不会怎么写Java相关的博客了,因为找到了字节跳动的实习工作,用Go/Python开发后端,所以这几天在抓紧时间学Go,在学Go的时候,了解到Go语言只有值传递…

    Java 2020年6月26日
    03100
  • JDK8新增高效原子累加器LongAdder源码分析

    很久以前写过CAS应用之JUC下的原子类,但是LongAdder这个类没有去看,只是给了一个其他博客的参考链接。今天就自己来分析一下。 AtomicLong的问题和LongAdde…

    2020年5月19日
    0740
  • Java8避免空指针异常Optional类的使用

    最近都是一天写一篇算法题解,好久没有写过博客了,不知道写啥了而且快到期末考试了。。 今天介绍一个Java8的特性:Optional类,这个类我平时也不咋用,今天来研究一下。 Opt…

    Java 2020年6月3日
    0660
  • 详解Java中的四种引用及其应用

    本文参考资源: 深入理解Java中的引用(一)——Reference - 简书 深入理解Java中的引用(二)——强软弱虚引用 - 简书 深入理解Java中的引用(三)——Dire…

    2020年2月14日
    0190
  • HashSet源码分析

    Set家族一览: HashSet简介 Set是Collection三大接口其中之一,意为集合,且元素不能重复。Set接口中的方法和Collection中的方法完全一致,只是起到一个…

    2019年12月2日
    0200
  • JUC包下的读写锁ReentrantReadWriteLock以及StampedLock

    ReentrantReadWriteLock 概述 当读操作远远高于写操作时,这时候使用 读写锁 让 读-读 可以并发,提高性能。 类似于数据库中的 select ... from…

    2020年2月5日
    0140
  • JDK8-Stream流库详解

    流提供了一种让我们可以在比集合更高的概念级别上指定计算的数据视图。通过使用流,我们可以说明想要完成什么任务,而不是说明如何去实现它。 流的创建 Collection.stream(…

    Java 2020年2月11日
    0150
  • 日志门面SLF4J介绍和使用

    SLF4j概述 上篇文章写了日志门面介绍和JCL使用,作为一个曾经的主流日志门面技术,JCL终究因为设计时的产生问题所限,导致至今已没什么人使用,而一款优秀的日志门面技术SLF4j…

    2020年3月9日
    01340
  • 基于NIO模型改进多人聊天室

    第一版和第二版见基于BIO模型实现多人聊天室 NIO介绍见: NIO、BIO模型对比实现文件的复制NIO网络编程之Selector介绍 第三版:使用NIO模型改进 服务端实现 pu…

    Java 2020年2月7日
    0190
  • CopyOnWriteArrayList源码分析

    总结 总结放前面防止太长不看 CopyOnWriteArrayList是一个线程安全、并且在读操作时无锁的List实现。 CopyOnWriteArrayList内部通过volat…

    Java 2020年2月15日
    0190

发表回复

登录后才能评论