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 skipped if (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则用于过滤包含这些的异常堆栈。
以上就是logback的ThrowableProxyConverter的详细内容,更多关于logback的ThrowableProxyConverter的资料请关注脚本之家其它相关文章!
相关文章
SpringBoot集成SwaggerUi以及启动时遇到的错误
这篇文章主要介绍了SpringBoot集成SwaggerUi以及启动时遇到的错误,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2020-06-06Java +Tomcat + SpringMVC实现页面访问示例解析
这篇文章主要介绍了Java +Tomcat + SpringMVC实现页面访问示例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2020-07-07一文详解Java中的可变对象(Mutable)与不可变对象(Immutable)
如何在 Java 中创建不可变对象?我以前以为所有对象都是不可变的,因为如果你改变一个 String 实例的内容,它总是会创建一个新的 String 对象并指向该对象,在本文中,我不仅将分享在 Java 中Immutable的步骤,还将讨论可变对象与不可变对象及其优缺点2023-11-11Spring Cloud OpenFeign实例介绍使用方法
Spring Cloud OpenFeign 对 Feign 进行了二次封装,使得在 Spring Cloud 中使用 Feign 的时候,可以做到使用 HTTP 请求访问远程服务,就像调用本地方法一样的,开发者完全感知不到这是在调用远程访问,更感知不到在访问 HTTP 请求2022-09-09springboot项目部署在linux上运行的两种方式小结
这篇文章主要介绍了springboot项目部署在linux上运行的两种方式小结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2021-07-07
最新评论