Log4j2原理及应用详解(四)

本系列文章简介:

        在软件开发过程中,日志记录是一个不可或缺的重要环节。它不仅帮助开发者在开发阶段追踪和调试代码,还在软件运行阶段提供了宝贵的运行信息和错误追踪能力。随着软件系统的日益复杂,对日志记录的需求也变得越来越高,包括日志的灵活性、性能、安全性以及可管理性等方面。

        Log4j2,作为Apache Log4j的继任者,自发布以来便以其卓越的性能、灵活的架构和丰富的功能赢得了广泛的认可和应用。它不仅继承了Log4j的优点,还在多个方面进行了重大的改进和优化,特别是在日志性能、配置灵活性、自动重载配置以及无垃圾内存管理等方面,为开发者提供了更加强大和便捷的日志记录解决方案。

        本系列文章旨在通过深入剖析Log4j2的内部原理、详细讲解其配置方法、展示高级特性的应用,以及探讨在实际项目中的集成与管理,帮助读者全面理解和掌握Log4j2。无论您是Java开发者、系统管理员,还是对日志记录技术感兴趣的爱好者,本系列文章都将为您提供宝贵的参考和指导。

        我们相信,通过本系列的学习,您将能够熟练掌握Log4j2的使用技巧,并在实际项目中灵活应用其各项功能,从而为您的软件开发和运维工作带来极大的便利和效益。同时,我们也期待与您一起探索更多关于日志记录技术的奥秘,共同推动软件行业的进步和发展。

        欢迎大家订阅《Java技术栈高级攻略》专栏(PS:近期会涨价),一起学习,一起涨分!

一、引言

        随着Logback的兴起,Log4j开始式微。为了应对这一挑战,Apache软件基金会决定开发Log4j的继任者——Log4j2。Log4j2不仅改进了Log4j的缺点,还借鉴了Logback的许多优点,号称在性能上完胜Logback。

        本文将跟随《Log4j2原理及应用详解(三)》的进度,继续介绍Log4j2。希望通过本系列文章的学习,您将能够更好地理解Log4j2的内部工作原理,掌握Log4j2的使用技巧,以及通过合理的设计完成最佳实践,充分发挥优化Log4j2的潜力,为系统的高效运行提供有力保障。

二、Log4j2原理

2.1 架构与组件

        详见《Log4j2原理及应用详解(二)​​​​​​​

2.2 启动过程

        详见《Log4j2原理及应用详解(三)

2.3 核心机制

2.3.1 日志级别与过滤

Log4j2作为Java日志框架的升级版本,其日志级别与过滤机制是其核心功能之一。以下是对Log4j2的日志级别与过滤原理的详细解释:

日志级别

Log4j2定义了多个日志级别,用于控制日志信息的输出。这些级别按照优先级从高到低排列,依次为:

  1. OFF:最高等级,用于关闭所有日志记录。
  2. FATAL:指出严重的错误事件,将会导致应用程序的退出。
  3. ERROR:指出虽然发生错误事件,但仍然不影响系统的继续运行。通常用于打印错误和异常信息。
  4. WARN:表明会出现潜在错误的情形,有些信息不是错误信息,但也要给程序员一些提示。
  5. INFO:突出强调应用程序的运行过程,打印一些你感兴趣的或者重要的信息。可用于生产环境中输出程序运行的一些重要信息,但不能滥用,避免打印过多的日志。
  6. DEBUG:该级别信息对调试应用程序是非常有帮助的,主要用于开发过程中打印一些运行信息。
  7. TRACE:很低的日志级别,一般不会使用,除非在需要极其详细的跟踪信息时。
  8. ALL:最低等级,用于打开所有日志记录。

日志级别的设置允许开发者根据需要在不同的环境下(如开发、测试、生产)输出不同级别的日志信息,从而帮助快速定位问题和优化程序性能。

过滤机制

Log4j2的过滤机制允许开发者根据日志的级别、源、线程等条件进行过滤,以决定是否记录日志。过滤机制在Log4j2中通过Filter组件实现,可以配置在多个层级上,包括全局、Logger、Appender等。

Filter的工作原理是基于日志事件的属性进行条件判断,然后根据判断结果决定是否允许该日志事件继续传递。Log4j2提供了多种内置的Filter实现,如ThresholdFilterLevelRangeFilterRegexFilter等,同时也支持自定义Filter。

