LoggingApplicationListener

org.springframework.boot:spring-boot:1.3.0.M1

spring-boot-1.3.0.M1.jar

package org.springframework.boot.logging;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.ApplicationPid;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.GenericApplicationListener;
import org.springframework.core.Ordered;
import org.springframework.core.ResolvableType;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;

/**
 * An {@link ApplicationListener} that configures the {@link LoggingSystem}. If the
 * environment contains a {@code logging.config} property a then that will be used to
 * initialize the logging system, otherwise a default configuration is used.
 * <p>
 * By default, log output is only written to the console. If a log file is required the
 * {@code logging.path} and {@code logging.file} properties can be used.
 * <p>
 * Some system properties may be set as side effects, and these can be useful if the
 * logging configuration supports placeholders (i.e. log4j or logback):
 * <ul>
 * <li>{@code LOG_FILE} is set to the value of path of the log file that should be written
 * (if any).</li>
 * <li>{@code PID} is set to the value of the current process ID if it can be determined.</li>
 * </ul>
 *
 * @author Dave Syer
 * @author Phillip Webb
 * @author Andy Wilkinson
 * @see LoggingSystem#get(ClassLoader)
 */
public class LoggingApplicationListener implements GenericApplicationListener {

    /**
     * The name of the Spring property that contains a reference to the logging
     * configuration to load.
     */
    public static final String CONFIG_PROPERTY = "logging.config";

    /**
     * The name of the Spring property that contains the path where the logging
     * configuration can be found.
     */
    public static final String PATH_PROPERTY = LogFile.PATH_PROPERTY;

    /**
     * The name of the Spring property that contains the name of the logging configuration
     * file.
     */
    public static final String FILE_PROPERTY = LogFile.FILE_PROPERTY;

    /**
     * The name of the System property that contains the process ID.
     */
    public static final String PID_KEY = "PID";

    private static MultiValueMap<LogLevel, String> LOG_LEVEL_LOGGERS;
    static {
        LOG_LEVEL_LOGGERS = new LinkedMultiValueMap<LogLevel, String>();
        LOG_LEVEL_LOGGERS.add(LogLevel.DEBUG, "org.springframework.boot");
        LOG_LEVEL_LOGGERS.add(LogLevel.TRACE, "org.springframework");
        LOG_LEVEL_LOGGERS.add(LogLevel.TRACE, "org.apache.tomcat");
        LOG_LEVEL_LOGGERS.add(LogLevel.TRACE, "org.apache.catalina");
        LOG_LEVEL_LOGGERS.add(LogLevel.TRACE, "org.eclipse.jetty");
        LOG_LEVEL_LOGGERS.add(LogLevel.TRACE, "org.hibernate.tool.hbm2ddl");
        LOG_LEVEL_LOGGERS.add(LogLevel.DEBUG, "org.hibernate.SQL");
    }

    private static Class<?>[] EVENT_TYPES = { ApplicationStartedEvent.class,
            ApplicationEnvironmentPreparedEvent.class, ContextClosedEvent.class };

    private static Class<?>[] SOURCE_TYPES = { SpringApplication.class,
            ApplicationContext.class };

    private final Log logger = LogFactory.getLog(getClass());

    private LoggingSystem loggingSystem;

    private int order = Ordered.HIGHEST_PRECEDENCE + 11;

    private boolean parseArgs = true;

    private LogLevel springBootLogging = null;

    @Override
    public boolean supportsEventType(ResolvableType resolvableType) {
        return isAssignableFrom(resolvableType.getRawClass(), EVENT_TYPES);
    }

    @Override
    public boolean supportsSourceType(Class<?> sourceType) {
        return isAssignableFrom(sourceType, SOURCE_TYPES);
    }

    private boolean isAssignableFrom(Class<?> type, Class<?>... supportedTypes) {
        if (type != null) {
            for (Class<?> supportedType : supportedTypes) {
                if (supportedType.isAssignableFrom(type)) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof ApplicationStartedEvent) {
            onApplicationStartedEvent((ApplicationStartedEvent) event);
        }
        else if (event instanceof ApplicationEnvironmentPreparedEvent) {
            onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);
        }
        else if (event instanceof ContextClosedEvent) {
            onContextClosedEvent();
        }
    }

    private void onApplicationStartedEvent(ApplicationStartedEvent event) {
        this.loggingSystem = LoggingSystem.get(event.getSpringApplication()
                .getClassLoader());
        this.loggingSystem.beforeInitialize();
    }

    private void onApplicationEnvironmentPreparedEvent(
            ApplicationEnvironmentPreparedEvent event) {
        if (this.loggingSystem == null) {
            this.loggingSystem = LoggingSystem.get(event.getSpringApplication()
                    .getClassLoader());
        }
        initialize(event.getEnvironment(), event.getSpringApplication().getClassLoader());
    }

    private void onContextClosedEvent() {
        if (this.loggingSystem != null) {
            this.loggingSystem.cleanUp();
        }
    }

    /**
     * Initialize the logging system according to preferences expressed through the
     * {@link Environment} and the classpath.
     * @param environment the environment
     * @param classLoader the classloader
     */
    protected void initialize(ConfigurableEnvironment environment, ClassLoader classLoader) {
        if (System.getProperty(PID_KEY) == null) {
            System.setProperty(PID_KEY, new ApplicationPid().toString());
        }
        initializeEarlyLoggingLevel(environment);
        initializeSystem(environment, this.loggingSystem);
        initializeFinalLoggingLevels(environment, this.loggingSystem);
    }

