Java日志系统之Log4j2

news2024/12/23 8:56:17

Log4j2介绍

Log4j2是Log4j的升级版,参考Logback的优秀设计并修复了一些问题。主要优点有:

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

Log4j2的简单使用

Log4j2和Slf4j一样,既可以当门户也可以当日志实现。但是通常都是用Slf4j当门户,Log4j2当日志实现。先单独使用Log4j2进行日志打印

    <dependencies>
        <!--log门户-->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.19.0</version>
        </dependency>
        <!--log日志实现-->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.19.0</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
public class TestLog4j2 {
    public  final static Logger logger = LogManager.getLogger(TestLog4j2.class);

    @Test
    public void testLog() throws Exception {
        logger.fatal("fatal");
        logger.error("error");
        logger.warn("wring");
        logger.info("info");
        logger.debug("debug");
        logger.trace("trace");
    }
}

20:05:28.830 [main] FATAL com.zmt.TestLog4j2 - fatal

20:05:28.831 [main] ERROR com.zmt.TestLog4j2 - error

可以看出,Log4j2的默认级别为error。

接下来使用Slf4j与Log4j2混合使用。

只需要在pom文件中添加slf4j-api与log4j-slf4j-impl依赖就好。其余什么都不用改变。

  	<dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>2.0.7</version>
        </dependency>

        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.13.3</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>

Log4j2的配置文件

log4j2默认加载classpath路径下的log4j2.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!--
        status:日志框架本身的输出日志级别(输出框架信息)
        monitorInterval:自动加载配置文件的间隔时间,在生产环境中不需要重启项目
-->
<configuration status="warn" monitorInterval="5">
    <properties>
        <property name="log_dir" value="D:/logs"></property>
    </properties>
    <!--
    日志输出格式:
        %-5level 日志级别
        %d{yyyy-MM-dd HH:mm:ss}日期
        %c类的完整名称
        %M为method
        %L为行号
        %thread线程名称
        %m或者%msg为信息
        %n换行
    -->
    <Appenders>
        <!--控制台输出 appender-->
        <Console name="Console" target="SYSTEM_ERR">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] [%-5level] %c{36}:%L --- %m%n"/>
        </Console>
        <!--日志文件输出 appender-->
        <File name="file" fileName="${log_dir}/myfile.log">
            <Patternlayout pattern="[%d{yyyy-MM-dd HH:mm:ss}] [%-5level] %l %c{36} - %m%n"/>
        </File>

        <!--使用随机读写流的日志文件输出appender,性能提高-->
        <RandomAccessFile name="accessFile" fileName="${log_dir}/myAcclog.log">
            <Patternlayout pattern="[%d{yyyy-MM-dd HH:mm:ss}] [%-5level] %l %c{36} - %m%n"/>
        </RandomAccessFile>
        <!--按照一定规则拆分的日志文件的 appender-->
        <RollingFile name="rollingFile" fileName="${log_dir}/myrollog.log"
                     filePattern="${log_dir}/$${date:yyyy-MM-dd}/myrollog-%d{yyyy-MM-dd-HH-mm}-%i.log">
            <!--日志级别过滤器-->
            <ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>
            <!--日志消息格式-->
            <Patternlayout pattern="[%d{yyyy-MM-dd HH:mm:ss}] [-5level] %l %c{36} - %msg%n"/>
            <Policies>
                <!--在系统启动时,出发拆分规则,生产一个新的日志文件-->
                <OnStartupTriggeringPolicy/>
                <!--按照文件大小拆分,10MB-->
                <SizeBasedTriggeringPolicy size="10 MB"/>
                <!--按照时间节点拆分,规则根据filePattern定义的-->
                <TimeBasedTriggeringPolicy/>
            </Policies>
            <!--在同一个目录下,文件的个数限定为 30 个,超过进行覆盖-->
            <DefaultRolloverStrategy max="30"/>
        </RollingFile>
    </Appenders>

    <!--logger 定义-->
    <Loggers>
        <!--使用 rootLogger 配置 日志级别 level="trace"-->
        <Root Level="trace">
            <!--指定日志使用的处理器-->
            <AppenderRef ref="Console"/>
            <AppenderRef ref="file"/>
        </Root>
    </Loggers>
</configuration>

Log4j2异步日志

异步日志分为三种:

  • AsyncAppender:异步Appender
  • 全局AsyncLogger:全局异步Logger
  • 混合AsyncLogger:异步与同步混合使用的Logger

其中异步Appender的性能最差,基本不使用。

全局异步Logger性能最好,但是有时并不是所有的业务都需要异步记录日志,因此也不常用。

通常使用混合AsyncLogger。

异步Appender简单实现

