Log4j2抽丝剥茧之入门及进阶

本文最后更新于2019年12月26日,可能由于时间等因素导致内容失效,请自行辨别或联系作者。

一、前言

目前公司主要是通过日志组件+企业微信的形式,实现业务报警监控,刚入职的那会儿,师傅让我在已有的扩展上,再去扩展一些新的功能,测试相关兼容性,让我研究一下Log4j2,于是,在拖了将近一个月之后,这篇文章终于诞生了。

本篇文章需要你有一定的JavaWeb开发经验,并不会从零开始集成,在看这篇文章之前,你可以先搜索:Springboot集成Log4j2,进行前置学习和准备。

二、Log4j2是什么

Log4j2是一个日志框架,也许你还听说过LogBack,那为什么我会选择用Log4j2呢,原因很简单,正是因为它比LogBack更强大,我们来简单看一下Log4j2的有点,我挑几点列举一下:

Log4j 2 contains next-generation Asynchronous Loggers based on the LMAX Disruptor library. In multi-threaded scenarios Asynchronous Loggers have 10 times higher throughput and orders of magnitude lower latency than Log4j 1.x and Logback.

Log4j 2 uses a Plugin system that makes it extremely easy to extend the framework by adding new Appenders, Filters, Layouts, Lookups, and Pattern Converters without requiring any changes to Log4j.

Many Logback Appenders do not accept a Layout and will only send data in a fixed format. Most Log4j 2 Appenders accept a Layout, allowing the data to be transported in any format desired.

具体的比较,在这就不展开了,以上三点可以概括为:强大的性能、友好的扩展、丰富的布局。

三、Log4j2有什么用

准确来说,是日志框架有什么用。如果我没记错的话,在学校的学习中,老师是根本不会讲这个东西的,但是在实际工作中,你所参与的每个项目,必定会用到日志框架。

日记,是对过去的总结和记录,日志,也是如此,可以在任何你需要记录的位置,记录下程序曾今运行的状态,比如:什么时候调用了什么方法、某个方法返回了哪些参数等等。甚至还可以通过扩展,实现当你的程序有错误时,结合微信,推送至你的微信上。

四、Log4j2配置的主要结构

如果你已经在生产环境中使用了,可能网上随便找个配置,看一下,随手一改就完事了,并不会仔细去看每个标签其中的含义和关联,所以这也是我写这篇文章的目的之一,下面我会根据上图的序号,来讲解一下大概的含义、用法和注意事项。

按照国际惯例,我还是贴一下本次示例的配置代码,跟我实际使用的差不多。

<?xml version="1.0" encoding="UTF-8"?>
<configuration status="WARN" monitorInterval="30">
    <Properties>
        <Property name="APP">your name</Property>
        <Property name="SPLIT_SIZE">100 MB</Property>
        <Property name="LOG_FILE_PATH">./logs</Property>
    </Properties>

    <appenders><!--详细见下文①-->
        <!--输出控制台的配置-->
        <console name="Console" target="SYSTEM_OUT">
            <!--输出日志的格式-->
            <PatternLayout pattern="%date %-5level[%thread]%logger{56}:%L-%msg%n"/><!--详细见下文③-->
        </console>

        <!-- base日志文件配置 -->
        <RollingFile name="BaseFileInfo" fileName="${LOG_FILE_PATH}/${APP}-base.${date:yyyy-MM-dd}.log"
                     filePattern="${LOG_FILE_PATH}/${APP}-base.%d{yyyy-MM-dd}.%i.log">
            <PatternLayout pattern="%date %-5level[%thread]%logger{56}:%L-%msg%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="${SPLIT_SIZE}"/>
            </Policies>
            <Filters><!--详细见下文④-->
                <!-- 只记录info和warn级别信息 -->
                <ThresholdFilter level="error" onMatch="DENY" onMismatch="NEUTRAL"/>
                <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
            <DefaultRolloverStrategy max="10"/>
        </RollingFile>

        <!-- Error级别日志文件配置 -->
        <RollingFile name="RollingFileError" fileName="${LOG_FILE_PATH}/${APP}-error.${date:yyyy-MM-dd}.log"
                     filePattern="${LOG_FILE_PATH}/${APP}-error.%d{yyyy-MM-dd}.%i.log">
            <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="%date %-5level[%thread]%logger{56}:%L-%msg%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="${SPLIT_SIZE}"/>
            </Policies>
            <DefaultRolloverStrategy max="10"/>
        </RollingFile>

        <!--   接入企业微信     -->
        <!--   注意:此处是公司自定义的Appender     -->
        <WX name="Wx" projectName="测试业务" businessId="testBusinessId" md5Key="testSalt" domain="xxx.xxx.xxx.xxx" receivers="xxxx@xxxx.xxxx" countNums="1,5,10">

        </WX>
    </appenders>

    <loggers><!--详细见下文⑥-->
        <!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
        <logger name="org.springframework" level="INFO"></logger>
        <logger name="org.mybatis" level="INFO"></logger>
        <root level="INFO">
            <appender-ref ref="Console"/>
            <appender-ref ref="BaseFileInfo"/>
            <appender-ref ref="RollingFileError"/>
            <appender-ref ref="Wx"/>
        </root>
    </loggers>
