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);
        }

    }

 

 

 

 

 

 

 

 

 

 

 

 

 

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