在xml配置文件中Appenders标签下添加配置

  	<Appenders>
        <!--控制台输出 appender-->
        <Console name="Console" target="SYSTEM_ERR">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] [%-5level] %c{36}:%L --- %m%n"/>
        </Console>
        <!--日志文件输出 appender-->
        <File name="file" fileName="${log_dir}/myfile.log">
            <Patternlayout pattern="[%d{yyyy-MM-dd HH:mm:ss}] [%-5level] %l %c{36} - %m%n"/>
        </File>
      	<!--配置异步实现-->
				<Async name="async">
            <AppenderRef ref="file"></AppenderRef>
        </Async>
    </Appenders>

    <!--logger 定义-->
    <Loggers>
        <!--使用 rootLogger 配置 日志级别 level="trace"-->
        <Root Level="trace">
            <!--指定日志使用的处理器-->
            <AppenderRef ref="Console"/>
            <AppenderRef ref="async"/>
        </Root>
    </Loggers>
public class TestLog4j2 {
    public  final static Logger logger = LogManager.getLogger(TestLog4j2.class);

    @Test
    public void testLog() throws Exception {
        logger.fatal("fatal");
        logger.error("error");
        logger.warn("wring");
        logger.info("info");
        logger.debug("debug");
        logger.trace("trace");
    }
}

观察日志文件

全局异步Logger简单实现

只需要在resource目录下创建文件名为log4j.component.properties添加如下配置

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

log4j2.xml配置文件不需要做任何改动。

混和异步Logger简单实现

如果使用混合异步Logger,需要将全局异步Logger的配置文件注释或删除,并且需要添加依赖。

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

在log4j.xml文件中进行修改

    <!--logger 定义-->
    <Loggers>
        <!--自定义Logger-->
        <!--
            includeLocation:设为false作用是关闭日志行号记录,打开的话会影响性能
            additivity:不再继承rootLogger
        -->
        <AsyncLogger name="com.zmt" level="debug" includeLocation="false" additivity="false">
            <AppenderRef ref="Console"/>
        </AsyncLogger>


        <!--使用 rootLogger 配置 日志级别 level="trace"-->
        <Root Level="trace">
            <!--指定日志使用的处理器-->
            <AppenderRef ref="Console"/>
            <AppenderRef ref="async"/>
        </Root>
    </Loggers>

观察控制台输出

可以看到,即使日志格式中添加了%L但仍不会再控制台中打印行号

注意:

  • 如果使用异步日志AysncAppender、AsyncLogger与全局日志不要同时出现,性能会和最差的一致
  • 设置includeLocation为false是必要的,打印位置信息会降低异步日志的性能,比同步日志还慢。

Log4j2的无垃圾模式

其他日志系统在记录日志时会分配临时对象,如日志事件对象、字符串、字符数组等,当临时对象过多时会触发JVM的gc操作(该操作会暂停程序的运行)。而Log4j2从2.6版本开始,默认情况下以无垃圾模式运行,主要原理是重用对象和缓冲区,尽可能的不分配临时对象。

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

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

相关文章

Java高级编程----集合

集合 集合概述Collection接口List接口简介ArrayList集合Set接口简介Hash Set接口简介Map接口简介TreeMap集合Properties集合 集合概述 为了在程序中可以保存数目不确定的对象&#xff0c;Java提供了一系列特殊类&#xff0c;这些类可以存储任意类型的对象&#xff0c;并且长度…

使用java mail SMTPTransport发送邮箱,本地秒到,一上服务器就20-30s左右,生产环境直接发送失败。

一、代码 pom文件 <dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope></dependency><!--pom.xml添加javax.mail的引用&#xff0c;或者项目引入…

【最短路径算法】一文掌握Dijkstra算法,详解与应用示例+代码

目录 1 Dijkstra算法 2 Dijkstra算法的步骤 3 Dijkstra算法python实现 4 Dijkstra算法应用示例详解 1 Dijkstra算法 Dijkstra算法&#xff08;迪杰斯特拉算法&#xff09;是一种用于在加权图中查找从一个起始节点到所有其他节点的最短路径的算法。该算法最初由荷兰计算机科…

JVM 基础篇:类加载器

一.了解JVM 1.1什么是JVM JVM是Java Virtual Machine&#xff08;Java虚拟机&#xff09;的缩写&#xff0c;是一个虚构出来的计算机&#xff0c;是通过在实际的计算机上仿真模拟计算机功能来实现的&#xff0c;JVM屏蔽了与具体操作系统平台相关的信息&#xff0c;Java程序只需…

通讯录和内存动态管理

目录 (通讯录)动态增长版 实现效果 找单身狗 题目 源码 思路 三个内存函数的模拟实现 模拟实现strncpy 模拟实现strncat 模拟实现atoi (通讯录)动态增长版 该版本通讯录在原版的基础上增加了检查容量函数&#xff0c;实现了通讯录的动态…

在PS中轻松实现肖像磨皮,感受Imagenomic Portraiture 4的强大

每个人都希望自己的肖像照片看起来漂亮、清晰并且光滑。然而&#xff0c;在处理肖像照片时&#xff0c;要达到这些效果通常需要花费大量时间和精力。如果您正在寻找一种简单快捷的方法来优化您的肖像照片&#xff0c;那么Imagenomic Portraiture 4插件将是您的理想选择。 Imag…

单接口的批量测试如何实现

一、痛点&#xff1a;一条测试数据对应一个测试方法 前面的章节中我们已经写代码实现了登录接口的处理调用&#xff0c;但是一个接口往往是需要多条测试用例才能完整的覆盖到每一种情况&#xff0c;针对于单接口多条测试用例需要执行的情况&#xff0c;该如何处理呢&#xff0…