在配置文件中,Filter可以配置在Appender或Logger上。当日志事件到达时,Log4j2会按照配置的Filter顺序进行过滤。如果某个Filter决定拒绝该日志事件,则后续的Filter和Appender将不再处理该事件。如果所有Filter都允许该事件,则最终会由Appender将其输出到指定的目的地。

总结

Log4j2的日志级别与过滤机制是其灵活性和强大功能的重要体现。通过合理设置日志级别和配置Filter,开发者可以精确地控制日志信息的输出,从而在开发、测试和生产环境中获得所需的日志信息,帮助快速定位问题和优化程序性能。

2.3.2 日志事件处理流程

Log4j2的日志事件处理流程是一个复杂但高效的过程,它涉及多个组件的协同工作。以下是根据Log4j2的官方文档和权威资料总结的日志事件处理流程:

1、日志事件的产生
  1. 日志请求:在应用程序中,开发者通过Logger实例的日志方法(如trace()、debug()、info()、warn()、error()、fatal())发起日志请求。这些日志请求包含了日志级别、日志消息以及可能的异常信息等内容。
2、日志事件的传递与过滤
  1. 日志级别的过滤:Log4j2首先会根据Logger实例的日志级别对日志请求进行过滤。只有日志级别高于或等于Logger实例设置的日志级别的日志请求才会被进一步处理;否则,该日志请求将被忽略。

  2. Appender的过滤(可选):如果Logger实例配置了Appender,并且Appender也设置了过滤器(Filter),则Log4j2还会根据Appender的过滤器对日志请求进行进一步过滤。过滤器的规则可以基于日志级别、日志消息内容、日志事件的属性等多种条件进行。

3、日志事件的格式化与输出
  1. 日志事件的格式化:通过过滤的日志请求将被传递给Appender进行格式化。Appender使用Layout组件来定义日志消息的格式。Layout可以包含日期、时间、日志级别、日志消息、异常堆栈等多种信息,并且可以自定义这些信息的显示方式和顺序。

  2. 日志事件的输出:格式化后的日志消息将被输出到Appender指定的目的地。Appender的目的地可以是控制台、文件、数据库、远程服务器等多种类型。根据Appender的配置,Log4j2可以将日志消息输出到单个或多个目的地。

4、日志文件的滚动与归档(对于文件Appender)
  1. 日志文件的滚动:对于将日志消息输出到文件的Appender(如FileAppender、RollingFileAppender等),Log4j2还提供了日志文件的滚动策略。当日志文件达到一定大小或时间条件时,Log4j2会自动将当前日志文件滚动(即关闭当前文件并创建新文件),以便继续记录新的日志消息。

  2. 日志文件的归档:滚动后的旧日志文件可以被归档到指定的位置,以便后续的分析和审计。归档策略可以根据文件大小、时间间隔等多种条件进行配置。

5、异常处理与性能优化
  1. 异常处理:在日志事件的处理过程中,如果发生异常(如文件无法写入、网络问题等),Log4j2会提供异常处理机制,以确保日志系统的稳定性和可靠性。

  2. 性能优化:Log4j2在设计时就考虑了性能优化问题。它采用了多种优化策略,如对象重用、内存缓冲等,以减少日志记录对应用程序性能的影响。

总结

Log4j2的日志事件处理流程是一个高效、灵活且可扩展的过程。它通过日志级别的过滤、Appender的过滤、日志事件的格式化与输出、日志文件的滚动与归档等多个步骤,实现了对日志消息的有效管理和控制。同时,Log4j2还提供了异常处理和性能优化等机制,以确保日志系统的稳定性和可靠性。

2.3.3 自动重载配置的实现

Log4j2的自动重载配置是其一个重要的特性,它允许在不重启应用程序的情况下动态地更新日志配置。这一特性参考了Logback的设计,但Log4j2在重新配置时不会丢失日志事件,从而提供了更高的可用性和灵活性。以下是Log4j2自动重载配置的实现原理:

1. 配置文件监测

Log4j2能够自动监测配置文件的变化。这通常是通过设置一个监测间隔(monitorInterval)来实现的,该间隔以秒为单位,指定了Log4j2多久检查一次配置文件是否有更新。这个设置可以在配置文件的<Configuration>标签中通过monitorInterval属性进行配置,最小值为5秒。

2. 配置文件更新检测

在监测间隔到达时,Log4j2会检查配置文件(如log4j2.xml)的最后修改时间是否发生了变化。如果检测到配置文件被修改,Log4j2将开始重新加载配置的过程。

