java日志框架详解-Log4j2
一、概述
Apache Log4j 2 (Log4j – Apache Log4j 2)是对Log4j的升级,它比其前身Log4j 1.x提供了重大改进,并参考了Logback中优秀的设计,同时修复了Logback架构中的一些问题。被誉为是目前最优秀的Java日志框架;企业中通常使用SLF4j门面+Log4j2来记录日志。
Log4j2主要的性能提升:
异常处理:在logback中,Appender中的异常不会被应用感知到,但是在log4j2中,提供了一些异常处理机制。
性能提升:log4j2 相较于log4j 和 logback 都具有明显的性能提升,有18倍性能提升,后面会有官方测试的数据。
自动重载配置: 参考了logback的设计,当然会提供自动刷新参数配置,最实用的就是我们在生产上可以动态的修改日志的级别而不需要重启应用。
无垃圾机制: log4j2 在大部分情况下,都可以使用其设计的一套无垃圾机制【对象重用、内存缓冲】,避免频繁的日志收集导致的 jvm gc。
自动重新加载配置
与 Logback 一样,Log4j 2 可以在修改时自动重新加载其配置。与Logback不同,它会这样做 在进行重新配置时不会丢失日志事件。
高级过滤
与 Logback 一样,Log4j 2 支持基于上下文数据、标记、正则表达式和其他组件进行过滤 日志事件。可以指定筛选以在传递到记录器之前或通过时应用于所有事件 追加器。此外,过滤器还可以与记录器相关联。与 Logback 不同,您可以使用通用 Filter 类 在任何这些情况下。
二、Log4j2入门案例
开发实例:
如果您使用启动器来组装依赖项,这意味着您必须排除Logback,然后引入log4j2。
依赖引入POM.xml:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></exclusion></exclusions>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
Log4j2配置
log4j2默认加载classpath下的 log4j2.xml 文件中的配置。
<?xml version="1.0" encoding="UTF-8"?><!--status : 这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,会看到log4j2内部各种详细输出monitorInterval : Log4j能够自动检测修改配置文件和重新配置本身, 设置间隔秒数。此处表示每隔600秒重读一次配置文件
-->
<Configuration status="OFF" monitorInterval="600"><!--日志级别:TRACE < DEBUG < INFO < WARN < ERROR < FATAL--><!--如果设置为WARN,则低于WARN的信息都不会输出--><Properties><!-- 配置日志文件输出目录,此处为项目根目录下的logs文件夹 --><Property name="LOG_HOME">/app/applogs</Property><!-- 配置日志文件名称前缀 --><Property name="LOG_FILE_NAME">cu-upcc-ccc1-provider</Property><!-- 配置输出日志级别-通用日志 --><Property name="LOG_LEVEL">INFO</Property><!-- 配置输出日志级别-重要日志1 --><Property name="LOG_LEVEL_V1">DEBUG</Property><!-- 配置日志输出源appender的名称 --><Property name="APPENDER_NAME">APP-PROVIDER</Property><!-- 配置子Logger是否继承父Logger的输出源,true-是,false-否,默认true --><Property name="LOGGER_ADDITIVITY">true</Property><!-- 触发日志文件分割的时间间隔,此配置必须和filePattern协调, 如果后者是精确到HH, 则此配置项单位是小时,若后者精确到dd, 则此配置项单位是天--><Property name="POLICY_TIME_BASED_INTERVAL">1</Property><!-- 日志清理规则 从basePath起清理日志文件的目录层级深度 --><Property name="DELETE_MAX_DEPTH">1</Property><!-- 日志清理规则 文件名称匹配规则 --><Property name="DELETE_IF_FILE_NAME">*.log-*</Property><!-- 日志清理规则 归档日志文件存在时长匹配规则,此配置项必须和filePattern协调, 后者是精确到HH, 这里就要写成xH, xd就不起作用, 另外, 数字最好>2, 否则可能造成删除的时候, 最近的文件还处于被占用状态,导致删除不成功! --><Property name="DELETE_IF_LAST_MODIFIED_AGE">24H</Property></Properties><Appenders><!--这个输出控制台的配置--><Console name="Console" target="SYSTEM_OUT"><!--控制台只输出level及其以上级别的信息(onMatch),其他的直接拒绝(onMismatch)--><ThresholdFilter level="${LOG_LEVEL}" onMatch="ACCEPT" onMismatch="DENY"/><!--日志输出的格式--><PatternLayout pattern="|%d{yyyy-MM-dd HH:mm:ss.SSS}|%5p|%5t|%4c:%L|%X{PtxId}|%X{clientNodeName}|%X{serverNodeName}|%X{clientSysName}|%X{serverSysName}|%X{txId}|%X{logType}|%m|%n" /></Console><RollingRandomAccessFile name="${APPENDER_NAME}" fileName="${LOG_HOME}/${LOG_FILE_NAME}.log"filePattern="${LOG_HOME}/${LOG_FILE_NAME}.log-%d{yyyyMMddHH}"><PatternLayout pattern="|%d{yyyy-MM-dd HH:mm:ss.SSS}|%5p|%5t|%4c:%L|%X{PtxId}|%X{clientNodeName}|%X{serverNodeName}|%X{clientSysName}|%X{serverSysName}|%X{txId}|%X{logType}|%m|%n" /><Policies><TimeBasedTriggeringPolicy interval="${POLICY_TIME_BASED_INTERVAL}"/><!--<SizeBasedTriggeringPolicy size="50MB"/>--></Policies><DefaultRolloverStrategy><Delete basePath="${LOG_HOME}/" maxDepth="${DELETE_MAX_DEPTH}"><IfFileName glob="${DELETE_IF_FILE_NAME}" /><!--!Note: 这里的age必须和filePattern协调, 后者是精确到HH, 这里就要写成xH, xd就不起作用另外, 数字最好>2, 否则可能造成删除的时候, 最近的文件还处于被占用状态,导致删除不成功!--><IfLastModified age="${DELETE_IF_LAST_MODIFIED_AGE}" /></Delete></DefaultRolloverStrategy></RollingRandomAccessFile><!-- alarm plugins --><AlarmLog4j2Appender name="AlarmLog4j2Appender" enableApollo="true" apNameSpace="cu-upcc-ccc1-provider"><PatternLayout pattern="|%d{yyyy-MM-dd HH:mm:ss.SSS}|%m" /></AlarmLog4j2Appender></Appenders><!--然后定义logger,只有定义了logger并引入的appender,appender才会生效--><Loggers><Logger name="com.epay.cu1.upcc1.ccc1.provider" level="${LOG_LEVEL}" additivity="${LOGGER_ADDITIVITY}"><AppenderRef ref="${APPENDER_NAME}"/></Logger><Logger name="com.epay.ts.lacs.log" level="${LOG_LEVEL}" additivity="${LOGGER_ADDITIVITY}"><AppenderRef ref="${APPENDER_NAME}"/></Logger><Logger name="com.epay.ts.piss" level="${LOG_LEVEL}" additivity="${LOGGER_ADDITIVITY}"><AppenderRef ref="${APPENDER_NAME}"/></Logger><Logger name="org.springframework" level="${LOG_LEVEL}" additivity="${LOGGER_ADDITIVITY}"><AppenderRef ref="${APPENDER_NAME}"/></Logger><Logger name="com.ctrip.framework" level="${LOG_LEVEL}" additivity="${LOGGER_ADDITIVITY}"><AppenderRef ref="${APPENDER_NAME}"/></Logger><Logger name="org.apache" level="${LOG_LEVEL}" additivity="${LOGGER_ADDITIVITY}"><AppenderRef ref="${APPENDER_NAME}"/></Logger><Logger name="feign.Logger" level="${LOG_LEVEL}" additivity="${LOGGER_ADDITIVITY}"><AppenderRef ref="${APPENDER_NAME}"/></Logger><Logger name="com.alibaba.druid" level="${LOG_LEVEL}" additivity="${LOGGER_ADDITIVITY}"><AppenderRef ref="${APPENDER_NAME}"/></Logger><logger name="com.broad.assessment.business.dao" level="${LOG_LEVEL_V1}"><AppenderRef ref="${APPENDER_NAME}"/></logger><logger name="org.mybatis" level="${LOG_LEVEL_V1}"><AppenderRef ref="${APPENDER_NAME}"/></logger><logger name="com.unicompayment.basictools" level="${LOG_LEVEL_V1}"><AppenderRef ref="${APPENDER_NAME}"/></logger><!-- alarm plugins --><Logger name="com.epay.cu1.upcc1.ccc1.provider" level="${LOG_LEVEL}" additivity="${LOGGER_ADDITIVITY}"><AppenderRef ref="AlarmLog4j2Appender"/></Logger><Root level="${LOG_LEVEL}"><Appender-Ref ref="Console"/></Root></Loggers></Configuration>
测试代码:
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;public class Log4j2Test {private static final Logger logger = LogManager.getLogger();public Log4j2Test(){logger.info( "Hello World!" );}
}
三、Log4j2异步日志
Log4j2提供了两种实现日志的方式,一个是通过AsyncAppender,一个是通过AsyncLogger,分别对应前面我们说的Appender组件和Logger组件。
POM文件异步日志依赖添加:
<dependency><groupId>com.lmax</groupId><artifactId>disruptor</artifactId><version>3.3.4</version>
</dependency>
1、AsyncAppender有锁异步
异步日志是通过引用别的Appender来实现的,当有日志事件到达时,会开启另外一个线程来处理它们。需要注意的是,如果在Appender的时候出现异常,对应用来说是无法感知的。AsyncAppender应该在它引用的Appender之后配置,默认使用java.util.concurrent.ArrayBlockingQueue实现而不需要其它外部的类库。当使用此Appender的时候,在多线程的环境下需要注意,阻塞队列容易受到锁争用的影响,这可能会对性能产生影响。这时候,我们应该考虑使用无锁的异步记录器(AsyncLogger)
日志配置文件
<Configuration status="fatal" monitorInterval="30"><Properties><Property name="myPattern" value="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/></Properties><Appenders><Console name="ConsoleAppend" target="SYSTEM_OUT"><PatternLayout pattern="${myPattern}"/><!-- 只接受程序中DEBUG级别的日志进行处理--><ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/></Console><!--在Appenders标签内创建Async异步标签--><Async name="AsyncConsoleAppend"><!--指定当前Appenders标签内的哪个Appender需要设置异步并通过引用--><AppenderRef ref="ConsoleAppend"/></Async></Appenders><Loggers><Root level="ALL"><!--设置异步的Appender--><AppenderRef ref="AsyncConsoleAppend"/></Root></Loggers>
</Configuration>
2、AsyncLogger无锁日志
AsyncLogger才是log4j2实现异步最重要的功能体现,也是官方推荐的异步方式。它可以使得调用Logger.log返回的更快。你可以有两种选择:全局异步和混合异步。
全局异步:所有的日志都异步的记录,在配置文件上不用做任何改动,只需要在jvm启动的时候增加一个参数即可实现。
混合异步:你可以在应用中同时使用同步日志和异步日志,这使得日志的配置方式更加灵活。
虽然Log4j2提供以一套异常处理机制,可以覆盖大部分的状态,但是还是会有一小部分的特殊情况是无法完全处理的,比如我们如果是记录审计日志(特殊情况之一),那么官方就推荐使用同步日志的方式,而对于其它一些仅仅是记录一个程序日志的地方,使用异步日志将大幅提升性能,减少对应用本身的影响。混合异步的方式需要通过修改配置文件来实现,使用AsyncLogger标记配置。
全局异步:
<!-- 导入所需的依赖坐标 -->
<dependency><groupId>com.lmax</groupId><artifactId>disruptor</artifactId><version>3.4.4</version>
</dependency><!-- 在resources资源目录下创建log4j2.component.properties文件并编写配置 -->
Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
混合异步:
<Configuration status="fatal" monitorInterval="30"><Properties><Property name="myPattern" value="%d{HH:mm:ss.SSS} [%t] %L %-5level %logger{36} - %msg%n"/></Properties><Appenders><Console name="ConsoleAppend" target="SYSTEM_OUT"><PatternLayout pattern="${myPattern}"/><!-- 只接受程序中DEBUG级别的日志进行处理--><ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/></Console></Appenders><Loggers><!--创建一个自定义的异步Logger--><!--name:对com.xw当前及其子包下的全部类的日志记录走此异步方式--><!--includeLocation:表示去除日志上的行号信息--><!--注:配置多个Logger时需要设置additivty来取消继承RootLogger--><AsyncLoggger name="com.xw" level="INFO" includeLocation="false" additivty="false"><AppenderRef ref="ConsoleAppend"/></AsyncLoggger><!--RootLogger--><Root level="ALL"><!--设置异步的Appender--><AppenderRef ref="ConsoleAppend"/></Root></Loggers>
</Configuration>
相关文章:

