Log處理(一)_Slf4j

一:簡介

1.因爲最近在搭建一個項目,需要用到ELK框架+filebeat,來整理、分析和可視化日誌,所以就花些時間一併消化整理了;

2.slf4j的官網文檔的解釋:它是一系列日誌框架的簡單的外觀或者抽象,比如logback和log4j;它允許使用者在部署時去插入需要的日誌框架;而且你的應用啓用SLF4J,只需要一個額外的依賴:slf4j-api-xxxx.jar。

The Simple Logging Facade for Java (SLF4J) serves as a simple facade or abstraction for various logging frameworks, such as java.util.logging, logback and log4j. SLF4J allows the end-user to plug in the desired logging framework at deployment time. Note that SLF4J-enabling your library/application implies the addition of only a single mandatory dependency, namely slf4j-api-1.7.21.jar.

3.加載失敗的日誌,下文是沒有找到對應配置的例子,會直接使用logback.classic的默認配置:

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/Users/xxxx/.m2/repository/ch/qos/logback/logback-classic/1.1.11/logback-classic-1.1.11.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/Users/xxxx/.m2/repository/org/slf4j/slf4j-log4j12/1.7.25/slf4j-log4j12-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]

4.slf4加載成功的日誌:下文就是正確加載logback的例子,在其路徑下配置了logback-test.xml之後,slf4j會找到對應的配置文件,並加載配置;

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/Users/xxxx/.m2/repository/ch/qos/logback/logback-classic/1.1.11/logback-classic-1.1.11.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/Users/xxxx/.m2/repository/org/slf4j/slf4j-log4j12/1.7.25/slf4j-log4j12-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.

17:23:15,953 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]
17:23:15,953 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback-test.xml] at [file:/Users/xxxx/xxxx/target/classes/logback-test.xml]
17:23:16,075 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - debug attribute not set
17:23:16,085 |-INFO in ch.qos.logback.core.joran.util.ConfigurationWatchListUtil@1df8b5b8 - Adding [jar:file:/Users/xxxx/.m2/repository/org/springframework/boot/spring-boot/1.5.9.RELEASE/spring-boot-1.5.9.RELEASE.jar!/org/springframework/boot/logging/logback/defaults.xml] to configuration watch list.
17:23:16,085 |-INFO in ch.qos.logback.core.joran.spi.ConfigurationWatchList@23202fce - URL [jar:file:/Users/xxxx/.m2/repository/org/springframework/boot/spring-boot/1.5.9.RELEASE/spring-boot-1.5.9.RELEASE.jar!/org/springframework/boot/logging/logback/defaults.xml] is not of type file

二:配置生效過程

1.使用方法,一般的獲取Logger是用下面的方式:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

private final Logger logger = LoggerFactory.getLogger(getClass());

2.在應用程序啓動中,會去調用上面的方法,這個時候Slf4j就會去搜索對應的配置,並加載,詳情見下面LoggerFactory的實現:

    public static Logger getLogger(Class<?> clazz) {
        Logger logger = getLogger(clazz.getName());
        if (DETECT_LOGGER_NAME_MISMATCH) {
            Class<?> autoComputedCallingClass = Util.getCallingClass();
            if (autoComputedCallingClass != null && nonMatchingClasses(clazz, autoComputedCallingClass)) {
                Util.report(String.format("Detected logger name mismatch. Given name: \"%s\"; computed name: \"%s\".", logger.getName(), autoComputedCallingClass.getName()));
                Util.report("See http://www.slf4j.org/codes.html#loggerNameMismatch for an explanation");
            }
        }

        return logger;
    }

public static Logger getLogger(String name) {
/*獲取到對應的Logger工廠類*/
        ILoggerFactory iLoggerFactory = getILoggerFactory();
/*利用實際的工廠類,加載logger*/
        return iLoggerFactory.getLogger(name);
    }
public static ILoggerFactory getILoggerFactory() {
/*保證只初始化一次*/
        if (INITIALIZATION_STATE == 0) {
            Class var0 = LoggerFactory.class;
            synchronized(LoggerFactory.class) {
                if (INITIALIZATION_STATE == 0) {
/*Double check*/
                    INITIALIZATION_STATE = 1;
                    performInitialization();
                }
            }
        }

        switch(INITIALIZATION_STATE) {
/*如果沒有綁定,則返回默認工廠*/
        case 1:
            return SUBST_FACTORY;
        case 2:
/*異常*/
            throw new IllegalStateException("org.slf4j.LoggerFactory in failed state. Original exception was thrown EARLIER. See also http://www.slf4j.org/codes.html#unsuccessfulInit");
/*找到合適的Logger實現類*/
        case 3:
            return StaticLoggerBinder.getSingleton().getLoggerFactory();
        case 4:
/*沒有返回*/
            return NOP_FALLBACK_FACTORY;
/*異常*/
        default:
            throw new IllegalStateException("Unreachable code");
        }
/*執行初始化*/
private static final void performInitialization() {
/*先去尋找可綁定的Logger實現*/
        bind();
        if (INITIALIZATION_STATE == 3) {
            versionSanityCheck();
        }
    }

3.在bind函數中,Slf4j會去搜索,並綁定Logger實現;

    private static final void bind() {
        String msg;
        try {
            Set<URL> staticLoggerBinderPathSet = null;
/*如果不是Android,則去尋找可用的Logger綁定路徑*/
            if (!isAndroid()) {
                staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet();
/*如果有多個可用的,去打印*/
                reportMultipleBindingAmbiguity(staticLoggerBinderPathSet);
            }
/*設置默認的Logger實現類*/
            StaticLoggerBinder.getSingleton();
/*表示找到合適的Logger實現類*/
            INITIALIZATION_STATE = 3;
/*打印實際使用的Logger,並綁定合適的Logger*/
            reportActualBinding(staticLoggerBinderPathSet);
            fixSubstituteLoggers();
            replayEvents();
            SUBST_FACTORY.clear();
        } catch (NoClassDefFoundError var2) {
            msg = var2.getMessage();
            if (!messageContainsOrgSlf4jImplStaticLoggerBinder(msg)) {
                failedBinding(var2);
                throw var2;
            }

            INITIALIZATION_STATE = 4;
            Util.report("Failed to load class \"org.slf4j.impl.StaticLoggerBinder\".");
            Util.report("Defaulting to no-operation (NOP) logger implementation");
            Util.report("See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.");
        } catch (NoSuchMethodError var3) {
            msg = var3.getMessage();
            if (msg != null && msg.contains("org.slf4j.impl.StaticLoggerBinder.getSingleton()")) {
                INITIALIZATION_STATE = 2;
                Util.report("slf4j-api 1.6.x (or later) is incompatible with this binding.");
                Util.report("Your binding is version 1.5.5 or earlier.");
                Util.report("Upgrade your binding to version 1.6.x.");
            }

            throw var3;
        } catch (Exception var4) {
            failedBinding(var4);
            throw new IllegalStateException("Unexpected initialization failure", var4);
        }

    }

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章