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

news2024/9/25 15:25:44

目录

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);
    @Test
    public 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.coloradmin.cn/o/1924016.html

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

相关文章

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

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

ISO 45001:提升职业健康与安全管理水平的关键

在现代企业管理中&#xff0c;员工的职业健康与安全&#xff08;OH&S&#xff09;已经成为不可忽视的重要议题。ISO 45001作为国际标准化组织&#xff08;ISO&#xff09;制定的职业健康与安全管理体系标准&#xff0c;为企业提供了科学有效的管理规范和指南。实施这一标准…

C#中的反射

dll和exe文件的区别 用途&#xff1a; .exe&#xff08;可执行文件&#xff09;&#xff1a;是可以直接运行的程序文件。当你双击一个 .exe 文件或在命令行中输入它的名字&#xff0c;操作系统会加载并执行这个程序。 .dll&#xff08;动态链接库&#xff09;&#xff1a;包含…

如何在SpringCloud中使用Kafka Streams实现实时数据处理

使用Kafka Streams在Spring Cloud中实现实时数据处理可以帮助我们构建可扩展、高性能的实时数据处理应用。Kafka Streams是一个基于Kafka的流处理库&#xff0c;它可以用来处理流式数据&#xff0c;进行流式计算和转换操作。 下面将介绍如何在Spring Cloud中使用Kafka Streams实…

从零开学C++:类和对象(中)

引言&#xff1a;在我们学习了类和对象&#xff08;上&#xff09;的基础知识后&#xff0c;我们就需要进入类和对象&#xff08;中&#xff09;的学习。本篇博客将会介绍C的几个默认成员函数&#xff0c;它们的存在虽然难以理解&#xff0c;但也是C如此简单实用的原因之一。相…

C++学习指南(一)——C++入门基础

欢迎来到繁星的CSDN&#xff0c;本期内容主要包括C第一个程序&#xff0c;命名空间&#xff0c;缺省参数&#xff0c;函数重载&#xff0c;引用、inline以及nullptr这些基础概念。 在进入正题之前&#xff0c;我需要先阐述一下。本系列涉及的内容为C部分&#xff0c;可以理解为…

The Open Group 爱丁堡大会高光集锦——企业架构、人工智能和可持续发展的创新交叉点

4月底&#xff0c;The Open Group峰会在英国爱丁堡顺利举办。活动邀请到数十位领域专家、技术、论坛成员、工作组和联合组织等相聚在一起&#xff0c;围绕生态系统架构和人工智能标准、可持续性、企业架构、数字转型等话题进行了对话与探讨。大会吸引了来自30个国家的400位观众…

bi项目笔记

1.bi是什么 bi项目就是商业智能系统&#xff0c;也就是数据可视画、报表可视化系统&#xff0c;如下图的就是bi项目了 2.技术栈

Mysql数据库的备份与恢复以及索引操作

一&#xff0c;备份与恢复操作 1&#xff0c;创建数据库booksDB CREATE DATABASE booksDB; use booksDB; 2&#xff0c;建表 &#xff08;1&#xff09;创建表books CREATE TABLE books ( bk_id INT NOT NULL PRIMARY KEY, bk_title VARCHAR(50) NOT NUL…

MYSQL--第八次作业

MYSQL–第八次作业 一、备份与恢复 环境搭建&#xff1a; CREATE DATABASE booksDB; use booksDB;CREATE TABLE books ( bk_id INT NOT NULL PRIMARY KEY, bk_title VARCHAR(50) NOT NULL, copyright YEAR NOT NULL );CREATE TABLE authors ( auth_id INT NOT NULL PRI…

SpringCloud第三篇(服务中心与OpenFeign)

p 文章目录 一、服务中心二、Nacos注册中心 一、服务中心 在上一章我们实现了微服务拆分&#xff0c;并且通过Http请求实现了跨微服务的远程调用。不过这种手动发送Http请求的方式存在一些问题。 试想一下&#xff0c;假如商品微服务被调用较多&#xff0c;为了应对更高的并发…

【JavaEE】AOP实现原理

概述 Spring AOP 是基于动态代理来实现AOP的, 此处主要介绍代理模式和Spring AOP的源码剖析 一.代理模式 代理模式是一种常用的设计模式&#xff0c;它允许为其他对象提供代理&#xff0c;以控制对这个对象的访问。这种结构在不改变原始类的基础上&#xff0c;通过引入代理类…

前端的页面代码

根据老师教的前端页面的知识&#xff0c;加上我也是借鉴了老师上课所说的代码&#xff0c;马马虎虎的写出了页面。如下代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</ti…

Gitea 仓库事件触发Jenkins远程构建

文章目录 引言I Gitea 仓库事件触发Jenkins远程构建1.1 Jenkins配置1.2 Gitea 配置引言 应用场景:项目部署 I Gitea 仓库事件触发Jenkins远程构建 Gitea支持用于仓库事件的Webhooks 1.1 Jenkins配置 高版本Jenkins需要关闭跨域限制和开启匿名用户访问 在Jenkins启动前加入…

微前端基础知识

1. 前言 随着Web应用程序规模的日益扩大和复杂性的增加&#xff0c;传统的前端开发模式逐渐显现出其在维护、扩展以及团队协作方面的局限性。微前端作为一种新兴的前端架构模式&#xff0c;正是为了应对这些挑战而诞生的。 微前端&#xff08;Micro-Frontends&#xff09;并没有…

matine组件库踩坑日记 --- react

Mantine实践 一 禁忌核心css样式二 添加轮播图扩展组件 一 禁忌核心css样式 import React from react import ReactDOM from react-dom/client import { BrowserRouter } from react-router-dom; import App from ./App.jsx import ./index.css import mantine/core/styles.cs…

收银系统源码-会员功能

随着新零售时代不断更新迭代&#xff0c;私域会员已经成为很多连锁门店必要的选择。自然离开不了一套能高效管理会员的收银系统。今天给大家推荐一下&#xff0c;智慧新零售收银系统的会员功能。 了解更多查看下文&#xff1a; 门店收银系统源码-CSDN博客文章浏览阅读2.6k次&…

开源项目:机遇与挑战共存的创新之路

开源项目&#xff1a;机遇与挑战共存的创新之路 开源&#xff08;Open Source&#xff0c;开放源码&#xff09;被非盈利软件组织&#xff08;美国的Open Source Initiative协会&#xff09;注册为认证标记&#xff0c;并对其进行了正式的定义&#xff0c;用于描述那些源码可以…

倒计时 2 周!CommunityOverCode Asia 2024 IoT Community 专题部分

CommunityOverCode 是 Apache 软件基金会&#xff08;ASF&#xff09;的官方全球系列大会&#xff0c;其前身为 ApacheCon。自 1998 年以来&#xff0c;在 ASF 成立之前&#xff0c;ApacheCon 已经吸引了各个层次的参与者&#xff0c;在 300 多个 Apache 项目及其不同的社区中探…

线性回归(梯度下降)

首先说案例&#xff1a; 房子的价格和所占面积有着很大的关系&#xff0c;假如现在有一些关于房子面积和价格的数据&#xff0c;我要如何根据已经有的数据来判断未知的数据呢&#xff1f; 假如x(房屋面积)&#xff0c;y(房屋价格) x[ 56 72 69 88 102 86 76 79 94 74] y[92, …