log4j2的日志框架(详细,springboot和异步日志的实现)

目录

log4j2的介绍

Log4j2的性能

SpringBoot中的使用Log4j2

log4j2的进阶--异步日志

 AsyncAppender方式

AsyncLogger方式 


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在多线程的环境下吞吐量与Log4j和 Logback的比较如下图。下图比较中Log4j2有三种模式:1)全局使用异步模式;2)部分Logger采用异步模式;3)异步Appender。可以看出在前两种模式下,Log4j2的性能较之Log4j和Logback有很大的 优势。

无垃圾记录

垃圾收集暂停是延迟峰值的常见原因,并且对于许多系统而言,花费大量精力来控制这些暂停。

许多日志库(包括以前版本的Log4j)在稳态日志记录期间分配临时对象,如日志事件对象,字符串, 字符数组,字节数组等。这会对垃圾收集器造成压力并增加GC暂停发生的频率。

从版本2.6开始,默认情况下Log4j以“无垃圾”模式运行,其中重用对象和缓冲区,并且尽可能不分配临 时对象。还有一个“低垃圾”模式,它不是完全无垃圾,但不使用ThreadLocal字段。

Log4j 2.6中的无垃圾日志记录部分通过重用ThreadLocal字段中的对象来实现,部分通过在将文本转换 为字节时重用缓冲区来实现。 

从图中可以看出log4j2的性能是完全吊打其他日志框架的,而且log4j2的异步日志功能非常的强大,可以大大的减少日志系统对业务系统的负担。基于这些功能,所以现在主流的日志开发架构就是SLF4J+Log4j2这个组合,所以这个log4j2这个日志框架是必须要学会的

SpringBoot中的使用Log4j2

springboot框架在企业中的使用越来越普遍,springboot日志也是开发中常用的日志系统。springboot 默认就是使用SLF4J作为日志门面,logback作为日志实现来记录日志。所以如果我们要在springboot项目中使用Log4j2,需要内置的日志框架给去除。

分成三步,第一移除默认的日志框架,第二加入log4j2的依赖(启动器),第三编写配置文件

  • 移除默认的日志框架
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><!--排除默认spring-boot-starter-logging启动器--><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></exclusion></exclusions>
</dependency>
  • 加入log4j2的依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

编写log4j2.xml配置文件‘

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN"><!-- 定义全局变量,日志文件路径和格式 --><Properties><Property name="log.path">./dev</Property><Property name="log.name">forlan-log4j2</Property><Property name="file.pattern">%d{yyyy-MM-dd HH:mm:ss} %-5level [%thread] %logger{50} - %msg%n</Property></Properties><!-- 控制台输出配置 --><Appenders><Console name="STDOUT" target="SYSTEM_OUT"><PatternLayout pattern="${file.pattern}"/><ThresholdFilter level="DEBUG"/></Console><!-- 文件输出配置 --><RollingFile name="INFO_FILE" fileName="${log.path}/${log.name}.info.log"filePattern="${log.path}/%d{yyyy-MM-dd}/${log.name}.info.%d{yyyy-MM-dd}-%i.log"><PatternLayout pattern="${file.pattern}"/><LevelMatchFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/><!-- 每个文件最大10MB --><SizeBasedTriggeringPolicy size="10MB"/><!-- 最多保留30天的历史记录 --><DefaultRolloverStrategy max="30"/></RollingFile><!-- 文件输出配置 --><RollingFile name="ERROR_FILE" fileName="${log.path}/${log.name}.error.log"filePattern="${log.path}/%d{yyyy-MM-dd}/${log.name}.error.%d{yyyy-MM-dd}-%i.log"><PatternLayout pattern="${file.pattern}"/><LevelMatchFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/><!-- 每个文件最大10MB --><SizeBasedTriggeringPolicy size="10MB"/><!-- 最多保留30天的历史记录 --><DefaultRolloverStrategy max="30"/></RollingFile></Appenders><!-- 设置root logger --><Loggers><Root level="INFO"><AppenderRef ref="STDOUT"/><AppenderRef ref="INFO_FILE"/><AppenderRef ref="ERROR_FILE"/></Root></Loggers>
</Configuration>
  •  运行测试
