log4j异常堆栈文件输出
目的:log4j异常堆栈关联到traceId一句话中,方便搜索
1、获取堆栈后一起打印
private void logException(Throwable t, ProceedingJoinPoint joinPoint) {if (this.printErrorStackSys) {StringWriter sw = new StringWriter();PrintWriter pw = new PrintWriter(sw);t.printStackTrace(pw);String errorMsg = sw.toString();log.error("error->" + errorMsg);} else {// 子定义打印Signature signature = joinPoint.getSignature();String service = signature.toShortString();StringBuilder builder = new StringBuilder();builder.append("\r\n========================================== \r\n");builder.append("Invoke exception!!! \r\n");builder.append("Service = ").append(service).append("\r\n");Throwable cause = t.getCause();while (cause != null) {builder.append("\n\t\tCause: ").append(cause.getClass().getCanonicalName());builder.append(": ").append(cause.getMessage());cause = cause.getCause();}builder.append(" StackTrace=");StackTraceElement[] stackTraceElements = t.getStackTrace();for(int i = 0; i<stackTraceElements.length; i++){StackTraceElement stackTrace = stackTraceElements[i];builder.append(stackTrace.getClassName()).append(":").append(stackTrace.getMethodName()).append(":").append(stackTrace.getLineNumber()).append("\r\n;");}builder.append("\r\n==========================================");log.error(builder);}}
结果示例:
使用printStackTrace方法打印

自定义打印

2、使用%throwable打印堆栈跟踪信息
%throwable 用于在日志配置文件中输出异常的堆栈跟踪信息。
它不是 XML 的标准标签或属性,而是日志框架中的占位符
<!--控制台输出-->
<Console name="Console" target="SYSTEM_OUT"><PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS}|${ctx:uuid}|%t|%-5p|%c{1}:%L|%msg%n" /></Console>
<!--文件输出--><RollingFile name="RollingFile" filename="${logPath}/${rollingLogName}.log" filepattern="${logPath}/%d{yyyyMMdd}/${rollingLogName}-%i.log"><PatternLayout pattern='{"time":"%d{yyyy-MM-dd HH:mm:ss.SSS}","thread":"%t","tid":"${ctx:uuid}","level":"%-5p","class_line":"%c:%L","msg":"{%msg}%throwable"}%n'></PatternLayout><Policies><TimeBasedTriggeringPolicy interval="1" modulate="true" /><SizeBasedTriggeringPolicy size="1024 MB" /></Policies><DefaultRolloverStrategy max="100" /></RollingFile>
%d{HH:mm:ss,SSS} 表示日期和时间。
[%t] 表示线程名称。
%-5p 表示日志级别,左对齐,宽度为 5。
%c{1} 表示日志记录器的名称,只显示最后一级。
:%L 表示日志记录器的行号。
%m 表示日志消息。
%throwable 表示异常的堆栈跟踪信息。
%n 表示换行符。
结果示例:

3、自定义格式化插件
这种方式与2一样,2使用的是ThrowablePatternConverter
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.impl.LocationAware;
import org.apache.logging.log4j.core.pattern.ConverterKeys;
import org.apache.logging.log4j.core.pattern.ThrowablePatternConverter;@Plugin(name = "CustomerThrowablePatternConverter",category = "Converter"
)
@ConverterKeys({"ct", "customerThrowable"})public class CustomerThrowablePatternConverter extends ThrowablePatternConverter implements LocationAware {protected CustomerThrowablePatternConverter(String[] options, Configuration config) {super("CT", "CTStyle", options, config);}// 被触发的得到实例的方法public static CustomerThrowablePatternConverter newInstance(Configuration config, String[] options) {return new CustomerThrowablePatternConverter(options, config);}@Overridepublic void format(LogEvent event, StringBuilder buffer) {Throwable thrown = event.getThrown();if (thrown != null && thrown instanceof CustomerException) {buffer.append("自定义异常");}super.format(event, buffer);}// 位置信息@Overridepublic boolean requiresLocation() {return true;}
}
<PatternLayout pattern=‘{“tid”:“${ctx:uuid}”,“time”:“%d{yyyy-MM-dd HH:mm:ss.SSS}”,“thread”:“%t”,“level”:“%-5p”,“class_line”:“%c:%L”,“msg”:“%enc{%msg-%customerThrowable}{JSON}”}%n’>

4、源码分析
Disruptor 是一个高性能的无锁并发框架,常用于异步日志记录、消息传递等场景。
- LogEvent:表示一个日志事件的类,将要输出的日志上下文信息封装成事件。
public LogEvent createEvent(String loggerName, Marker marker, String fqcn, StackTraceElement location, Level level, Message data, List<Property> properties, Throwable t) {return new Log4jLogEvent(loggerName, marker, fqcn, location, level, data, properties, t);}
- RingBuffer:一个循环缓冲区,用于存储事件数据。
private static final EventTranslatorTwoArg<Log4jEventWrapper, LogEvent, AsyncLoggerConfig> TRANSLATOR = new EventTranslatorTwoArg<Log4jEventWrapper, LogEvent, AsyncLoggerConfig>() {public void translateTo(Log4jEventWrapper ringBufferElement, long sequence, LogEvent logEvent, AsyncLoggerConfig loggerConfig) {ringBufferElement.event = logEvent;ringBufferElement.loggerConfig = loggerConfig;}};
- Sequencer:负责管理和分配序列号的组件。 方法用于发布一个序列号,表示某个事件已经准备好,可以被消费者线程处理。发布后的消息通常由一个或多个消费者类(也称为事件处理器或 EventHandler)进行消费。
private <A, B> void translateAndPublish(EventTranslatorTwoArg<E, A, B> translator, long sequence, A arg0, B arg1) {try {translator.translateTo(this.get(sequence), sequence, arg0, arg1);} finally {this.sequencer.publish(sequence);}}
- EventHandler:负责处理事件的消费者类,定义了一个 onEvent 方法,该方法会在事件准备好后被调用。
public void onEvent(Log4jEventWrapper event, long sequence, boolean endOfBatch) throws Exception {event.event.setEndOfBatch(endOfBatch);// 去消费event.loggerConfig.logToAsyncLoggerConfigsOnCurrentThread(event.event);event.clear();this.notifyIntermediateProgress(sequence);}
5、主要流程
org.apache.logging.log4j.core.async.AsyncLoggerConfig#log
->org.apache.logging.log4j.core.Logger#logMessage
->org.apache.logging.log4j.core.config.LoggerConfig#log(java.lang.String, java.lang.String, org.apache.logging.log4j.Marker, org.apache.logging.log4j.Level, org.apache.logging.log4j.message.Message, java.lang.Throwable)
->org.apache.logging.log4j.core.config.AwaitCompletionReliabilityStrategy#log(org.apache.logging.log4j.util.Supplier<org.apache.logging.log4j.core.config.LoggerConfig>, java.lang.String, java.lang.String, org.apache.logging.log4j.Marker, org.apache.logging.log4j.Level, org.apache.logging.log4j.message.Message, java.lang.Throwable)
->org.apache.logging.log4j.core.appender.RollingFileAppender#append
->org.apache.logging.log4j.core.layout.PatternLayout#encode
->org.apache.logging.log4j.core.layout.PatternLayout.PatternSerializer#toSerializable(org.apache.logging.log4j.core.LogEvent, java.lang.StringBuilder)
->LogEventPatternConverter的子类进行格式化操作拼接打印日志输出
// 异步输出日志方法重写protected void log(LogEvent event, LoggerConfig.LoggerConfigPredicate predicate) {if (predicate == LoggerConfigPredicate.ALL && ASYNC_LOGGER_ENTERED.get() == Boolean.FALSE && this.hasAppenders()) {ASYNC_LOGGER_ENTERED.set(Boolean.TRUE);try {super.log(event, LoggerConfigPredicate.SYNCHRONOUS_ONLY);this.logToAsyncDelegate(event);} finally {ASYNC_LOGGER_ENTERED.set(Boolean.FALSE);}} else {super.log(event, predicate);}}
//父类的方法,1、同步日志调用, 2、EventHandler回调使用protected void log(LogEvent event, LoggerConfigPredicate predicate) {if (!this.isFiltered(event)) {this.processLogEvent(event, predicate);}}
// 日志处理--打印输出private void processLogEvent(LogEvent event, LoggerConfigPredicate predicate) {event.setIncludeLocation(this.isIncludeLocation());// 判断当前 !config instanceof AsyncLoggerConfig是否为非异步if (predicate.allow(this)) {// 打印处理this.callAppenders(event);}this.logParent(event, predicate);}
// 队列处理private void logToAsyncDelegate(LogEvent event) {if (!this.isFiltered(event)) {this.populateLazilyInitializedFields(event);// 发布序列号,添加到缓冲区if (!this.delegate.tryEnqueue(event, this)) {// 缓存区满了处理this.handleQueueFull(event);}}}public void format(LogEvent event, StringBuilder buf) {if (this.skipFormattingInfo) {this.converter.format(event, buf);} else {this.formatWithInfo(event, buf);}}
相关文章:
log4j异常堆栈文件输出
目的:log4j异常堆栈关联到traceId一句话中,方便搜索 1、获取堆栈后一起打印 private void logException(Throwable t, ProceedingJoinPoint joinPoint) {if (this.printErrorStackSys) {StringWriter sw new StringWriter();PrintWriter pw new Print…...
在配置环境变量之后使用Maven报错 : mvn : 无法将“mvn”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。
最近,我在 Windows 系统上安装和配置 Apache Maven 时遇到了一些问题,想在此记录下我的解决历程,希望对遇到类似问题的朋友有所帮助。 问题描述 我下载了 Maven 并按照常规步骤配置了相关的环境变量。然而,在 PowerShell 中输入…...
SpringSecurity源码中核心类
SpringSecurity源码 第一部分 核心类 SecurityBuilderHttpSecurityWebSecuritySecurityFilterChainFilterChainProxy SecurityBuilder是安全构架器,HttpSecurity和WebSecurity都是SecurityBuilder的实现类,HttpSecurity通过build()构建了一个Security…...
【JAVA】使用IDEA创建maven聚合项目
【JAVA】使用IDEA创建maven聚合项目 1.效果图 2.创建父模块项目 2.1删除父模块下面的src目录以及不需要的maven依赖 3创建子模块项目 3.1右击父模块项目选择Module… 3.2创建子模块 3.3删除子模块下不需要的maven依赖 4.子模块创建完成后引入SpringBoot依赖启动项目...
猿创征文|Inscode桌面IDE:打造高效开发新体验
猿创征文|Inscode桌面IDE:打造高效开发新体验 引言 在当今快速发展的软件开发领域,一个高效、易用的集成开发环境(IDE)是每个开发者必不可少的工具。Inscode 桌面 IDE 作为一款新兴的开发工具,凭借其强大…...
概率论中的PMF、PDF和CDF
在概率论中,PMF(概率质量函数)、PDF(概率密度函数)和CDF(累积分布函数)是描述随机变量分布的三个重要概念。它们分别用于不同类型的随机变量,并帮助我们理解随机事件的概率特性。本文…...
Vue 简单入手
前端工程化(Front-end Engineering)指的是在前端开发中,通过一系列工具、流程和规范的整合,以提高开发效率、代码质量和可维护性的一种技术和实践方法。其核心目的是使得前端开发变得更高效、可扩展和可维护。 文章目录 一、Vue 项…...
Github配置ssh key原理及操作步骤
文章目录 配置SSH第一步:检查本地主机是否已经存在ssh key第二步:生成ssh key第三步:获取ssh key公钥内容第四步:Github账号上添加公钥第五步:验证是否设置成功验证原理 往github上push项目的时候,如果走ht…...
大循环引起CPU负载过高
一、问题背景 环境:jdk1.8 tomcat7 在一次发布时,cpu出现负载过高,其负载突破200%,并且响应时间也大幅度超时。 二、问题分析 【1】发布前做过压测,并没有发现cpu异常升高的现象,所以其可能与生产环境的请…...
[Java]微服务治理
注册中心原理 注册中心可以统一管理项目中的所有服务 服务治理中的三个角色分别是什么? 服务提供者: 暴露服务接口,供其它服务调用服务消费者: 调用其它服务提供的接口注册中心: 记录并监控微服务各实例状态,推送服务变更信息 消费者如何知道提供者的…...
深入解析C语言中的extern关键字:语法、工作原理与高级应用技巧
引言 在C语言中,extern 关键字是一个强大的工具,用于声明外部变量和函数,使得这些变量和函数可以在多个源文件之间共享。理解 extern 的工作原理和最佳实践对于编写模块化、可维护的代码至关重要。本文将深入探讨 extern 关键字的各个方面&a…...
元器件封装
元器件封装类型 为什么越来越多用贴片元件,而不是插件元件 为什么越来越多用贴片元件,而不是插件元件 1.体积小、质量小、容易保存和运输; 2.容易焊接和拆卸。抗震效果好。 贴片元件不用过孔,用锡少。直插元件最麻烦的就是拆卸&a…...
状态空间方程离散化(Matlab符号函数)卡尔曼
// 卡尔曼滤波(4):扩展卡尔曼滤波 - 知乎 // // matlab 连续系统状态空间表达式的离散化&状态转移矩阵求解_matlab状态方程离散化-CSDN博客 // // // %https://blog.csdn.net/weixin_44051006/article/details/107007916 clear all; clc; syms R1 R2 C1 C…...
软件设计师-计算机网络
OSI网络模型 物理层,提供原始物理通路。数据交换的单位是二进制,bit,比特流,设备有中继器,集线器数据连输层,把原始不可靠的物理层链接变成无差错的数据通道,并解决多用户竞争问题。传送单位是帧ÿ…...
SpringBoot操作Elasticsearch
SpringBoot操作Elasticsearch SpringData框架简化Java代码连接ES的过程 官网:https://spring.io/projects/spring-data/ 以上列表中都是Spring Data支持连接的数据源 添加依赖 已经添加过了 <!--添加SpringDataES的依赖--><dependency><groupId&…...
阿里云aliyun gradle安装包下载地址
阿里云 查找你要下载的安装包 macports-distfiles-gradle安装包下载_开源镜像站-阿里云 https://mirrors.aliyun.com/macports/distfiles/gradle/gradle-8.9-bin.zip 腾讯 https://mirrors.cloud.tencent.com/gradle/ https://mirrors.cloud.tencent.com/gradle/ https…...
【设计模式】创建型设计模式-工厂模式的实现
工厂模式实现 定义例子UML类图理解Java代码实现总结 定义 工厂方法模式定义了一个接口用于创建对象,该模式由子类决定实例化哪个工厂类。该模式把类的实例化推迟到了子类。 例子 通过一个公共的类方法来管理画图对象的创建。 UML类图理解 Java代码实现 定义接口…...
【分布式】CAP理论
CAP定理的核心要点: CAP定理指出,任何一个分布式系统在面对网络分区(Partition)的情况下,最多只能同时满足以下三个特性中的两个: 一致性(Consistency): 所有节点在同一…...
市域社会治理现代化解决方案-2
1. 社会治理现代化背景 市域社会治理现代化旨在通过制度化、科学化、规范化、程序化和精细化的治理体系,实现社会治理能力的提升。该方案强调市一级的统筹协调和资源技术优势,以有效应对新型社会矛盾和风险挑战。 2. 社会治理面临的问题 当前社会治理在实践中存在诸多问题…...
谷歌浏览器的自动翻译功能如何开启
在当今全球化的网络环境中,能够流畅地浏览不同语言的网页是至关重要的。谷歌浏览器(Google Chrome)提供了一项强大的自动翻译功能,可以帮助用户轻松跨越语言障碍。本文将详细介绍如何开启和使用谷歌浏览器的自动翻译功能ÿ…...
翻译工具:AI跨语言执行任务
翻译工具:AI跨语言执行任务📝 本章学习目标:本章聚焦工具系统,让AI Agent具备丰富的执行能力。通过本章学习,你将全面掌握"翻译工具:AI跨语言执行任务"这一核心主题。一、引言:为什么…...
ArcGIS Pro 3.7 重磅升级!这四大模块更新,让GIS效率翻倍
ArcGIS Pro 3.7 正式发布,这次不仅性能大幅提升,还带来了 GeoAI 工具集、实时等高线、本地知识图谱等一系列“黑科技”。无论你是制图师、空间分析师还是开发者。 01 性能与生产力:更快、更顺、更好找 新增「分析地图」窗格 可量化评估地图的…...
React 性能优化:从 3 秒卡顿到 60 帧流畅,我做了这 5 件事
摘要 React 应用越做越大,卡顿问题越来越严重?本文分享 5 个亲测有效的性能优化方案,包括 React.memo 正确使用姿势、useMemo 依赖陷阱、虚拟列表实战、代码分割策略和 Profiler 调试技巧。每个方案都附带真实代码对比,帮你把页面…...
牛牛走迷宫【牛客tracker 每日一题】
牛牛走迷宫 时间限制:1秒 空间限制:256M 网页链接 牛客tracker 牛客tracker & 每日一题,完成每日打卡,即可获得牛币。获得相应数量的牛币,能在【牛币兑换中心】,换取相应奖品!助力每日有…...
工业AI落地:自定义数据集与交叉验证的动态选择策略
1. 这不是选择题,而是控制权与可信度的平衡术你手头刚攒够2000张标注好的工业缺陷图,模型在验证集上跑出了92.3%的准确率——但上线三天后,产线新批次的钢板表面反光角度变了,准确率直接掉到68%。或者,你用sklearn的St…...
Spring Boot + MyBatis服务启动流程,新增代码跑通流程,映射规则,常见问题定位
一、服务启动流程 零代码(仅需配置文件和依赖)。 顺序固定,由框架保证。 一旦某个步骤失败(如 XML 解析错误),整个启动失败。 二、新增代码跑通流程 全手动,需熟悉 MyBatis 映射规则、Spring…...
从录制到规划:手把手教你用CARLA录制点云,在Autoware中构建完整自动驾驶仿真闭环
从CARLA到Autoware:构建自定义自动驾驶仿真场景的完整实践指南 在自动驾驶技术快速迭代的今天,仿真测试已成为算法验证不可或缺的环节。CARLA与Autoware作为开源仿真平台和自动驾驶框架的黄金组合,为研究者提供了高度灵活的测试环境。本文将深…...
《纳瓦尔宝典》哲学篇精读:程序员的终极精神解药
本文是《纳瓦尔宝典》第五部分"哲学"的完整精读笔记,专为在技术洪流中迷失方向、陷入存在主义焦虑的程序员群体打造。纳瓦尔的哲学不是象牙塔里的空洞思辨,而是一套经过他亲身验证的、可落地的生活操作系统,能帮你在快速变化的世界…...
2025年AI数字人行业现状:全国超99万家企业涌入,真正能落地的不到一成
当生成式AI的浪潮席卷各行各业,AI数字人成为最先跑出商业化落地速度的细分赛道。然而,在全国超99万家相关企业蜂拥而入的热闹背后,一个残酷的现实正在显现:绝大多数所谓的"AI数字人"不过是披着科技外衣的"会动的照…...
AI-HF_Patch终极指南:3步解锁AI-Shoujo完整游戏体验的秘诀
AI-HF_Patch终极指南:3步解锁AI-Shoujo完整游戏体验的秘诀 【免费下载链接】AI-HF_Patch Automatically translate, uncensor and update AI-Shoujo! 项目地址: https://gitcode.com/gh_mirrors/ai/AI-HF_Patch 还在为AI-Shoujo游戏的语言障碍、模组冲突和功…...