3. 配置重新加载

一旦检测到配置文件的变化,Log4j2会尝试重新加载新的配置。这个过程包括解析新的配置文件、构建新的日志系统组件(如Logger、Appender等),并更新现有的日志系统以反映新的配置。

4. 日志事件不丢失

与Logback不同,Log4j2在重新配置时不会丢失日志事件。这是通过确保在重新配置过程中,所有待处理的日志事件都被正确地处理并输出到适当的Appender来实现的。这样,即使在重新配置期间,应用程序也能继续记录日志,而不会丢失任何信息。

5. 注意事项
  • 监测间隔:虽然设置较小的监测间隔可以更快地检测到配置文件的更新,但过于频繁的监测可能会对性能产生一定的影响。因此,应根据实际需求合理设置监测间隔。
  • 配置文件位置:Log4j2默认会在classpath目录下寻找配置文件,但也可以通过系统属性等方式指定其他位置。
  • 配置兼容性:在更新配置文件时,应确保新的配置与Log4j2的版本兼容,并且不会引入意外的行为或错误。
示例配置

以下是一个简单的Log4j2配置文件示例,其中包含了monitorInterval的设置:

<Configuration status="WARN" monitorInterval="30"> <!-- 其他配置... --> </Configuration>

在这个示例中,monitorInterval被设置为30秒,意味着Log4j2将每30秒检查一次配置文件是否有更新。

结论

Log4j2的自动重载配置功能通过监测配置文件的变化并在必要时重新加载新的配置,实现了在不重启应用程序的情况下动态更新日志配置的能力。这一特性提高了日志系统的灵活性和可用性,使得开发者能够更容易地根据实际需求调整日志策略。

2.3.4 无垃圾机制(对象重用、内存缓冲)

Log4j2 的无垃圾机制(对象重用、内存缓冲)是其性能优化和减少垃圾收集(GC)压力的重要特性。这一机制主要通过减少临时对象的分配和重用现有对象来实现,从而避免了频繁的GC操作对系统性能的影响。以下是对Log4j2无垃圾机制的详细解析:

1、无垃圾机制概述

Log4j2 相较于之前的日志框架,如Log4j 1.x和Logback,在性能上有了显著提升。从版本2.6开始,Log4j2默认以“无垃圾”模式运行,该模式通过对象重用和内存缓冲等技术,避免了在日志记录过程中产生大量的临时对象,从而减少了GC的触发频率。

2、对象重用

对象重用是无垃圾机制的核心之一。在Log4j2中,通过重用ThreadLocal字段中的对象和日志事件缓冲区,避免了在每次日志记录时都创建新的对象。具体来说,Log4j2会维护一个线程局部变量(ThreadLocal),用于存储每个线程自己的日志事件对象和缓冲区。这样,当线程需要记录日志时,就可以直接从ThreadLocal中获取已存在的对象,而无需创建新的对象。

此外,Log4j2还通过重用缓冲区来减少内存分配。在将日志消息转换为字节流并写入文件或控制台时,Log4j2会使用一个可重用的缓冲区来存储这些字节流。这样,在多次日志记录过程中,只需要对缓冲区的内容进行更新,而无需每次都创建一个新的缓冲区。

3、内存缓冲

内存缓冲是Log4j2无垃圾机制的另一个重要组成部分。通过在内存中维护一个缓冲区来暂存日志消息,Log4j2可以减少对磁盘或网络IO的依赖,从而提高日志记录的效率。当缓冲区满时,Log4j2会将其中的内容批量写入到目标位置(如文件、数据库或网络服务器)。

4、配置与控制

Log4j2提供了两个系统属性来控制无垃圾机制的行为:

  • log4j2.enableThreadlocals:如果设置为true(非Web应用程序的默认值),则Log4j2会使用ThreadLocal来存储和重用对象;如果设置为false,则每次记录日志时都会创建新的对象。
  • log4j2.enableDirectEncoders:如果设置为true(默认值),则Log4j2在将日志事件转换为字节流时不会创建临时对象,而是直接写入到目标缓冲区中。
5、总结

Log4j2的无垃圾机制通过对象重用和内存缓冲等技术,显著减少了日志记录过程中产生的临时对象数量,从而降低了GC的触发频率,提高了系统的整体性能。这一机制是Log4j2性能优化的重要组成部分,也是其作为现代日志框架的重要优势之一。