</configuration>

五、①Appenders

Appenders 主要负责将事件传递到目的地,官方提供了非常多的输出方式(如下图),最常见的就是通过log文件的方式进行输出和保存。此外,还可以传输到消息队列、数据库等。具体使用可看官方文档:https://logging.apache.org/log4j/2.x/manual/appenders.html

六、③Layout布局

Layout是Appender用来格式化日志事件并组织有用信息的工具。下图列举了一些主要的Layout,具体使用可看官方文档:https://logging.apache.org/log4j/2.x/manual/layouts.html

七、④Filter过滤器

过滤器的作用就是,当事件达到了一个怎样的条件时,进行输出。下方列举了三个常用的Filter,过滤器之间可以组合使用,具体使用可看官方文档:https://logging.apache.org/log4j/2.x/manual/filters.html

八、自定义Appender

虽然官方提供了多种Appender,但是总会有涉及不到的地方,比如一开始我举的例子,这个时候,我们就可以按照官方提供的扩展方法,实现我们自定义的Appender。官方列举了一个简单的例子(见下图):https://logging.apache.org/log4j/2.x/manual/extending.html#Appenders

对照上图的注释,应该很容易理解官方的示例了。下面我贴一下公司这块的代码,当然,敏感操作我会删去。

如上图所示,整体结构跟官方给出的一致,定义好名字,继承抽象的Appender,重写append方法。值得注意的是,目前我们只定义了一个Appender,并没有实现自定义的Filter,所以,每产生一个LogEvent,都会调用一次append方法,故具体的过滤逻辑以及本例中的推送逻辑,在append方法中实现即可。

九、自定义Filter

官方提供的例子(见下图):https://logging.apache.org/log4j/2.x/manual/extending.html#Filters

看完上图的例子,是不是感觉在哪见过这种思路?这其实就是官方ThresholdFilter的源码。下面我贴一下公司这块的代码,当然,敏感操作我同样会删去。

十、主要参考

官方手册:https://logging.apache.org/log4j/2.x/manual/

中文版:https://www.docs4dev.com/docs/zh/log4j2/2.x/all/manual-index.html#%E6%89%8B%E5%86%8C

十一、进阶

Log4j2抽丝剥茧之源码分析

十二、总结

当我把自定义扩展这块看完,并且大概弄懂之后,真心觉得Log4j2太棒了!更何况我还没有涉及到异步以及深入学习源码。网上对于自定义这块的教程来说,非常少,也没有真正用于生产的代码。对我来说,一开始对于英文文档真的看不下去,所以会想方设法找中文翻译版,但是等我看中文文档之后,我发现有些翻译还是需要回到原版才能更好的理解,索性直接看原版了,到现在,也能够静下心来好好看下去了。对于自定义的使用,对我的帮助非常大,我会在随后的毕设中进行使用。

为TA充电
共{{data.count}}人
人已赞赏
Java编程语言

Springboot WebSocket 入门及源码

2019-11-26 21:17:28

Java编程语言

Sharding-JDBC踩坑记

2019-12-27 22:18:38

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
今日签到
有新私信 私信列表
搜索