From 012bd99394976709fb9c04e1450c2841d57a6a0f Mon Sep 17 00:00:00 2001 From: Yang Libin Date: Fri, 6 Nov 2020 14:30:19 +0800 Subject: [PATCH] fix: resolve SpringBoot-LogSystem.md (#77) --- docs/SpringBoot/SpringBoot-LogSystem.md | 534 ++++++++++++------------ 1 file changed, 261 insertions(+), 273 deletions(-) diff --git a/docs/SpringBoot/SpringBoot-LogSystem.md b/docs/SpringBoot/SpringBoot-LogSystem.md index c3b9045..1062194 100644 --- a/docs/SpringBoot/SpringBoot-LogSystem.md +++ b/docs/SpringBoot/SpringBoot-LogSystem.md @@ -9,21 +9,21 @@ - 日志级别: `org.springframework.boot.logging.LogLevel` -```java -public enum LogLevel { - TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF -} -``` + ```java + public enum LogLevel { + TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF + } + ``` -## java 日志实现 +## Java 日志实现 - `org.springframework.boot.logging.java.JavaLoggingSystem` -![image-20200323144523848](../../images/SpringBoot/image-20200323144523848.png) + ![image-20200323144523848](../../images/SpringBoot/image-20200323144523848.png) -```JAVA + ```java static { - // KEY : springBoot 定义的日志级别, value: jdk 定义的日志级别 + // KEY : springBoot 定义的日志级别, value: jdk 定义的日志级别 LEVELS.map(LogLevel.TRACE, Level.FINEST); LEVELS.map(LogLevel.DEBUG, Level.FINE); LEVELS.map(LogLevel.INFO, Level.INFO); @@ -32,24 +32,22 @@ public enum LogLevel { LEVELS.map(LogLevel.FATAL, Level.SEVERE); LEVELS.map(LogLevel.OFF, Level.OFF); } -``` + ``` - LEVELS 对象 - ```java - protected static class LogLevels { - - /** - * key : SpringBoot 中定义的日志级别, value: 其他日志框架的日志级别 - */ - private final Map systemToNative; - - /** - * key : 其他日志框架的日志级别 , value: springBoot 中定义中定义的日志级别 - */ - private final Map nativeToSystem; - } - ``` + ```java + protected static class LogLevels { + /** + * key : SpringBoot 中定义的日志级别, value: 其他日志框架的日志级别 + */ + private final Map systemToNative; + /** + * key : 其他日志框架的日志级别 , value: springBoot 中定义中定义的日志级别 + */ + private final Map nativeToSystem; + } + ``` ## LoggingSystem @@ -58,7 +56,7 @@ public enum LogLevel { - 一个 map 对象: `SYSTEMS` -```JAVA + ```java /** * key: 第三方日志框架的类 value: springBoot 中的处理类 */ @@ -72,59 +70,58 @@ public enum LogLevel { systems.put("java.util.logging.LogManager", "org.springframework.boot.logging.java.JavaLoggingSystem"); SYSTEMS = Collections.unmodifiableMap(systems); } - -``` + ``` - 各个抽象方法 -| 方法名称 | 作用 | -| ----------------------- | ---------------------------------- | -| beforeInitialize | 初始化之前调用,目的是减少日志输出 | -| initialize | 初始化日志 | -| cleanUp | 清除日志 | -| getShutdownHandler | | -| getSupportedLogLevels | 获取支持的日志级别 | -| setLogLevel | 设置日志级别 | -| getLoggerConfigurations | 获取日志配置 | + | 方法名称 | 作用 | + | ----------------------- | ---------------------------------- | + | beforeInitialize | 初始化之前调用,目的是减少日志输出 | + | initialize | 初始化日志 | + | cleanUp | 清除日志 | + | getShutdownHandler | | + | getSupportedLogLevels | 获取支持的日志级别 | + | setLogLevel | 设置日志级别 | + | getLoggerConfigurations | 获取日志配置 | ### get ```java public static LoggingSystem get(ClassLoader classLoader) { - // 获取系统属性 - String loggingSystem = System.getProperty(SYSTEM_PROPERTY); - - if (StringUtils.hasLength(loggingSystem)) { - // 是不是NONE - if (NONE.equals(loggingSystem)) { - // 空的日志系统 - return new NoOpLoggingSystem(); - } - return get(classLoader, loggingSystem); + // 获取系统属性 + String loggingSystem = System.getProperty(SYSTEM_PROPERTY); + + if (StringUtils.hasLength(loggingSystem)) { + // 是不是NONE + if (NONE.equals(loggingSystem)) { + // 空的日志系统 + return new NoOpLoggingSystem(); } - // 循环所有日志, - return SYSTEMS.entrySet().stream().filter((entry) -> ClassUtils.isPresent(entry.getKey(), classLoader)) - .map((entry) -> - // 实例化具体日志 - get(classLoader, entry.getValue())).findFirst() - .orElseThrow(() -> new IllegalStateException("No suitable logging system located")); + return get(classLoader, loggingSystem); } + // 循环所有日志, + return SYSTEMS.entrySet().stream().filter((entry) -> ClassUtils.isPresent(entry.getKey(), classLoader)) + .map((entry) -> + // 实例化具体日志 + get(classLoader, entry.getValue())).findFirst() + .orElseThrow(() -> new IllegalStateException("No suitable logging system located")); +} ``` - 实例化日志系统 ```java - private static LoggingSystem get(ClassLoader classLoader, String loggingSystemClass) { - try { - Class systemClass = ClassUtils.forName(loggingSystemClass, classLoader); - Constructor constructor = systemClass.getDeclaredConstructor(ClassLoader.class); - constructor.setAccessible(true); - return (LoggingSystem) constructor.newInstance(classLoader); - } - catch (Exception ex) { - throw new IllegalStateException(ex); - } +private static LoggingSystem get(ClassLoader classLoader, String loggingSystemClass) { + try { + Class systemClass = ClassUtils.forName(loggingSystemClass, classLoader); + Constructor constructor = systemClass.getDeclaredConstructor(ClassLoader.class); + constructor.setAccessible(true); + return (LoggingSystem) constructor.newInstance(classLoader); } + catch (Exception ex) { + throw new IllegalStateException(ex); + } +} ``` @@ -138,29 +135,28 @@ public static LoggingSystem get(ClassLoader classLoader) { ![image-20200323154205484](../../images/SpringBoot/image-20200323154205484.png) - - 链路 - 1. `org.springframework.boot.context.logging.LoggingApplicationListener#onApplicationEvent` - 2. `org.springframework.boot.context.logging.LoggingApplicationListener#onApplicationStartingEvent` - 3. `org.springframework.boot.logging.LoggingSystem#beforeInitialize` - -- 因为前文中我们已知对象是:`org.springframework.boot.logging.logback.LogbackLoggingSystem` 直接看这个类的**`beforeInitialize`**方法 - - ```JAVA - @Override - public void beforeInitialize() { - // 日志上下文 - LoggerContext loggerContext = getLoggerContext(); - // 是否初始化 - if (isAlreadyInitialized(loggerContext)) { - return; - } - // 父类方法 - super.beforeInitialize(); - // 添加过滤器 - loggerContext.getTurboFilterList().add(FILTER); - } +- 链路 + 1. `org.springframework.boot.context.logging.LoggingApplicationListener#onApplicationEvent` + 2. `org.springframework.boot.context.logging.LoggingApplicationListener#onApplicationStartingEvent` + 3. `org.springframework.boot.logging.LoggingSystem#beforeInitialize` - ``` +- 因为前文中我们已知对象是:`org.springframework.boot.logging.logback.LogbackLoggingSystem` 直接看这个类的 `beforeInitialize` 方法 + + ```java + @Override + public void beforeInitialize() { + // 日志上下文 + LoggerContext loggerContext = getLoggerContext(); + // 是否初始化 + if (isAlreadyInitialized(loggerContext)) { + return; + } + // 父类方法 + super.beforeInitialize(); + // 添加过滤器 + loggerContext.getTurboFilterList().add(FILTER); + } + ``` - 初始化之前的的操作完成了初始化方法开始 @@ -168,132 +164,129 @@ public static LoggingSystem get(ClassLoader classLoader) { - `org.springframework.boot.context.logging.LoggingApplicationListener#onApplicationEnvironmentPreparedEvent` - ```JAVA - private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) { - if (this.loggingSystem == null) { - this.loggingSystem = LoggingSystem.get(event.getSpringApplication().getClassLoader()); - } - initialize(event.getEnvironment(), event.getSpringApplication().getClassLoader()); + ```java + private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) { + if (this.loggingSystem == null) { + this.loggingSystem = LoggingSystem.get(event.getSpringApplication().getClassLoader()); } + initialize(event.getEnvironment(), event.getSpringApplication().getClassLoader()); + } ``` - `org.springframework.boot.context.logging.LoggingApplicationListener#initializeSystem` - ```JAVA - protected void initialize(ConfigurableEnvironment environment, ClassLoader classLoader) { - new LoggingSystemProperties(environment).apply(); - this.logFile = LogFile.get(environment); - if (this.logFile != null) { - this.logFile.applyToSystemProperties(); - } - this.loggerGroups = new LoggerGroups(DEFAULT_GROUP_LOGGERS); - // 早期 的日志级别 - initializeEarlyLoggingLevel(environment); - // 初始化日志系统 - initializeSystem(environment, this.loggingSystem, this.logFile); - // 初始化日志级别 - initializeFinalLoggingLevels(environment, this.loggingSystem); - registerShutdownHookIfNecessary(environment, this.loggingSystem); + ```java + protected void initialize(ConfigurableEnvironment environment, ClassLoader classLoader) { + new LoggingSystemProperties(environment).apply(); + this.logFile = LogFile.get(environment); + if (this.logFile != null) { + this.logFile.applyToSystemProperties(); } + this.loggerGroups = new LoggerGroups(DEFAULT_GROUP_LOGGERS); + // 早期 的日志级别 + initializeEarlyLoggingLevel(environment); + // 初始化日志系统 + initializeSystem(environment, this.loggingSystem, this.logFile); + // 初始化日志级别 + initializeFinalLoggingLevels(environment, this.loggingSystem); + registerShutdownHookIfNecessary(environment, this.loggingSystem); + } ``` - ```JAVA - private void initializeSystem(ConfigurableEnvironment environment, LoggingSystem system, LogFile logFile) { - LoggingInitializationContext initializationContext = new LoggingInitializationContext(environment); - String logConfig = environment.getProperty(CONFIG_PROPERTY); - if (ignoreLogConfig(logConfig)) { - // 日志系统初始化 - system.initialize(initializationContext, null, logFile); + ```java + private void initializeSystem(ConfigurableEnvironment environment, LoggingSystem system, LogFile logFile) { + LoggingInitializationContext initializationContext = new LoggingInitializationContext(environment); + String logConfig = environment.getProperty(CONFIG_PROPERTY); + if (ignoreLogConfig(logConfig)) { + // 日志系统初始化 + system.initialize(initializationContext, null, logFile); + } + else { + try { + ResourceUtils.getURL(logConfig).openStream().close(); + system.initialize(initializationContext, logConfig, logFile); } - else { - try { - ResourceUtils.getURL(logConfig).openStream().close(); - system.initialize(initializationContext, logConfig, logFile); - } - catch (Exception ex) { - // NOTE: We can't use the logger here to report the problem - System.err.println("Logging system failed to initialize using configuration from '" + logConfig + "'"); - ex.printStackTrace(System.err); - throw new IllegalStateException(ex); - } + catch (Exception ex) { + // NOTE: We can't use the logger here to report the problem + System.err.println("Logging system failed to initialize using configuration from '" + logConfig + "'"); + ex.printStackTrace(System.err); + throw new IllegalStateException(ex); } } - + } ``` - `org.springframework.boot.logging.logback.LogbackLoggingSystem#initialize` -```java - @Override - public void initialize(LoggingInitializationContext initializationContext, String configLocation, LogFile logFile) { - LoggerContext loggerContext = getLoggerContext(); - if (isAlreadyInitialized(loggerContext)) { - return; - } - // 日志初始化 - super.initialize(initializationContext, configLocation, logFile); - loggerContext.getTurboFilterList().remove(FILTER); - markAsInitialized(loggerContext); - if (StringUtils.hasText(System.getProperty(CONFIGURATION_FILE_PROPERTY))) { - getLogger(LogbackLoggingSystem.class.getName()).warn("Ignoring '" + CONFIGURATION_FILE_PROPERTY - + "' system property. Please use 'logging.config' instead."); - } - } + ```java + @Override + public void initialize(LoggingInitializationContext initializationContext, String configLocation, LogFile logFile) { + LoggerContext loggerContext = getLoggerContext(); + if (isAlreadyInitialized(loggerContext)) { + return; + } + // 日志初始化 + super.initialize(initializationContext, configLocation, logFile); + loggerContext.getTurboFilterList().remove(FILTER); + markAsInitialized(loggerContext); + if (StringUtils.hasText(System.getProperty(CONFIGURATION_FILE_PROPERTY))) { + getLogger(LogbackLoggingSystem.class.getName()).warn("Ignoring '" + CONFIGURATION_FILE_PROPERTY + + "' system property. Please use 'logging.config' instead."); + } + } -``` + ``` - `org.springframework.boot.logging.AbstractLoggingSystem#initializeWithConventions` - ```JAVA - private void initializeWithConventions(LoggingInitializationContext initializationContext, LogFile logFile) { - String config = getSelfInitializationConfig(); - if (config != null && logFile == null) { - // self initialization has occurred, reinitialize in case of property changes - reinitialize(initializationContext); - return; - } - if (config == null) { - config = getSpringInitializationConfig(); - } - if (config != null) { - loadConfiguration(initializationContext, config, logFile); - return; - } - // 加载默认配置 - loadDefaults(initializationContext, logFile); + ```java + private void initializeWithConventions(LoggingInitializationContext initializationContext, LogFile logFile) { + String config = getSelfInitializationConfig(); + if (config != null && logFile == null) { + // self initialization has occurred, reinitialize in case of property changes + reinitialize(initializationContext); + return; + } + if (config == null) { + config = getSpringInitializationConfig(); + } + if (config != null) { + loadConfiguration(initializationContext, config, logFile); + return; } + // 加载默认配置 + loadDefaults(initializationContext, logFile); + } + ``` + +- `org.springframework.boot.logging.logback.LogbackLoggingSystem#loadDefaults` + ```java + @Override + protected void loadDefaults(LoggingInitializationContext initializationContext, LogFile logFile) { + LoggerContext context = getLoggerContext(); + stopAndReset(context); + boolean debug = Boolean.getBoolean("logback.debug"); + if (debug) { + StatusListenerConfigHelper.addOnConsoleListenerInstance(context, new OnConsoleStatusListener()); + } + LogbackConfigurator configurator = debug ? new DebugLogbackConfigurator(context) + : new LogbackConfigurator(context); + Environment environment = initializationContext.getEnvironment(); + context.putProperty(LoggingSystemProperties.LOG_LEVEL_PATTERN, + environment.resolvePlaceholders("${logging.pattern.level:${LOG_LEVEL_PATTERN:%5p}}")); + context.putProperty(LoggingSystemProperties.LOG_DATEFORMAT_PATTERN, environment.resolvePlaceholders( + "${logging.pattern.dateformat:${LOG_DATEFORMAT_PATTERN:yyyy-MM-dd HH:mm:ss.SSS}}")); + context.putProperty(LoggingSystemProperties.ROLLING_FILE_NAME_PATTERN, environment + .resolvePlaceholders("${logging.pattern.rolling-file-name:${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz}")); + new DefaultLogbackConfiguration(initializationContext, logFile).apply(configurator); + context.setPackagingDataEnabled(true); + } ``` - - `org.springframework.boot.logging.logback.LogbackLoggingSystem#loadDefaults` - - ```JAVA - @Override - protected void loadDefaults(LoggingInitializationContext initializationContext, LogFile logFile) { - LoggerContext context = getLoggerContext(); - stopAndReset(context); - boolean debug = Boolean.getBoolean("logback.debug"); - if (debug) { - StatusListenerConfigHelper.addOnConsoleListenerInstance(context, new OnConsoleStatusListener()); - } - LogbackConfigurator configurator = debug ? new DebugLogbackConfigurator(context) - : new LogbackConfigurator(context); - Environment environment = initializationContext.getEnvironment(); - context.putProperty(LoggingSystemProperties.LOG_LEVEL_PATTERN, - environment.resolvePlaceholders("${logging.pattern.level:${LOG_LEVEL_PATTERN:%5p}}")); - context.putProperty(LoggingSystemProperties.LOG_DATEFORMAT_PATTERN, environment.resolvePlaceholders( - "${logging.pattern.dateformat:${LOG_DATEFORMAT_PATTERN:yyyy-MM-dd HH:mm:ss.SSS}}")); - context.putProperty(LoggingSystemProperties.ROLLING_FILE_NAME_PATTERN, environment - .resolvePlaceholders("${logging.pattern.rolling-file-name:${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz}")); - new DefaultLogbackConfiguration(initializationContext, logFile).apply(configurator); - context.setPackagingDataEnabled(true); - } - - ``` - -```JAVA + ```java @Override public void initialize(LoggingInitializationContext initializationContext, String configLocation, LogFile logFile) { LoggerContext loggerContext = getLoggerContext(); @@ -312,69 +305,66 @@ public static LoggingSystem get(ClassLoader classLoader) { + "' system property. Please use 'logging.config' instead."); } } -``` - -标记`markAsInitialized` + ``` -```JAVA - private void markAsInitialized(LoggerContext loggerContext) { - loggerContext.putObject(LoggingSystem.class.getName(), new Object()); - } +- 标记 `markAsInitialized` -``` + ```java + private void markAsInitialized(LoggerContext loggerContext) { + loggerContext.putObject(LoggingSystem.class.getName(), new Object()); + } + ``` -此时日志初始化完成 +此时日志初始化完成。 ### 默认配置文件 -- `getStandardConfigLocations` 这个方法定义了默认配置文件有哪些 +- `getStandardConfigLocations` 这个方法定义了默认配置文件有哪些。 -```java - @Override - protected String[] getStandardConfigLocations() { - return new String[] { "logback-test.groovy", "logback-test.xml", "logback.groovy", "logback.xml" }; - } - -``` + ```java + @Override + protected String[] getStandardConfigLocations() { + return new String[] { "logback-test.groovy", "logback-test.xml", "logback.groovy", "logback.xml" }; + } + ``` -- 切回`org.springframework.boot.logging.AbstractLoggingSystem#initializeWithConventions`方法 +- 切回 `org.springframework.boot.logging.AbstractLoggingSystem#initializeWithConventions` 方法 - 添加依赖 -```XML - - org.springframework.boot - spring-boot-starter-logging - ${revision} - + ```XML + + org.springframework.boot + spring-boot-starter-logging + ${revision} + -``` + ``` - 添加配置文件 -![image-20200323161442058](../../images/SpringBoot/image-20200323161442058.png) + ![image-20200323161442058](../../images/SpringBoot/image-20200323161442058.png) -![image-20200323161522570](../../images/SpringBoot/image-20200323161522570.png) + ![image-20200323161522570](../../images/SpringBoot/image-20200323161522570.png) - 此时配置文件地址出现了 -```JAVA + ```java protected String getSelfInitializationConfig() { - // 寻找配置文件 + // 寻找配置文件 return findConfig(getStandardConfigLocations()); } + ``` -``` - -```JAVA + ```java @Override protected String[] getStandardConfigLocations() { return new String[] { "logback-test.groovy", "logback-test.xml", "logback.groovy", "logback.xml" }; } -``` + ``` -```JAVA + ```java private String findConfig(String[] locations) { for (String location : locations) { ClassPathResource resource = new ClassPathResource(location, this.classLoader); @@ -384,73 +374,71 @@ public static LoggingSystem get(ClassLoader classLoader) { } return null; } + ``` -``` - -- 此时自定义配置文件如何获取的已经明了 +- 此时自定义配置文件如何获取的已经明了。 #### reinitialize -```JAVA - @Override - protected void reinitialize(LoggingInitializationContext initializationContext) { - // 日志上下文重新设置 - getLoggerContext().reset(); - getLoggerContext().getStatusManager().clear(); - // 加载配置文件 - loadConfiguration(initializationContext, getSelfInitializationConfig(), null); - } - +```java +@Override +protected void reinitialize(LoggingInitializationContext initializationContext) { + // 日志上下文重新设置 + getLoggerContext().reset(); + getLoggerContext().getStatusManager().clear(); + // 加载配置文件 + loadConfiguration(initializationContext, getSelfInitializationConfig(), null); +} ``` -```JAVA - @Override - protected void loadConfiguration(LoggingInitializationContext initializationContext, String location, - LogFile logFile) { - // 父类方法 - super.loadConfiguration(initializationContext, location, logFile); - // 获取上下文 - LoggerContext loggerContext = getLoggerContext(); - // 停止并且重启 - stopAndReset(loggerContext); - try { - // 配置文件加载 - configureByResourceUrl(initializationContext, loggerContext, ResourceUtils.getURL(location)); - } - catch (Exception ex) { - throw new IllegalStateException("Could not initialize Logback logging from " + location, ex); - } - List statuses = loggerContext.getStatusManager().getCopyOfStatusList(); - StringBuilder errors = new StringBuilder(); - for (Status status : statuses) { - if (status.getLevel() == Status.ERROR) { - errors.append((errors.length() > 0) ? String.format("%n") : ""); - errors.append(status.toString()); - } - } - if (errors.length() > 0) { - throw new IllegalStateException(String.format("Logback configuration error detected: %n%s", errors)); +```java +@Override +protected void loadConfiguration(LoggingInitializationContext initializationContext, String location, + LogFile logFile) { + // 父类方法 + super.loadConfiguration(initializationContext, location, logFile); + // 获取上下文 + LoggerContext loggerContext = getLoggerContext(); + // 停止并且重启 + stopAndReset(loggerContext); + try { + // 配置文件加载 + configureByResourceUrl(initializationContext, loggerContext, ResourceUtils.getURL(location)); + } + catch (Exception ex) { + throw new IllegalStateException("Could not initialize Logback logging from " + location, ex); + } + List statuses = loggerContext.getStatusManager().getCopyOfStatusList(); + StringBuilder errors = new StringBuilder(); + for (Status status : statuses) { + if (status.getLevel() == Status.ERROR) { + errors.append((errors.length() > 0) ? String.format("%n") : ""); + errors.append(status.toString()); } } + if (errors.length() > 0) { + throw new IllegalStateException(String.format("Logback configuration error detected: %n%s", errors)); + } +} ``` ```java - private void configureByResourceUrl(LoggingInitializationContext initializationContext, LoggerContext loggerContext, - URL url) throws JoranException { - if (url.toString().endsWith("xml")) { - // logback 日志操作 - JoranConfigurator configurator = new SpringBootJoranConfigurator(initializationContext); - // 设置上下文 - configurator.setContext(loggerContext); - // 执行配置 - configurator.doConfigure(url); - } - else { - new ContextInitializer(loggerContext).configureByResource(url); - } +private void configureByResourceUrl(LoggingInitializationContext initializationContext, LoggerContext loggerContext, + URL url) throws JoranException { + if (url.toString().endsWith("xml")) { + // logback 日志操作 + JoranConfigurator configurator = new SpringBootJoranConfigurator(initializationContext); + // 设置上下文 + configurator.setContext(loggerContext); + // 执行配置 + configurator.doConfigure(url); + } + else { + new ContextInitializer(loggerContext).configureByResource(url); } +} ``` -- 执行配置属于 logback 操作源码不在此进行分析 +执行配置属于 logback 操作源码不在此进行分析。