需要注意的是,虽然无垃圾机制可以减少GC的压力,但在某些情况下(如多线程环境下)可能会引入额外的同步开销。因此,在配置Log4j2时需要根据实际应用场景进行权衡和选择。

三、Log4j2配置

3.1 配置文件类型

        详见《Log4j2原理及应用详解(五)

3.2 配置示例

        详见《Log4j2原理及应用详解(六)

3.3 配置参数详解

        详见《Log4j2原理及应用详解(七)

四、Log4j2的高级特性

       详见《Log4j2原理及应用详解(八)

五、Log4j2的应用

       详见《Log4j2原理及应用详解(九)

六、总结与展望

       详见《Log4j2原理及应用详解(九)

七、结语

        文章至此,已接近尾声!希望此文能够对大家有所启发和帮助。同时,感谢大家的耐心阅读和对本文档的信任。在未来的技术学习和工作中,期待与各位大佬共同进步,共同探索新的技术前沿。最后,再次感谢各位的支持和关注。您的支持是作者创作的最大动力,如果您觉得这篇文章对您有所帮助,请分享给身边的朋友和同事!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/46756.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

鼠标的形状

鼠标的形状多样&#xff0c;主要取决于其设计、用途以及制造商的创意。一般来说&#xff0c;鼠标的基本形状包括以下几个部分&#xff1a; 主体部分&#xff1a; 大多数鼠标的主体部分呈流线型或稍微扁平的形状&#xff0c;以适应手掌握持。主体部分通常包含按键和滚轮&#x…

ESP32-S3多模态交互方案在线AI语音设备应用,启明云端乐鑫代理商

随着物联网&#xff08;IoT&#xff09;和人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;嵌入式设备正逐渐变得智能化&#xff0c;让我们的家庭生活变得更加智能化和个性化。 随着大型语言模型的不断进步和优化&#xff0c;AI语音机器人设备能够实现更加智能、…

自定义 Java ClassLoader:深入探索

在 Java 应用程序中&#xff0c;类加载器&#xff08;ClassLoader&#xff09;是实现动态加载类和资源的关键组件。默认情况下&#xff0c;Java 提供了一个类加载器层次结构&#xff0c;但有时我们需要自定义类加载器来满足特定的需求&#xff0c;比如加载加密的类文件、从数据…

mysql链接错误,unblock with ‘mysqladmin flush-hosts‘“

message from server: “Host ‘172.16.39.238’ is blocked because of many connection errors; unblock with ‘mysqladmin flush-hosts’”. 解决步骤&#xff1a; show global variables like ‘%max_connect_errors%’; set global max_connect_errors1000; flush host…

Springboot + JWT 的 Token 登录验证

目录 项目结构 一、 引入依赖 二、自定义Auth认证注解 三、 编写登录拦截器 四、定义跨域拦截器 五、 定义全局异常处理器 六、定义工具类 1. 统一错误状态码 2.统一响应类 3.Token工具类 七、 编写实体类 八、 定义控制器 1.定义登录控制器类 2 定义报错处理器 …

【单片机毕业设计选题24067】-基于STM32的智能衣控制系统

系统功能: 系统上电后OLED显示“欢迎使用智能衣服系统请稍后”两秒钟后进入正常页面显示&#xff0c; 第一行显示系统状态信息 第二行显示获取到体温值 第三行显示设定的高体温阈值和低体温阈值 第四行显示获取到心率和血氧值 短按B3按键调高心率设定高阈值 短按B4按键调…

每日一道算法题 994. 腐烂的橘子

题目 994. 腐烂的橘子 - 力扣&#xff08;LeetCode&#xff09; Python class Solution:def orangesRotting(self, grid: List[List[int]]) -> int:# 分类&#xff0c;挑好坏橘子m,nlen(grid),len(grid[0])have_goodFalserot_orange[]for r in range(m):for c in range(n…

浏览器渲染流程

渲染流水线 生成dom树 根据html生成dom树 生成cssom树 解析css生成一颗cssom树 document.styleSheets构建布局树-layout 根据dom树与cssom树构建一棵layout布局树,会移除不可见部分, 如display:none的dom, 但visible: hidden这种会保留 同时会计算可见部分的几何位置 划…

【学术会议征稿】2024年第三届信息学,网络与计算技术国际学术会议(ICINC2024)

