聊聊logback的ThrowableProxyConverter

本文主要研究一下logback的ThrowableProxyConverter

ThrowableHandlingConverter

ch/qos/logback/classic/pattern/ThrowableHandlingConverter.java

/*** Converter which handle throwables should be derived from this class.**/
public abstract class ThrowableHandlingConverter extends ClassicConverter {boolean handlesThrowable() {return true;}
}

ThrowableHandlingConverter继承了ClassicConverter,其handlesThrowable方法返回true

ThrowableProxyConverter

ch/qos/logback/classic/pattern/ThrowableProxyConverter.java

public class ThrowableProxyConverter extends ThrowableHandlingConverter {protected static final int BUILDER_CAPACITY = 2048;int lengthOption;List<EventEvaluator<ILoggingEvent>> evaluatorList = null;List<String> ignoredStackTraceLines = null;int errorCount = 0;@SuppressWarnings("unchecked")public void start() {String lengthStr = getFirstOption();if (lengthStr == null) {lengthOption = Integer.MAX_VALUE;} else {lengthStr = lengthStr.toLowerCase();if ("full".equals(lengthStr)) {lengthOption = Integer.MAX_VALUE;} else if ("short".equals(lengthStr)) {lengthOption = 1;} else {try {lengthOption = Integer.parseInt(lengthStr);} catch (NumberFormatException nfe) {addError("Could not parse [" + lengthStr + "] as an integer");lengthOption = Integer.MAX_VALUE;}}}final List<String> optionList = getOptionList();if (optionList != null && optionList.size() > 1) {final int optionListSize = optionList.size();for (int i = 1; i < optionListSize; i++) {String evaluatorOrIgnoredStackTraceLine = (String) optionList.get(i);Context context = getContext();Map<String, EventEvaluator<?>> evaluatorMap = (Map<String, EventEvaluator<?>>) context.getObject(CoreConstants.EVALUATOR_MAP);EventEvaluator<ILoggingEvent> ee = (EventEvaluator<ILoggingEvent>) evaluatorMap.get(evaluatorOrIgnoredStackTraceLine);if (ee != null) {addEvaluator(ee);} else {addIgnoreStackTraceLine(evaluatorOrIgnoredStackTraceLine);}}}super.start();}//......
}    

ThrowableProxyConverter继承了ThrowableHandlingConverter,其start方法会先读取getFirstOption,该参数为lengthOption,为null则取Integer.MAX_VALUE,若为full则取Integer.MAX_VALUE,为short取1,其他的则解析该值,出现异常则取Integer.MAX_VALUE;之后取optionList的其他值,先通过evaluatorMap来取,若EventEvaluator不为null则执行addEvaluator,否则执行addIgnoreStackTraceLine

addEvaluator

    private void addEvaluator(EventEvaluator<ILoggingEvent> ee) {if (evaluatorList == null) {evaluatorList = new ArrayList<EventEvaluator<ILoggingEvent>>();}evaluatorList.add(ee);}

addEvaluator则是添加到evaluatorList

addIgnoreStackTraceLine

    private void addIgnoreStackTraceLine(String ignoredStackTraceLine) {if (ignoredStackTraceLines == null) {ignoredStackTraceLines = new ArrayList<String>();}ignoredStackTraceLines.add(ignoredStackTraceLine);}

addIgnoreStackTraceLine则是添加到ignoredStackTraceLines