@SpringBootTest
public class Slf4jTest {// 声明日志对象public final static Logger LOGGER = LoggerFactory.getLogger(Slf4jTest.class);@Testpublic void testQuick() throws Exception {//打印日志信息LOGGER.error("error");LOGGER.warn("warn");LOGGER.info("info");LOGGER.debug("debug");LOGGER.trace("trace");// 使用占位符输出日志信息String name = "jack";Integer age = 18;LOGGER.info("用户:{},{}", name, age);// 将系统异常信息写入日志try {int i = 1 / 0;} catch (Exception e) {// e.printStackTrace();LOGGER.info("出现异常:", e);}}
}

 

出现入上图的结果就代表log4j2就配置成功了,主要注意那个dev的日志文件是否生成,这个日志文件是在前面的配置文件中配置的。

到这里log4j2的基本使用其实已经可以实现了,对于一些小的项目,这样子配置就可以了,但对于那些大型项目,log4j2还可以更加强大,那就是使用它的异步日志功能 

log4j2的进阶--异步日志

logl4j2最大的特点就是异步日志,其性能的提升主要也是从异步日志中受益,我们来看看如何使用 log4j2的异步日志。

Log4j2 提供了两种实现日志的方式,一个是通过AsyncAppender,一个是通过AsyncLogger,分别对应 前面我们说的Appender组件和Logger组件。 

log4j2的全局异步AsyncLogger性能最好,第二个是混合异步AsyncLogger,性能最差的是AsyncAppender(和同步日志相比没有什么性能提升。和logback性能一样)

如果使用异步日志,全局异步AsyncLogger、混合异步AsyncLogger、AsyncAppender,不要同时使用。否则会使用性能较低的一种异步方式
 

注意:配置异步日志需要添加依赖

<!--异步日志依赖-->
 <dependency>
         <groupId>com.lmax</groupId>
         <artifactId>disruptor</artifactId>
         <version>3.3.4</version>
 </dependency>

 AsyncAppender方式

 AsyncAppender:这种使用方式较为简单,只需要在我们上述的Appender中加入以下标签即可:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" monitorInterval="5"><properties><property name="LOG_HOME">C:/Users/dell/Desktop/java11Test/logs</property></properties><Appenders><File name="File" fileName="${LOG_HOME}/myFile.log"><PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%-5level] %l --- %msg%n" /></File><!-- AsyncAppender引用appender --><Async name="Async"><AppenderRef ref="File"/></Async></Appenders><Loggers><Root level="INFO"><!-- 直接引用AsyncAppender --><AppenderRef ref="Async" /></Root></Loggers></Configuration>
AsyncLogger方式 

AsyncLogger才是log4j2 的重头戏,也是官方推荐的异步方式。它可以使得调用Logger.log返回的 更快。你可以有两种选择:全局异步和混合异步。

全局异步 就是,所有的日志都异步的记录,在配置文件上不用做任何改动,只需要添加一个 log4j2.component.properties 配置;

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

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

    <!--logger定义--><Loggers><!--自定义异步logger对象includeLocation = "false" 关闭日志记录行好信息additivity = "false" 不再继承rootlogger对象--><AsyncLogger name = "com.itcats" level = "trace" includeLocation = "false" additivity = "false"><AppenderRef ref="Console"/></AsyncLogger><Root level = "trace"><AppenderRef ref  ="Console"/></Root></Loggers>

将以上配置配置到我们之前的log4j2.xml配置文件中,将之前的logger定义替换。此时我们com.itcats日志是异步的,root日志是同步的。

使用异步日志需要注意的问题:

1. 如果使用异步日志,AsyncAppender、AsyncLogger和全局日志,不要同时出现。性能会和 AsyncAppender一致,降至最低。

2. 设置includeLocation=false ,打印位置信息会急剧降低异步日志的性能,比同步日志还要慢

到这里我们的java日志框架基本就介绍完了

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

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

相关文章

Go-知识测试-测试参数