2024年第三届信息学&#xff0c;网络与计算技术国际学术会议(ICINC2024) 2024 3rd International Conference on Informatics,Networking and Computing (ICINC 2024) 2024年第三届信息学&#xff0c;网络与计算技术国际学术会议(ICINC2024)将于2024年10月25-27日于中国郑州召…

Vue中使用mind-map实现在线思维导图

概述 在前面的文章Vue中实现在线画流程图实现中介绍了流程图的在线绘制&#xff0c;在本文&#xff0c;给大家分享一下基于mind-map实现在线的思维导图&#xff0c;并实现&#xff1a;1. 导图导出为图片&#xff1b;2. 打开xmind文件。 实现效果 实现 1. mind-map简介 simp…

使用Druid完成SpringBoot集成MySql、DM(达梦)数据库数据源操作

业务背景 一个方法里&#xff0c;对A数据源需要进行查询&#xff0c;B数据源进行插入(切面插入访问数据&#xff0c;日志)。 详细业务是查询业务数据&#xff0c;同时主数据库记录访问日志。 第一步依赖先行 <dependency><groupId>mysql</groupId><art…

正确选择指挥中心操作台厂家的因素

在当今数字化和信息化快速发展的时代&#xff0c;指挥中心操作台在各类机构和企业的运营中发挥着至关重要的作用。然而&#xff0c;选择一个合适的指挥中心操作台厂家并非易事。以下是一些选择指挥中心操作台厂家的考虑因素。 一、产品质量与工艺 要考察厂家的产品质量和工艺水…

C语言中的指针:掌握内存的钥匙

C语言中的指针&#xff1a;掌握内存的钥匙 引言 C语言是一种结构化编程语言&#xff0c;它提供了对硬件底层的直接访问&#xff0c;其中最强大的特性之一就是指针。指针允许程序员直接操作内存地址&#xff0c;这对于理解程序的内部工作原理以及优化代码性能至关重要。本文将深…

解决宝塔Spring Boot项目获取不到环境变量的问题

问题描述 在使用宝塔面板管理Spring Boot项目时&#xff0c;可能会遇到代码无法获取 /etc/profile 文件中设置的Linux环境变量的问题。虽然在SSH终端中可以正常获取&#xff0c;但在通过宝塔面板启动的Spring Boot项目中&#xff0c;环境变量却无法被读取。 解决方案&#xf…

LeetCode 224. 基本计算器

LeetCode 224. 基本计算器 给你一个字符串表达式 s &#xff0c;请你实现一个基本计算器来计算并返回它的值。 注意:不允许使用任何将字符串作为数学表达式计算的内置函数&#xff0c;比如 eval() 。 示例 1&#xff1a; 输入&#xff1a;s “1 1” 输出&#xff1a;2 示例 2…

GNU/Linux - 压缩解压文件

在 Linux 中&#xff0c;压缩和解压缩文件夹或文件的方法有很多。下面详细列出了最常用的方法以及相应的压缩和解压缩命令&#xff1a; There are numerous methods to compress and uncompress a folder or files in Linux. Below is a detailed list of the most common meth…

量化交易研究报告#13

核心公式 通过对 HS300 相对强弱指标值变化规律的梳理&#xff0c;我们制定如下的交易法则&#xff1a; &#xff08;1&#xff09;计算指标的 20 日均值变化&#xff0c;以及 20 日标准差&#xff1b; &#xff08;2&#xff09;20日均值1倍标准差作为上阈值&#xff0c;20…

【Chapter 3: Creating Minimal API Applications】

Chapter 1: Foundations of Framework Learning and Practical Strategies Chapter 2: An Introduction to ASP.NET Core in Layman‘s Terms Chapter 3: Creating Minimal API Applications 1. Overview of Minimal APIs In the vast landscape of ASP.NET Core, “Minima…

Mysql表的三范式、事务和查询

数据表的三范式 在制定数据表,需要遵循的制表规范:第一范式(1NF),第二范式(2NF),第三范式(3NF) 第一范式 属性不可分割,每一个属性(每一个单元格)都是不可再分的原子,也就是说数据表中的每一个字段必须是单独一列的,不能出现还可以再拆分的情况,也可以说成是…

数电基础 - 半导体存储

目录 一. 简介 一. 只读存储器 二. 可编程只读存储器 三. 可擦除的可编程只读存储器 四. 随机存储器 五. 存储器容量的扩展 六. 总结 一. 简介 半导体存储是数字电路中用于存储数据的重要组成部分。 半导体存储器主要分为两大类&#xff1a;随机存取存储器&#xff0…