    private void initializeEarlyLoggingLevel(ConfigurableEnvironment environment) {
        if (this.parseArgs && this.springBootLogging == null) {
            if (environment.containsProperty("debug")) {
                this.springBootLogging = LogLevel.DEBUG;
            }
            if (environment.containsProperty("trace")) {
                this.springBootLogging = LogLevel.TRACE;
            }
        }
    }

    private void initializeSystem(ConfigurableEnvironment environment,
            LoggingSystem system) {
        LogFile logFile = LogFile.get(environment);
        String logConfig = environment.getProperty(CONFIG_PROPERTY);
        if (StringUtils.hasLength(logConfig)) {
            try {
                ResourceUtils.getURL(logConfig).openStream().close();
                system.initialize(logConfig, logFile);
            }
            catch (Exception ex) {
                this.logger.warn("Logging environment value '" + logConfig
                        + "' cannot be opened and will be ignored "
                        + "(using default location instead)");
                system.initialize(null, logFile);
            }
        }
        else {
            system.initialize(null, logFile);
        }
    }

    private void initializeFinalLoggingLevels(ConfigurableEnvironment environment,
            LoggingSystem system) {
        if (this.springBootLogging != null) {
            initializeLogLevel(system, this.springBootLogging);
        }
        setLogLevels(system, environment);
    }

    protected void initializeLogLevel(LoggingSystem system, LogLevel level) {
        List<String> loggers = LOG_LEVEL_LOGGERS.get(level);
        if (loggers != null) {
            for (String logger : loggers) {
                system.setLogLevel(logger, level);
            }
        }
    }

    protected void setLogLevels(LoggingSystem system, Environment environment) {
        Map<String, Object> levels = new RelaxedPropertyResolver(environment)
                .getSubProperties("logging.level.");
        for (Entry<String, Object> entry : levels.entrySet()) {
            setLogLevel(system, environment, entry.getKey(), entry.getValue().toString());
        }
    }

    private void setLogLevel(LoggingSystem system, Environment environment, String name,
            String level) {
        try {
            if (name.equalsIgnoreCase("root")) {
                name = null;
            }
            level = environment.resolvePlaceholders(level);
            system.setLogLevel(name, LogLevel.valueOf(level));
        }
        catch (RuntimeException ex) {
            this.logger.error("Cannot set level: " + level + " for '" + name + "'");
        }
    }

    public void setOrder(int order) {
        this.order = order;
    }

    @Override
    public int getOrder() {
        return this.order;
    }

    /**
     * Sets a custom logging level to be used for Spring Boot and related libraries.
     * @param springBootLogging the logging level
     */
    public void setSpringBootLogging(LogLevel springBootLogging) {
        this.springBootLogging = springBootLogging;
    }

    /**
     * Sets if initialization arguments should be parsed for {@literal --debug} and
     * {@literal --trace} options. Defaults to {@code true}.
     * @param parseArgs if arguments should be parsed
     */
    public void setParseArgs(boolean parseArgs) {
        this.parseArgs = parseArgs;
    }

}

 

时间: 2024-10-21 12:08:54

LoggingApplicationListener的相关文章

Logback 专题

  spring boot中使用logback时一个一个配置文件示例:简单的:logback-spring.xml <?xml version="1.0" encoding="UTF-8"?> <configuration> <include resource="org/springframework/boot/logging/logback/base.xml" /> <logger name="

深入JVM分析spring-boot应用hibernate-validator

问题 可重现的Demo代码:demo.zip 最近排查一个spring boot应用抛出hibernate.validator NoClassDefFoundError的问题,异常信息如下: Caused by: java.lang.NoClassDefFoundError: Could not initialize class org.hibernate.validator.internal.engine.ConfigurationImpl at org.hibernate.validator

《SpringBoot揭秘:快速构建微服务体系》—第3章3.3节SpringApplication:SpringBoot程序启动的一站式解决方案

3.3 SpringApplication:SpringBoot程序启动的一站式解决方案 如果非说SpringBoot微框架提供了点儿自己特有的东西,在核心类层面(各种场景下的自动配置一站式插拔模块,我们下一章再重点介绍),也就是SpringApplication了. SpringApplication将一个典型的Spring应用启动的流程"模板化"(这里是动词),在没有特殊需求的情况下,默认模板化后的执行流程就可以满足需求了:但有特殊需求也没关系,SpringApplication在

Spring Boot 探索系列 - 自动化配置篇

26. Logging Prev  Part IV. Spring Boot features  Next 26. Logging Spring Boot uses Commons Logging for all internal logging, but leaves the underlying log implementation open. Default configurations are provided for Java Util Logging,Log4J, Log4J2 an

springboot源码分析14-事件发布机制以及应用监听器

摘要:事件驱动模型,也就是我们经常提到用到的观察者模式.当然也可以将其理解为发布-订阅模型.具体的实现要素有如下几个方面. 1.首先是一对多的关系,一是目标对象,多则是观察者对象.比如报社是一个,而订报者是多个. 2.当目标对象的行为发生变化的时候,多个观察者对象会级联触发并做出相应的处理.换言之,目标对象的行为发生变化的时候,只需要通知一下所有的观察者对象(订阅过的)即可.具体的各个观察者怎么去处理,使用什么方式去处理,并不是目标对象所需要考虑的范畴.也就是说目标与观察者的实现是低耦合.目标对