前言
之前花了3篇文章来讲解spring boot中的LoggingSystem,其目的是为了讲解这边文章的主题–LoggersEndpoint.现在我们就来解析吧
解析
LoggersEndpoint 继承自AbstractEndpoint. 用来暴露日志的信息.
字段,构造器如下:
private final LoggingSystem loggingSystem; public LoggersEndpoint(LoggingSystem loggingSystem) { super("loggers"); Assert.notNull(loggingSystem, "LoggingSystem must not be null"); this.loggingSystem = loggingSystem; }
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; }
- 获得关于logger的配置
设置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中声明的声明的属性降序排列)
设置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()); }
此外,该类还声明了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)); }
属性配置:
由于该类声明了@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.
自动装配:
在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时生效