java日志框架详解-Log4j2
一、概述 Apache Log4j 2 (Log4j – Apache Log4j 2)是对Log4j的升级,它比其前身Log4j 1.x提供了重大改进,并参考了Logback中优秀的设计,同时修复了Logback架构中的一些问题。被誉为是目前最优秀的Java日志框架&#x…...
C++中vector追加vector
在C中,如果你想将一个vector追加到另一个vector的后面,可以使用std::vector的成员函数insert或者std::copy,或者简单地使用std::vector的push_back方法逐个元素添加。这里我将展示几种常用的方法: 方法1:使用insert方…...
加一(66)
66. 加一 - 力扣(LeetCode) 解法: class Solution { public:vector<int> plusOne(vector<int>& digits) {bool plus_one true;for (int i digits.size() - 1; i > 0; --i) {if (plus_one) {int tmp digits[i] 1;if …...
远程连接-简化登录
vscode通过ssh连接远程服务器免密登录(图文)_vscode ssh-CSDN博客...
canvas的基本用法
canvas canvas元素简介 1.是个container元素<canvas width100 height100></canvas>,有开闭标签 2.有且只有width和height两个attribute,不需要写单位 canvas的基本使用 const canvasEl document.getElementById(canvas01) const ctx …...
Tailwind CSS - Tailwind CSS 引入(安装、初始化、配置、引入、构建、使用 Tailwind CSS)
一、Tailwind CSS 概述 Tailwind CSS 是一个功能优先的 CSS 框架,它提供了大量的实用类(utility classes),允许开发者通过组合这些类来快速构建用户界面 Tailwind CSS 与传统的 CSS 框架不同(例如,Bootstr…...
鸿蒙开发黑科技“stack叠层”替代customdialog
前一篇提到的问题,本篇博文提出了一个解决方案: arkui-x LongPressGesture触发customdialog踩坑记录-CSDN博客 前一段时间遇到的这个问题,通过排除法观察,锁定为customdialog组件有bug,极为容易挂死。不论如何调整使用方法,都还是会触发挂死。 反馈给arkui团队,说是在…...

FreeRTOS从入门到精通 第十五章(事件标志组)
参考教程:【正点原子】手把手教你学FreeRTOS实时系统_哔哩哔哩_bilibili 一、事件标志组简介 1、概述 (1)事件标志位是一个“位”,用来表示事件是否发生。 (2)事件标志组是一组事件标志位的集合&#x…...

智慧园区管理平台实现智能整合提升企业运营模式与管理效率
内容概要 在当今数字化的背景下,智慧园区管理平台正逐渐成为企业提升运营效率和管理模式的重要工具。这个平台汇聚了多种先进技术,旨在通过智能整合各类资源与信息,帮助企业实现全面的管理创新。 智慧园区管理平台不仅仅是一个数据处理工具…...
markdown公式特殊字符
个人学习笔记 根号 在 Markdown 中,要表示根号 3,可以使用 LaTeX 语法来实现。常见的有以下两种方式: 行内公式形式:使用一对美元符号 $ 将内容包裹起来,即 $\sqrt{3}$ ,在支持 LaTeX 语法渲染的 Markdow…...

【深度分析】微软全球裁员计划不影响印度地区,将继续增加当地就业机会
当微软的裁员刀锋掠过全球办公室时,班加罗尔的键盘声却愈发密集——这场资本迁徙背后,藏着数字殖民时代最锋利的生存法则。 表面是跨国公司的区域战略调整,实则是全球人才市场的地壳运动。微软一边在硅谷裁撤年薪20万美金的高级工程师&#x…...

学习数据结构(5)单向链表的实现
(1)头部插入 (2)尾部删除 (3)头部删除 (4)查找 (5)在指定位置之前插入节点 (6)在指定位置之后插入节点 (7)删除…...
刷题记录 HOT100回溯算法-5:22. 括号生成
题目:22. 括号生成 数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。 示例 1: 输入:n 3 输出:["((()))","(()())","(())()",…...
Keepalived高可用集群企业应用实例二
一、实现ipvs的高可用性 ipvs相关配置 虚拟服务器配置结构: virtual_server ip port { …… real_server { …… } real_server { …… } } virtual server (虚拟服务器)的定义格式 virtual_server ip port 定义虚拟主机ip地址及其端口 virtual_server …...
C++计算特定随机操作后序列元素乘积的期望
有一个长度为 n n n的序列 a 1 , a 2 , . . . , a n a_1,a_2,...,a_n a1,a2,...,an。初始序列的所有元素均为 0 0 0。再给定正整数 m m m、 c c c和 ( n − m 1 ) (n-m1) (n−m1)个正整数 b 1 , b 2 , . . . , b n − m 1 b_1,b_2,...,b_{n-m1} b1,b2,...,bn−m1…...
c++字母大小写转换
可以通过标准库中的 <algorithm> 和 <cctype> 头文件来实现大小写转换。以下是常用的方法: 1. 使用 std::transform 和 std::toupper/std::tolower 1.1 转换为大写 #include <iostream> #include <string> #include <algorithm> //…...
MySQL知识点总结(十六)
请说明在复制拓扑中,中继日志集和从属服务器状态日志的作用。 中继日志用来保存从主服务器接受的二进制日志,与二进制日志相同的格式存储,由服务器自动管理,在其全部内容重放后会自动删除。 从属服务器状态日志存储关于如何连接…...

Windows程序设计10:文件指针及目录的创建与删除
文章目录 前言一、文件指针是什么?二、设置文件指针的位置:随机读写,SetFilePointer函数1.函数说明2.函数实例 三、 目录的创建CreateDirectory四、目录的删除RemoveDirectory总结 前言 Windows程序设计10:文件指针及目录的创建与…...

geolocator包的功能和用法
文章目录 1 概念介绍2 使用方法3 示例代码4 体验分享 我们在上一章回中介绍了如何实现滑动菜单相关的内容,本章回中将介绍如何获取位置信息.闲话休提,让我们一起Talk Flutter吧。 1 概念介绍 我们在这里说的获取位置信息本质上是获取当前手机所在位置的…...

Node.js——body-parser、防盗链、路由模块化、express-generator应用生成器
个人简介 👀个人主页: 前端杂货铺 🙋♂️学习方向: 主攻前端方向,正逐渐往全干发展 📃个人状态: 研发工程师,现效力于中国工业软件事业 🚀人生格言: 积跬步…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...

初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式
今天是关于AI如何在教学中增强学生的学习体验,我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育,这并非炒作,而是已经发生的巨大变革。教育机构和教育者不能忽视它,试图简单地禁止学生使…...

iview框架主题色的应用
1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题,无需引入,直接可…...
掌握 HTTP 请求:理解 cURL GET 语法
cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...
学习一下用鸿蒙DevEco Studio HarmonyOS5实现百度地图
在鸿蒙(HarmonyOS5)中集成百度地图,可以通过以下步骤和技术方案实现。结合鸿蒙的分布式能力和百度地图的API,可以构建跨设备的定位、导航和地图展示功能。 1. 鸿蒙环境准备 开发工具:下载安装 De…...