Go-知识测试-测试参数 1. -args2. -json3. -o4. -bench5. -benchtime6. -cpu7. -count8. -failfast9. -list10. -parallel11. -run12. -timeout13. -v14 -benchmem 1. -args 指示go test 把-args 后面的参数带到测试中去。具体的测试函数会根据此参数来控制测试流程。 -args后…

主机安全-进程、命令攻击与检测

目录 概述反弹shell原理nc/dev/xxx反弹shell下载不落地反弹Shell各种语言反弹shell linux提权sudosuid提权mysql提权 Dnslog参考 概述 本文更新通过在主机&#xff08;不含容器&#xff09;上直接执行命令或启动进程来攻击的场景。检测方面以字节跳动的开源HIDS elkeid举例。每…

磁感应强度检测模块使用教程

目录 一、磁感应强度检测模块(AT 协议版本、Modbus 协议版本)1、参数2、报警引脚 二、AT版本1、接线说明2、AT 指令 三、Modbus 版本1、接线说明2、Modbus 指令格式3、Modbus 指令 一、磁感应强度检测模块(AT 协议版本、Modbus 协议版本) 图1 正面 图2 背面 AT 协议版本和 Modb…

Letter Exchange

这道题目看官方题解就好了&#xff0c;这个转换图论挺显然的 证明一下为什么最后一定是 显然练完贬值后图只能长成这个样子 在消掉长度为\(2\)的环后&#xff0c;如果说图没边了&#xff0c; 那么显然就不用交换了&#xff0c;否则的话我们任取一条边 那么对于\(2\)号点来说&am…

韦东山嵌入式linux系列-驱动进化之路:总线设备驱动模型

1 驱动编写的 3 种方法 以 LED 驱动为例 1.1 传统写法 使用哪个引脚&#xff0c;怎么操作引脚&#xff0c;都写死在代码中。 最简单&#xff0c;不考虑扩展性&#xff0c;可以快速实现功能。 修改引脚时&#xff0c;需要重新编译。 应用程序调用open等函数最简单的方法是驱动…

微调Qwen2大语言模型加入领域知识

目录 试用Qwen2做推理安装LLaMA-Factory使用自有数据集微调Qwen2验证微调效果 试用Qwen2做推理 参考&#xff1a;https://qwen.readthedocs.io/en/latest/getting_started/quickstart.html from transformers import AutoModelForCausalLM, AutoTokenizer device "cuda…

9.6 栅格图层符号化唯一值着色渲染

文章目录 前言多波段彩色渲染唯一值着色QGis设置为唯一值着色二次开发代码实现唯一值着色 总结 前言 介绍栅格图层数据渲染之唯一值着色渲染说明&#xff1a;文章中的示例代码均来自开源项目qgis_cpp_api_apps 多波段彩色渲染唯一值着色 以“with_color_table.tif”数据为例…

硅谷甄选4(项目主体)

1.路由配置 1.1路由组件的雏形 src\views\home\index.vue&#xff08;以home组件为例&#xff09; 安装插件&#xff1a; 1.2路由配置 1.2.1路由index文件 src\router\index.ts //通过vue-router插件实现模板路由配置 import { createRouter, createWebHashHistory } fro…

react-router实现路由拦截,useLocation,useNavigate钩子

路由拦截 react-router中没有直接给出拦截路由的方法&#xff0c;需要手动的去监听路由的变化来拦截路由 路由拦截的要点&#xff1a; 能够识别出目标路由和原始路由&#xff08;区分跳转前和跳转后&#xff09;能够在跳转时&#xff08;跳转前或者跳转后&#xff09;执行一些…

Vulnhub靶场 | DC系列 - DC1

https://www.vulnhub.com/series/dc,199/ 环境搭建 靶机镜像下载地址&#xff1a;https://www.vulnhub.com/entry/dc-1,292/&#xff1b;需要将靶机和 kali 攻击机放在同一个局域网里&#xff1b;本实验kali 的 IP 地址&#xff1a;192.168.10.146。 渗透测试 1. 信息收集 …

CH16-DOM元素增删改

