spring boot 源码解析30-LoggersEndpoint

前言

之前花了3篇文章来讲解spring boot中的LoggingSystem,其目的是为了讲解这边文章的主题–LoggersEndpoint.现在我们就来解析吧

解析

LoggersEndpoint 继承自AbstractEndpoint. 用来暴露日志的信息.

  1. 字段,构造器如下:

    private final LoggingSystem loggingSystem;
    
    public LoggersEndpoint(LoggingSystem loggingSystem) {
        super("loggers");
        Assert.notNull(loggingSystem, "LoggingSystem must not be null");
        this.loggingSystem = loggingSystem;
    }
  2. invoke实现如下:

    public Map<String, Object> invoke() {
        // 1. 获得关于logger的配置
        Collection<LoggerConfiguration> configurations = this.loggingSystem
                .getLoggerConfigurations();
        if (configurations == null) {
            return Collections.emptyMap();
        }
    
        Map<String, Object> result = new LinkedHashMap<String, Object>();
        // 2. 设置key-->levels,value --> 该loggingSystem 支持的日志级别,降序排列
        result.put("levels", getLevels());
        // 3. 设置key-->loggers,value -->map{key--> loger名,value-->LoggerLevels}
        result.put("loggers", getLoggers(configurations));
        return result;
    }
    1. 获得关于logger的配置
    2. 设置key–>levels,value –> 该loggingSystem 支持的日志级别,降序排列.代码如下:

      private NavigableSet<LogLevel> getLevels() {
          Set<LogLevel> levels = this.loggingSystem.getSupportedLogLevels();
          // 返回降序排序的set : TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF
          return new TreeSet<LogLevel>(levels).descendingSet();
      }

      由于我们默认配置的是LogbackLoggingSystem,其getSupportedLogLevels返回的是:

      OFF, ERROR, INFO, TRACE, WARN, DEBUG

      这里有个问题,LogbackLoggingSystem中配置的是如下:

      private static final LogLevels<Level> LEVELS = new LogLevels<Level>();
      static {
          LEVELS.map(LogLevel.TRACE, Level.TRACE);
          LEVELS.map(LogLevel.TRACE, Level.ALL);
          LEVELS.map(LogLevel.DEBUG, Level.DEBUG);
          LEVELS.map(LogLevel.INFO, Level.INFO);
          LEVELS.map(LogLevel.WARN, Level.WARN);
          LEVELS.map(LogLevel.ERROR, Level.ERROR);
          LEVELS.map(LogLevel.FATAL, Level.ERROR);
          LEVELS.map(LogLevel.OFF, Level.OFF);
      }

      为什么返回的结果少了FATAL?

      原因是在LogLevels#map中有如下代码:

      if (!this.nativeToSystem.containsKey(nativeLevel)) {
                  this.nativeToSystem.put(nativeLevel, system);
      }

      由于我们首先保存LogLevel.ERROR, Level.ERROR,此时nativeToSystem中没有Level.ERROR,进行保存,然后我们在保存LogLevel.FATAL, Level.ERROR时,由于nativeToSystem中已经有Level.ERROR了,所有不会进行保存.因此该方法返回会少了1个FATAL.

      经过降序排列后,返回的是 OFF, ERROR, WARN, INFO, DEBUG, TRACE(按照在LogLevel中声明的声明的属性降序排列)

    3. 设置key–>loggers,value –>map{key–> loger名,value–>LoggerLevels}.其中getLoggers方法如下:

      private Map<String, LoggerLevels> getLoggers(
                  Collection<LoggerConfiguration> configurations) {
              Map<String, LoggerLevels> loggers = new LinkedHashMap<String, LoggerLevels>(
                      configurations.size());
              for (LoggerConfiguration configuration : configurations) {
                  loggers.put(configuration.getName(), new LoggerLevels(configuration));
              }
              return loggers;
          }

      遍历LoggerConfiguration,依次将其Logger名称, LoggerLevels 放入到loggers中.

      其中LoggerLevels–> 封装了LoggerConfiguration 中的configuredLevel,effectiveLevel.字段,构造器如下:

      // 配置的日志级别
      private String configuredLevel;
      
      // 生效的日志级别
      private String effectiveLevel;
      
      public LoggerLevels(LoggerConfiguration configuration) {
          this.configuredLevel = getName(configuration.getConfiguredLevel());
          this.effectiveLevel = getName(configuration.getEffectiveLevel());
      }
      
      private String getName(LogLevel level) {
          return (level == null ? null : level.name());
      }
  3. 此外,该类还声明了1个方法–> 用于获取指定logger名称的LoggerLevels,在LoggersMvcEndpoint中会调用.代码如下:

    public LoggerLevels invoke(String name) {
        Assert.notNull(name, "Name must not be null");
        LoggerConfiguration configuration = this.loggingSystem
                .getLoggerConfiguration(name);
        return (configuration == null ? null : new LoggerLevels(configuration));
    }
  4. 属性配置:

    由于该类声明了@ConfigurationProperties(prefix = “endpoints.loggers”),因此可以通过如下属性进行配置:

    endpoints.loggers.enabled=true # Enable the endpoint.
    endpoints.loggers.id= # Endpoint identifier.
    endpoints.loggers.sensitive=true # Mark if the endpoint exposes sensitive information.
  5. 自动装配:

    在EndpointAutoConfiguration中进行了配置,代码如下:

    @Bean
    @ConditionalOnBean(LoggingSystem.class)
    @ConditionalOnMissingBean
    public LoggersEndpoint loggersEndpoint(LoggingSystem loggingSystem) {
        return new LoggersEndpoint(loggingSystem);
    }
    • @Bean–> 注册1个id为loggersEndpoint,类型为LoggersEndpoint的bean
    • @ConditionalOnBean(LoggingSystem.class)–> 当beanFactory中存在LoggingSystem类型的bean时生效
    • @ConditionalOnMissingBean–> 当beanFactory中不存在LoggersEndpoint类型的bean时生效
    原文作者:Spring Boot
    原文地址: https://blog.csdn.net/qq_26000415/article/details/79131567
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