logback ThrowableProxyConverter类源码流程解析

 更新时间:2023年12月04日 08:38:41   作者: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&lt;ILoggingEvent&gt; ee) {
        if (evaluatorList == null) {
            evaluatorList = new ArrayList&lt;EventEvaluator&lt;ILoggingEvent&gt;&gt;();
        }
        evaluatorList.add(ee);
    }
addEvaluator则是添加到evaluatorList

addIgnoreStackTraceLine

private void addIgnoreStackTraceLine(String ignoredStackTraceLine) {
        if (ignoredStackTraceLines == null) {
            ignoredStackTraceLines = new ArrayList&lt;String&gt;();
        }
        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的资料请关注脚本之家其它相关文章!

相关文章

  • 一文详解如何在SpringMVC的视图中渲染模型数据

    一文详解如何在SpringMVC的视图中渲染模型数据

    SpringMVC是一个基于Spring框架的Web框架,它提供了一种方便的方式来处理 HTTP 请求和响应,在SpringMVC中,视图是用来渲染模型数据的组件,它们负责将模型数据转换为HTML、JSON、XML等格式的响应,在本文中,我们将讨论如何在SpringMVC中的视图中渲染模型数据
    2023-07-07
  • jenkins安装及其配置笔记

    jenkins安装及其配置笔记

    这篇文章主要介绍了jenkins安装及其配置笔记,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-01-01
  • SpringBoot接口调用之后报404问题的解决方案

    SpringBoot接口调用之后报404问题的解决方案

    这篇文章主要介绍了SpringBoot接口调用之后报404问题的解决方案,具有很好的参考价值,希望对大家有所帮助。
    2021-06-06
  • java用split分割字符串的一个有趣现象

    java用split分割字符串的一个有趣现象

    最近在项目中使用了java中的split分割字符串,发现了一个bug,充分了展示了自己对java底层的认知有很多的不足和欠缺。下面将这次的经过总结出来分享给大家,有需要的朋友们可以参考借鉴,下面来一起看看吧。
    2016-12-12
  • MyBatis Map结果的Key转为驼峰式

    MyBatis Map结果的Key转为驼峰式

    今天小编就为大家分享一篇关于MyBatis Map结果的Key转为驼峰式,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-12-12
  • Java实现视频时间维度剪切的工具类

    Java实现视频时间维度剪切的工具类

    这篇文章主要为大家详细介绍了将视频按照时间维度进行剪切的Java工具类,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起了解一下
    2022-12-12
  • 深入探讨Java多线程中的volatile变量

    深入探讨Java多线程中的volatile变量

    这篇文章主要为大家详细并深入的探讨Java多线程中的volatile变量,volatile用来确保将变量的更新操作通知到其他线程,保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新,感兴趣的小伙伴们可以参考一下
    2016-02-02
  • Java 栈与队列超详细分析讲解

    Java 栈与队列超详细分析讲解

    这篇文章主要介绍了Java数据结构中的栈与队列,在Java的时候,对于栈与队列的应用需要熟练的掌握,这样才能够确保Java学习时候能够有扎实的基础能力。本文小编就来详细说说Java中的栈与队列,需要的朋友可以参考一下
    2022-04-04
  • Mybatis Generator具体使用小技巧

    Mybatis Generator具体使用小技巧

    本文主要介绍了Mybatis Generator具体使用小技巧,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-12-12
  • Java8函数式编程应用小结

    Java8函数式编程应用小结

    Java8非常重要的就是引入了函数式编程的思想,使得这门经典的面向对象语言有了函数式的编程方式,弥补了很大程度上的不足,函数式思想在处理复杂问题上有着更为令人称赞的特性,本文给大家介绍Java8函数式编程应用小结,感兴趣的朋友一起看看吧
    2023-12-12

最新评论