convert

    public String convert(ILoggingEvent event) {IThrowableProxy tp = event.getThrowableProxy();if (tp == null) {return CoreConstants.EMPTY_STRING;}// an evaluator match will cause stack printing to be skippedif (evaluatorList != null) {boolean printStack = true;for (int i = 0; i < evaluatorList.size(); i++) {EventEvaluator<ILoggingEvent> ee = evaluatorList.get(i);try {if (ee.evaluate(event)) {printStack = false;break;}} catch (EvaluationException eex) {errorCount++;if (errorCount < CoreConstants.MAX_ERROR_COUNT) {addError("Exception thrown for evaluator named [" + ee.getName() + "]", eex);} else if (errorCount == CoreConstants.MAX_ERROR_COUNT) {ErrorStatus errorStatus = new ErrorStatus("Exception thrown for evaluator named [" + ee.getName() + "].", this, eex);errorStatus.add(new ErrorStatus("This was the last warning about this evaluator's errors."+ "We don't want the StatusManager to get flooded.", this));addStatus(errorStatus);}}}if (!printStack) {return CoreConstants.EMPTY_STRING;}}return throwableProxyToString(tp);}

convert方法先从event获取IThrowableProxy,若为null则返回空字符串;之后判断evaluatorList是否为null,不为null则遍历挨个执行evaluate(event),若为true则printStack设置为false,跳出循环,当printStack为false时,返回空字符串,否则通过throwableProxyToString转为字符串返回

throwableProxyToString

    protected String throwableProxyToString(IThrowableProxy tp) {StringBuilder sb = new StringBuilder(BUILDER_CAPACITY);recursiveAppend(sb, null, ThrowableProxyUtil.REGULAR_EXCEPTION_INDENT, tp);return sb.toString();}private void recursiveAppend(StringBuilder sb, String prefix, int indent, IThrowableProxy tp) {if (tp == null)return;subjoinFirstLine(sb, prefix, indent, tp);sb.append(CoreConstants.LINE_SEPARATOR);subjoinSTEPArray(sb, indent, tp);IThrowableProxy[] suppressed = tp.getSuppressed();if (suppressed != null) {for (IThrowableProxy current : suppressed) {recursiveAppend(sb, CoreConstants.SUPPRESSED, indent + ThrowableProxyUtil.SUPPRESSED_EXCEPTION_INDENT, current);}}recursiveAppend(sb, CoreConstants.CAUSED_BY, indent, tp.getCause());}

throwableProxyToString主要是递归执行recursiveAppend,它先执行subjoinFirstLine、再执行subjoinSTEPArray、最后继续递归

subjoinSTEPArray

    protected void subjoinSTEPArray(StringBuilder buf, int indent, IThrowableProxy tp) {StackTraceElementProxy[] stepArray = tp.getStackTraceElementProxyArray();int commonFrames = tp.getCommonFrames();boolean unrestrictedPrinting = lengthOption > stepArray.length;int maxIndex = (unrestrictedPrinting) ? stepArray.length : lengthOption;if (commonFrames > 0 && unrestrictedPrinting) {maxIndex -= commonFrames;}int ignoredCount = 0;for (int i = 0; i < maxIndex; i++) {StackTraceElementProxy element = stepArray[i];if (!isIgnoredStackTraceLine(element.toString())) {ThrowableProxyUtil.indent(buf, indent);printStackLine(buf, ignoredCount, element);ignoredCount = 0;buf.append(CoreConstants.LINE_SEPARATOR);} else {++ignoredCount;if (maxIndex < stepArray.length) {++maxIndex;}}}if (ignoredCount > 0) {printIgnoredCount(buf, ignoredCount);buf.append(CoreConstants.LINE_SEPARATOR);}if (commonFrames > 0 && unrestrictedPrinting) {ThrowableProxyUtil.indent(buf, indent);buf.append("... ").append(tp.getCommonFrames()).append(" common frames omitted").append(CoreConstants.LINE_SEPARATOR);}}

subjoinSTEPArray遍历StackTraceElementProxy数组,然后挨个判断isIgnoredStackTraceLine,若为false才执行printStackLine

isIgnoredStackTraceLine

    private boolean isIgnoredStackTraceLine(String line) {if (ignoredStackTraceLines != null) {for (String ignoredStackTraceLine : ignoredStackTraceLines) {if (line.contains(ignoredStackTraceLine)) {return true;}}}return false;}

isIgnoredStackTraceLine主要是判断指定line是否包含了ignoredStackTraceLines,包含其中一个即返回true

小结

logback的ThrowableProxyConverter继承了ThrowableHandlingConverter,它定义了evaluatorList、ignoredStackTraceLines属性,它将继承自DynamicConverter的optionList做了划分,第一个option为打印异常堆栈的数,之后的option优先作为evaluatorList,若解析为evaluator为null则作为ignoredStackTraceLines参数。evaluatorList用于evaluate(event),若有个返回true则返回空字符串,而ignoredStackTraceLines则用于过滤包含这些的异常堆栈。

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

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

相关文章

面试官:说说Vue中Proxy与Object.defineProperty的用法与区别

前言 面试时&#xff0c;我们说完Vue响应式原理&#xff0c;或者Vue2和Vue3的区别时&#xff0c;通常会引出Vue3使用了Proxy来优化响应式&#xff0c;而面试官会继续深挖&#xff1a;说说Proxy与Object.defineProperty的区别。 我们不能只说Proxy直接代理一个对象&#xff0c…

带头双向循环链表:一种高效的数据结构

&#x1f493; 博客主页&#xff1a;江池俊的博客⏩ 收录专栏&#xff1a;数据结构探索&#x1f449;专栏推荐&#xff1a;✅cpolar ✅C语言进阶之路&#x1f4bb;代码仓库&#xff1a;江池俊的代码仓库&#x1f525;编译环境&#xff1a;Visual Studio 2022&#x1f389;欢迎大…

基于maobox-gl 纯前端绘制全球色斑图

基于maobox-gl.js、turf.js 绘制全球色斑图绘制 1、准备全球的某一类的点位数据&#xff0c;可以使用turf.js 随机生成点&#xff0c;并点数据赋properties属性 let points turf.randomPoint(30, { bbox: [-180, -90, 180, 90]}); let interpolateOptions {gridType: "…

Linux下Python调用C语言

一&#xff1a;Python调用C语言场景 1&#xff0c;已经写好的C语言代码&#xff0c;不容易用Python实现&#xff0c;想直接通过Python调用写好的C语言代码 2&#xff0c;C比Python快&#xff08;只是从语言层面&#xff0c;不能绝对说C程序就是比Python快&#xff09; 3&…

某音订单接口在电商行业中的重要性及实践应用

一、引言 随着移动互联网的快速发展&#xff0c;短视频平台抖音已经成为人们日常生活中不可或缺的一部分。越来越多的商家开始利用抖音平台推广和销售商品&#xff0c;从而实现商业变现。在这个过程中&#xff0c;抖音订单接口起到了至关重要的作用。本文将详细探讨抖音订单接…

希尔排序(Java)

目录 希尔排序的步骤&#xff1a; Java实现希尔排序&#xff1a; 希尔排序&#xff08;Shell Sort&#xff09;是一种插入排序的改进算法&#xff0c;它通过比较距离较远的元素交换位置&#xff0c;从而实现数据局部的较小规模排序&#xff0c;逐渐减小元素之间的间隔&#x…

遥感方向期刊总结

开眼看期刊~ 期刊分区信息搜索网址中国科学院文献情报中心期刊分区表升级版科研通期刊查询&#xff1a; 遥感领域常见期刊Nature CommunicationsRemote Sensing of EnvironmentProceedings of the National Academy of Sciences &#xff08;PNAS&#xff09;ISPRS Journal of …

C++ day50 买卖股票最佳时机

题目1&#xff1a;123 买卖股票的最佳时机Ⅲ 题目链接&#xff1a;买卖股票的最佳时机Ⅲ 对题目的理解 prices[i]表示股票在第i天的价格&#xff0c;最多可以完成两笔交易&#xff0c;不能同时进行多笔交易 可以买卖一次&#xff0c;两次&#xff0c;也可以不买卖 动态规划…

[字符串操作] 分割乘积

​ 分割乘积 题目描述 给定一个整数&#xff0c;求插入两个乘号将该整数分割成三个数之后&#xff0c;三个数的的最大乘积。 关于输入 只有一行&#xff0c;一个整数。 关于输出 所求出的最大乘积。 例子输入 4242例子输出 336提示信息 整数有正有负&#xff0c;注意&…

yolov5 7.0版本部署手机端。通过pnnx导出ncnn。

yolov5 7.0版本部署手机端。通过pnnx导出ncnn。 流程配置ncnn android yolov5导出自己模型的ncnn修改yolo.py文件导出TorchScript文件pnnx转torchscript为ncnn 安卓运行权重路径输入输出anchors 大小类别名generate_proposals方法修改 结果 流程 网络yolov5 的部署已经有很多了…

最新最全的Postman接口测试: postman实现参数化

什么时候会用到参数化 比如&#xff1a;一个模块要用多组不同数据进行测试 验证业务的正确性 Login模块&#xff1a;正确的用户名&#xff0c;密码 成功&#xff1b;错误的用户名&#xff0c;正确的密码 失败 postman实现参数化 在实际的接口测试中&#xff0c;部分参数…

Redis Cluster

概念 Redis Cluster采用多主多从的方式&#xff0c;支持开启多个主节点&#xff0c;每个主节点可以挂载多个从节点。 Cluster会将数据进行分片&#xff0c;将数据分散到多个主节点上&#xff0c;而每个主节点都可以对外提供读写服务。这种做法使得Redis突破了单机内存大小的限制…

2023第二届全国大学生数据分析大赛AB题代码

看大家需求量比较大&#xff0c;所以更新了一下A、B题的示例代码&#xff0c;部分截图如下 A题部分截图 B题部分截图 免费获取代码 关注威信公众号 Python风控模型与数据分析&#xff0c;回复 23年数据分析大赛代码 文末查看如何免费获取代码&#xff1b;编写不易&#xff0c;…

低效的DOM操作(js的问题)

使用 JavaScript 操作DOM&#xff08;即添加、修改和删除元素&#xff09;是相对容易&#xff0c;但操作效率却不怎么样。 比如&#xff0c;每次添加一系列DOM元素。添加一个DOM元素是一个昂贵的操作。连续添加多个DOM元素的代码是低效的。 当需要添加多个DOM元素时&#xff…

【数据结构】AOV网与拓扑排序

一.AOV网的概念&#xff08;Activity On Vertex Network&#xff09; 在一个表示工程的有向图中&#xff0c;用顶点表示活动&#xff0c;用弧表示活动之间的优先关系。这样的有向图为顶点表示活动的网&#xff0c;我们称为AOV网&#xff08;Activity On Vertex Network&#xf…

scikit-learn线性回归法进行利润预测

大家好&#xff0c;生成式人工智能无疑是一个改变游戏规则的技术&#xff0c;但对于大多数商业问题来说&#xff0c;回归和分类等传统的机器学习模型仍然是首选。 私募股权或风险投资这样的投资者利用机器学习&#xff0c;首先必须了解关注的数据以及它是如何被使用的。投资公…

anaconda 笔记:安装anaconda之后显示conda command not found

解决方法是在.bashrc文件中添加如下一行文字&#xff08;如果没有.bashrc文件&#xff0c;就在root中新建一个这个文件&#xff09; export PATH$PATH:/home/Your_name/anaconda3/bin也就是安装anaconda3的路径 然后退出编辑&#xff0c;在命令行中敲入 source ~/.bashrc即可…

云原生Kubernetes系列 | init container初始化容器的作用

云原生Kubernetes系列 | init container初始化容器的作用 kubernetes 1.3版本引入了init container初始化容器特性。主要用于在启动应用容器(app container)前来启动一个或多个初始化容器,作为应用容器的一个基础。只有init container运行正常后,app container才会正常运行…

Spring——IOC,DI,AOP

Spring框架是一个轻量级的Java开发框架&#xff0c;它提供了许多功能强大的特性来简化Java应用程序的开发。其中&#xff0c;IOC&#xff08;控制反转&#xff09;、DI&#xff08;依赖注入&#xff09;和AOP&#xff08;面向切面编程&#xff09;是Spring框架的三大核心特性。…

k8s安装学习环境

目录 环境准备 配置hosts 关闭防火墙 关闭交换分区 调整swappiness参数 关闭setlinux Ipv4转发 时钟同步 安装Docker 配置Yum源 安装 配置 启动 日志 安装k8s 配置Yum源 Master节点 安装 初始化 配置kubectl 部署CNI网络插件 Node节点 检查 环境准备 准…