logback源碼分析-3.logger element

源碼基於logback 1.1.7java

logback.xml:緩存

<?xml version="1.0" encoding="UTF-8"?>
<configuration xmlns="http://www.padual.com/java/logback.xsd">

    <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>/Users/apple/Documents/UNKONESERVER/warn.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 按天回滾 daily -->
            <fileNamePattern>/Users/apple/Documents/UNKONESERVER/warn.%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- 日誌最大的保存天數 -->
            <maxHistory>2</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%msg%n</pattern>
        </encoder>
    </appender>

    <logger name="com.logback.test" level="debug"
            additivity="false">
        <appender-ref ref="WARN" />
    </logger>

    <root level="debug">
    </root>

</configuration>

下面分析loaback是如何解析logger元素的:app

1.當解析到[configuration][logger]的時候會觸發[configuration][logger]的startEvent方法,最終調用LoggerAction的begin方法:this

public void begin(InterpretationContext ec, String name, Attributes attributes) {
        // Let us forget about previous errors (in this object)
        inError = false;
        logger = null;

        LoggerContext loggerContext = (LoggerContext) this.context;
        //獲取logger name,這裏是com.logback.test
        String loggerName = ec.subst(attributes.getValue(NAME_ATTRIBUTE));

        if (OptionHelper.isEmpty(loggerName)) {
            inError = true;
            String aroundLine = getLineColStr(ec);
            String errorMsg = "No 'name' attribute in element " + name + ", around " + aroundLine;
            addError(errorMsg);
            return;
        }
        //根據loggerName獲取logger,下面會詳細分析
        logger = loggerContext.getLogger(loggerName);

        String levelStr = ec.subst(attributes.getValue(LEVEL_ATTRIBUTE));

        if (!OptionHelper.isEmpty(levelStr)) {
            if (ActionConst.INHERITED.equalsIgnoreCase(levelStr) || ActionConst.NULL.equalsIgnoreCase(levelStr)) {
                addInfo("Setting level of logger [" + loggerName + "] to null, i.e. INHERITED");
                logger.setLevel(null);
            } else {
                Level level = Level.toLevel(levelStr);
                addInfo("Setting level of logger [" + loggerName + "] to " + level);
                //設置logger級別,沒有設置的話默認用debug
                logger.setLevel(level);
            }
        }

        String additivityStr = ec.subst(attributes.getValue(ActionConst.ADDITIVITY_ATTRIBUTE));
        if (!OptionHelper.isEmpty(additivityStr)) {
            boolean additive = OptionHelper.toBoolean(additivityStr, true);
            addInfo("Setting additivity of logger [" + loggerName + "] to " + additive);
            //在本文中例子中,若是是false,那隻輸出com.logback.test對應logger的日誌
            //若是是true,不只會輸出com.logback.test對應logger的日誌,仍是輸出com.logback對應logger的日誌
            //若是com.logback對應的logger的additive也是true,那也會輸出上級logger日誌
            logger.setAdditive(additive);
        }
        ec.pushObject(logger);
    }

loggerContext.getLogger(loggerName):debug

public final Logger getLogger(final String name) {

        if (name == null) {
            throw new IllegalArgumentException("name argument cannot be null");
        }

        // if we are asking for the root logger, then let us return it without
        // wasting time
        if (Logger.ROOT_LOGGER_NAME.equalsIgnoreCase(name)) {
            return root;
        }

        int i = 0;
        Logger logger = root;

        // check if the desired logger exists, if it does, return it
        // without further ado.
        //從緩存中根據name獲取logger對象,首次是沒有值的
        Logger childLogger = (Logger) loggerCache.get(name);
        // if we have the child, then let us return it without wasting time
        if (childLogger != null) {
            return childLogger;
        }

        // if the desired logger does not exist, them create all the loggers
        // in between as well (if they don't already exist)
        //將loggerName按照.進行層級拆分,好比com.logback.test,會被查分紅com, com.logback ,com.logback.test三個childName。
        //而後根據這個三個childName去緩存中獲取對應的logger,沒有就建立,而後保存到緩存中。
        //該方法最後返回childName爲com.logback.test的logger。
        //每一個logger會保存它的父級logger。
        //每一個logger又會保存它的child logger,好比com對應的logger會保存com.logback對應的logger。
        //ROOT logger是最頂級logger,保存全部一級logger,好比com對應的logger,也是全部一級logger的父級logger。
        String childName;
        while (true) {
            int h = LoggerNameUtil.getSeparatorIndexOf(name, i);
            if (h == -1) {
                childName = name;
            } else {
                childName = name.substring(0, h);
            }
            // move i left of the last point
            i = h + 1;
            synchronized (logger) {
                childLogger = logger.getChildByName(childName);
                if (childLogger == null) {
                    childLogger = logger.createChildByName(childName);
                    loggerCache.put(childName, childLogger);
                    incSize();
                }
            }
            logger = childLogger;
            if (h == -1) {
                return childLogger;
            }
        }
    }

2.當[configuration][logger]的startEvent結束後,會觸發[configuration][logger][appender-ref]的startEvent,最終會調用AppenderRefAction的begin方法:日誌

public void begin(InterpretationContext ec, String tagName, Attributes attributes) {
        // Let us forget about previous errors (in this object)
        inError = false;

        // logger.debug("begin called");
        //獲取[configuraion][logger]對應的logger實例
        Object o = ec.peekObject();

        if (!(o instanceof AppenderAttachable)) {
            String errMsg = "Could not find an AppenderAttachable at the top of execution stack. Near [" + tagName + "] line " + getLineNumber(ec);
            inError = true;
            addError(errMsg);
            return;
        }

        AppenderAttachable<E> appenderAttachable = (AppenderAttachable<E>) o;
        //獲取appender name,本文例子的appender name爲WARN
        String appenderName = ec.subst(attributes.getValue(ActionConst.REF_ATTRIBUTE));

        if (OptionHelper.isEmpty(appenderName)) {
            // print a meaningful error message and return
            String errMsg = "Missing appender ref attribute in <appender-ref> tag.";
            inError = true;
            addError(errMsg);

            return;
        }
        //根據appender name獲取對應的appender實例
        HashMap<String, Appender<E>> appenderBag = (HashMap<String, Appender<E>>) ec.getObjectMap().get(ActionConst.APPENDER_BAG);
        Appender<E> appender = (Appender<E>) appenderBag.get(appenderName);

        if (appender == null) {
            String msg = "Could not find an appender named [" + appenderName + "]. Did you define it below instead of above in the configuration file?";
            inError = true;
            addError(msg);
            addError("See " + CoreConstants.CODES_URL + "#appender_order for more details.");
            return;
        }

        addInfo("Attaching appender named [" + appenderName + "] to " + appenderAttachable);
        //將appender實例存入logger中
        appenderAttachable.addAppender(appender);
    }

3.[configuration][logger][appender-ref]的startEvent結束後,觸發[configuration][logger][appender-ref]的endEvent,沒作任何事情。 4.接下來就是[configuration][logger]的endEvent了,但LoggerAction的end方法也沒作什麼事情。code

相關文章
相關標籤/搜索