uboot移植之mx6ull_alientek_nand.h文件详解一

一. 简介 mx6ull_alientek_nand.h文件是 开发板的 uboot的一个配置文件。每个开发板都有一个 .h的配置文件。 mx6ull_alientek_nand.h文件其实是 之前针对正点原子ALPHA开发板移植的 Uboot配置文件。 本文简单分析一下 针对正点原子ALPHA开发板的 配置文件&#xff1a; mx6u…

STL模拟实现—vector

引言&#xff1a;本篇文章主要是模拟实现vector&#xff0c;但不同于stl中vector的成员变量都是迭代器&#xff0c;这个自定义的vector是一个T* 的数据变量和一个int类型的size和int类型的capacity。&#xff08;有时间再写三个迭代器的版本吧&#xff01;&#xff09; 首先来看…

Redis学习(第八章缓存策略)

目录 RdisExample 课程介绍 1.Redis介绍 2.Redis 安装 3. Redis的数据结构 4. Redis缓存特性 5. Redis使用场景 6. Redis客户端-Jedis 7. Jedis Pipeline 8. Redis缓存策略 学习资料 QA 相关问题 http, socket ,tcp的区别 RdisExample 项目代码地址&#xff1a;htt…

Leetcode—104.二叉树的最大深度【简单】

2023每日刷题&#xff08;六&#xff09; Leetcode—104.二叉树的最大深度 递归实现代码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/int maxDepth(struct TreeNode* root){…

2017年高热度编程语言简介

世上语言千千万&#xff0c;我却独爱这一种!”这句话用来形容程序员和编程语言之间的爱恨情仇实在是再精准不过了。根据GitHub 2016年的开源报告&#xff0c;其上所有开源项目共包含了316种编程语言&#xff0c;这是一个什么概念呢?举个例子来说&#xff0c;世界上共有226个国…

高防CDN的发展趋势

随着互联网的迅速发展&#xff0c;网站和在线服务的安全性变得至关重要。网络攻击如DDoS攻击和恶意流量正在增加&#xff0c;因此高防CDN&#xff08;高防御内容分发网络&#xff09;成为网络安全的重要组成部分。本文将探讨高防CDN未来的发展趋势&#xff0c;并比较其与传统CD…

PyCharm改变代码背景图片的使用教程

一个好的集成环境是学习和使用一门编程语言的重中之重&#xff0c;这次我给大家分享如何改变PyCharm软件的代码背景图片。 说明&#xff1a;本教程使用的是汉化版PyCharm软件。 打开PyCharm软件。 点击软件最上方导航栏的文件&#xff0c;然后找到设置。 打开设置然后点击外观…

小米妙享无法正常启动,用非管理员权限启动

网上找到的其他方法大多数不太好 1.非管理员方式运行的方法 1.创建一个用户123&#xff0c;密码123 2.创建一个bat文件&#xff0c;复制粘贴以下内容 runas /savecred /user:123 “C:\Program Files\MI\AIoT\Launch.exe” 第一次点击运行&#xff0c;要输入密码&#xff0c;以…

面试官:说说webpack的热更新是如何做到的?

一、是什么 HMR 全称 Hot Module Replacement&#xff0c;可以理解为模块热替换&#xff0c;指在应用程序运行过程中&#xff0c;替换、添加、删除模块&#xff0c;而无需重新刷新整个应用 例如&#xff0c;我们在应用运行过程中修改了某个模块&#xff0c;通过自动刷新会导致…

靶机 DC_1

DC_1 信息搜集 存活检测 详细扫描 网页目录扫描 网页信息搜集 cms 为 Drupal 漏洞利用 使用 msf 搜索 drupal 的漏洞 启动 msfconsole搜索 search drupal尝试编号为 0 的漏洞 失败 利用编号为 1 的漏洞 use 1查看需要配置的选项 show options设置目标 ip set rhost 10…

Leetcode—1726.同积元组【中等】

2023每日刷题&#xff08;六&#xff09; Leetcode—1726.同积元组 哈希表解题思路 实现代码 class Solution { public:int tupleSameProduct(vector<int>& nums) {unordered_map<int, int>count;int n nums.size();int i, j;for(i 0; i < n - 1; i) {f…

C语言实现单链表(图解增删查改+代码)

文章目录 写在前面1. 链表节点的定义2. 链表的创建3. 插入数据3.1 头插3.2 尾插3.3 在指定位置的前面插入数据 4. 删除数据4.1 头删4.2 尾删4.3 删除指定位置的数据 5. 查找数据5. 链表的销毁 写在前面 上面文章用C语言实现了顺序表的增删查改&#xff0c;本片文章继续用C语言…

web各个指标理解

QPS : 单位时间得请求次数 TPS &#xff1a;单位时间得事务数 并发 &#xff1a; QPS *单位响应时间 pv &#xff1a;进入一个网站&#xff0c;又单击打开该网站的其他页面&#xff0c;每打开一个页面就 增加一个PV,甚至在同一页面每刷新一次也多一个PV 二八定律&#xff1a;百…