CH16-DOM元素增删改 本章目标 掌握如何使用DOM获取节点时使用的属性熟练使用DOM节点进行创建、添加、删除、替换 一、使用DOM获取节点时使用的属性 1.1 首尾子节点 firstChild&#xff1a;获取当前节点的首个子节点&#xff0c;注意&#xff1a;换行符、空格等也是节点。 …

【逆向】-异或-分组异或2

IDA查看源代码 src长度32&#xff0c;encrypt函数加密&#xff0c;工4个参数&#xff0c;_FFFC双击&#xff0c;可以看到是个长度为7的固定值FnTest! 加密函数将4个参数又重新命名&#xff0c;混淆视听&#xff0c;但是还是可以看到是嵌套循环&#xff0c;动态调试直接看结果可…

C++11中重要的新特性之 lambda表达式 Part two

序言 在上一篇文章中&#xff0c;我们主要介绍了 C11 中的新增的关键词&#xff0c;以及 范围for循环 这类语法糖的使用和背后的逻辑。在这篇文章中我们会继续介绍一个特别重要的新特性分别是 lambda表达式 。 1. lambda表达式 1.1 lambda的定义 C11 中的 lambda表达式 是一种…

Java基础之集合

集合和数组的类比 数组: 长度固定可以存基本数据类型和引用数据类型 集合: 长度可变只能存引用数据类型存储基本数据类型要把他转化为对应的包装类 ArrayList集合 ArrayList成员方法 添加元素 删除元素 索引删除 查询 遍历数组

Linux: Mysql环境安装

Mysql环境安装&#xff08;Centos&#xff09; 前言一、卸载多余环境1.1 卸载mariadb1.2 查看并卸载系统mysql和mariadb安装包 二、换取mysql官方yum源三、安装并启动mysql服务3.1 yum源加载3.2 安装yum源3.3 安装mysql服务3.3.1 安装指令3.3.2 GPG密钥问题解决方法3.3.3 查看是…

循环结构(一)——for语句【互三互三】

文章目录 &#x1f341; 引言 &#x1f341; 一、语句格式 &#x1f341; 二、语句执行过程 &#x1f341; 三、语句格式举例 &#x1f341;四、例题 &#x1f449;【例1】 &#x1f680;示例代码: &#x1f449;【例2】 【方法1】 &#x1f680;示例代码: 【方法2】…

Cartographer重入门到精通(二):运行作者demo及自己的数据集

在demo数据包上运行cartographer 现在Cartographer和Cartographer的Ros包已经都安装好了&#xff0c;你可以下载官方的数据集到指定的目录&#xff08;比如在Deutsches Museum用背包采集的2D和3D 数据&#xff09;&#xff0c;然后使用roslauch来启动demo。 注&#xff1a;la…

IO半虚拟化-Virtio学习笔记

参考&#xff1a;《深入浅出DPDK》及大佬们的各种博客 Virtio简介&运行环境 Virtio 是一种用于虚拟化环境中的半虚拟化 I/O 框架&#xff0c;目的是在虚拟机和主机之间提供一种高效的 I/O 机制。关于什么是半虚拟化和全虚拟化&#xff1a;见SR-IOV学习笔记。 YES&#xf…

PDMS二次开发(二十二)——关于1.0.3.1版本升级内容的说明

目录 1.更新内容介绍2.效果演示3.关于重构自动添加焊口功能的说明3.1错误示例 3.问题交流1.创建焊口提示失败2.程序崩溃 1.更新内容介绍 在添加焊口之前先清除当前branch已有焊口&#xff1b;显示清除焊口的个数和添加焊口的个数&#xff1b;重构了自动添加焊口功能&#xff0…

值得关注的数据资产入表

不错的讲解视频&#xff0c;来自&#xff1a;第122期-杜海博士-《数据资源入表及数据资产化》-大数据百家讲坛-厦门大学数据库实验室主办第122期-杜海博士-《数据资源入表及数据资产化》-大数据百家讲坛-厦门大学数据库实验室主办-20240708_哔哩哔哩_bilibili