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的资料请关注脚本之家其它相关文章!

相关文章

  • java编程进行动态编译加载代码分享

    java编程进行动态编译加载代码分享

    这篇文章主要介绍了java编程进行动态编译加载代码分享,具有一定借鉴价值,需要的朋友可以参考下。
    2017-12-12
  • 浅谈Java对象禁止使用基本类型

    浅谈Java对象禁止使用基本类型

    本文主要介绍了浅谈Java对象禁止使用基本类型,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-02-02
  • Mapper层继承BaseMapper<T>需要引入的pom依赖方式

    Mapper层继承BaseMapper<T>需要引入的pom依赖方式

    这篇文章主要介绍了Mapper层继承BaseMapper<T>需要引入的pom依赖方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • Spring中自动装配的4种方式

    Spring中自动装配的4种方式

    今天小编就为大家分享一篇关于Spring中自动装配的4种方式,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-01-01
  • springmvc常用注解标签详解

    springmvc常用注解标签详解

    本篇文章主要介绍了springmvc常用注解标签详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • RabbitMQ的ACK确认机制保障消费端消息的可靠性详解

    RabbitMQ的ACK确认机制保障消费端消息的可靠性详解

    这篇文章主要介绍了RabbitMQ的ACK确认机制保障消费端消息的可靠性详解,简单来说,就是你必须关闭 RabbitMQ 的自动ack ,可以通过一个 api 来调用就行,然后每次你自己代码里确保处理完的时候,再在程序里 ack 一把,需要的朋友可以参考下
    2023-12-12
  • Java Lambda表达式语法及用法示例

    Java Lambda表达式语法及用法示例

    这篇文章主要给大家介绍了关于Java Lambda表达式语法及用法的相关资料,lambda表达式是JAVA8中提供的一种新的特性,它支持Java也能进行简单的"函数式编程",文中通过代码介绍的非常详细,需要的朋友可以参考下
    2023-10-10
  • Mybatis实现分表插件

    Mybatis实现分表插件

    随着系统的发展,数据量也会越来越大,分库分表可以有效的缓解数据库的压力,本文主要介绍了Mybatis实现分表插件,感兴趣的可以了解一下
    2021-05-05
  • shiro并发人数登录控制的实现代码

    shiro并发人数登录控制的实现代码

    在做项目中遇到这样的需求要求每个账户同时只能有一个人登录或几个人同时登录,如果是同时登录的多人,要么不让后者登录,要么踢出前者登录,怎么实现这样的功能呢?下面小编给大家带来了shiro并发人数登录控制的实现代码,一起看看吧
    2017-09-09
  • SpringBoot实现物品收藏功能

    SpringBoot实现物品收藏功能

    这篇文章主要介绍了SpringBoot实现物品收藏功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04

最新评论