logback ThrowableProxyConverter类源码流程解析
作者:odecraft
这篇文章主要为大家介绍了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的资料请关注脚本之家其它相关文章!