Skip to content

Commit

Permalink
Merge branch '2.7.x' into 3.0.x
Browse files Browse the repository at this point in the history
Closes gh-35920
  • Loading branch information
philwebb committed Jun 15, 2023
2 parents eeea065 + 137f4ee commit 4c8b93b
Show file tree
Hide file tree
Showing 7 changed files with 402 additions and 37 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2022 the original author or authors.
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -34,6 +34,8 @@
import org.springframework.boot.actuate.logging.LoggersEndpoint.SingleLoggerLevelsDescriptor;
import org.springframework.boot.logging.LogLevel;
import org.springframework.boot.logging.LoggerConfiguration;
import org.springframework.boot.logging.LoggerConfiguration.ConfigurationScope;
import org.springframework.boot.logging.LoggerConfiguration.LevelConfiguration;
import org.springframework.boot.logging.LoggerGroup;
import org.springframework.boot.logging.LoggerGroups;
import org.springframework.boot.logging.LoggingSystem;
Expand Down Expand Up @@ -164,7 +166,11 @@ public static class LoggerLevelsDescriptor implements OperationResponseBody {
private final String configuredLevel;

public LoggerLevelsDescriptor(LogLevel configuredLevel) {
this.configuredLevel = getName(configuredLevel);
this.configuredLevel = (configuredLevel != null) ? configuredLevel.name() : null;
}

LoggerLevelsDescriptor(LevelConfiguration directConfiguration) {
this.configuredLevel = (directConfiguration != null) ? directConfiguration.getName() : null;
}

protected final String getName(LogLevel level) {
Expand Down Expand Up @@ -203,8 +209,8 @@ public static class SingleLoggerLevelsDescriptor extends LoggerLevelsDescriptor
private final String effectiveLevel;

public SingleLoggerLevelsDescriptor(LoggerConfiguration configuration) {
super(configuration.getConfiguredLevel());
this.effectiveLevel = getName(configuration.getEffectiveLevel());
super(configuration.getLevelConfiguration(ConfigurationScope.DIRECT));
this.effectiveLevel = configuration.getLevelConfiguration().getName();
}

public String getEffectiveLevel() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.springframework.boot.actuate.logging.LoggersEndpoint.SingleLoggerLevelsDescriptor;
import org.springframework.boot.logging.LogLevel;
import org.springframework.boot.logging.LoggerConfiguration;
import org.springframework.boot.logging.LoggerConfiguration.LevelConfiguration;
import org.springframework.boot.logging.LoggerGroups;
import org.springframework.boot.logging.LoggingSystem;

Expand Down Expand Up @@ -113,6 +114,17 @@ void loggerLevelsWhenNameSpecifiedShouldReturnLevels() {
assertThat(levels.getEffectiveLevel()).isEqualTo("DEBUG");
}

@Test // gh-35227
void loggerLevelsWhenCustomLevelShouldReturnLevels() {
given(this.loggingSystem.getLoggerConfiguration("ROOT"))
.willReturn(new LoggerConfiguration("ROOT", null, LevelConfiguration.ofCustom("FINEST")));
SingleLoggerLevelsDescriptor levels = (SingleLoggerLevelsDescriptor) new LoggersEndpoint(this.loggingSystem,
this.loggerGroups)
.loggerLevels("ROOT");
assertThat(levels.getConfiguredLevel()).isNull();
assertThat(levels.getEffectiveLevel()).isEqualTo("FINEST");
}

@Test
void groupNameSpecifiedShouldReturnConfiguredLevelAndMembers() {
GroupLoggerLevelsDescriptor levels = (GroupLoggerLevelsDescriptor) new LoggersEndpoint(this.loggingSystem,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2022 the original author or authors.
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,22 +16,25 @@

package org.springframework.boot.logging;

import java.util.Objects;

import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;

/**
* Immutable class that represents the configuration of a {@link LoggingSystem}'s logger.
*
* @author Ben Hale
* @author Phillip Webb
* @since 1.5.0
*/
public final class LoggerConfiguration {

private final String name;

private final LogLevel configuredLevel;
private final LevelConfiguration levelConfiguration;

private final LogLevel effectiveLevel;
private final LevelConfiguration inheritedLevelConfiguration;

/**
* Create a new {@link LoggerConfiguration instance}.
Expand All @@ -43,66 +46,204 @@ public LoggerConfiguration(String name, LogLevel configuredLevel, LogLevel effec
Assert.notNull(name, "Name must not be null");
Assert.notNull(effectiveLevel, "EffectiveLevel must not be null");
this.name = name;
this.configuredLevel = configuredLevel;
this.effectiveLevel = effectiveLevel;
this.levelConfiguration = (configuredLevel != null) ? LevelConfiguration.of(configuredLevel) : null;
this.inheritedLevelConfiguration = LevelConfiguration.of(effectiveLevel);
}

/**
* Create a new {@link LoggerConfiguration instance}.
* @param name the name of the logger
* @param levelConfiguration the level configuration
* @param inheritedLevelConfiguration the inherited level configuration
* @since 2.7.13
*/
public LoggerConfiguration(String name, LevelConfiguration levelConfiguration,
LevelConfiguration inheritedLevelConfiguration) {
Assert.notNull(name, "Name must not be null");
Assert.notNull(inheritedLevelConfiguration, "EffectiveLevelConfiguration must not be null");
this.name = name;
this.levelConfiguration = levelConfiguration;
this.inheritedLevelConfiguration = inheritedLevelConfiguration;
}

/**
* Returns the name of the logger.
* @return the name of the logger
*/
public String getName() {
return this.name;
}

/**
* Returns the configured level of the logger.
* @return the configured level of the logger
* @see #getLevelConfiguration(ConfigurationScope)
*/
public LogLevel getConfiguredLevel() {
return this.configuredLevel;
LevelConfiguration configuration = getLevelConfiguration(ConfigurationScope.DIRECT);
return (configuration != null) ? configuration.getLevel() : null;
}

/**
* Returns the effective level of the logger.
* @return the effective level of the logger
* @see #getLevelConfiguration(ConfigurationScope)
*/
public LogLevel getEffectiveLevel() {
return this.effectiveLevel;
return getLevelConfiguration().getLevel();
}

/**
* Returns the name of the logger.
* @return the name of the logger
* Return the level configuration, considering inherited loggers.
* @return the level configuration
* @since 2.7.13
*/
public String getName() {
return this.name;
public LevelConfiguration getLevelConfiguration() {
return getLevelConfiguration(ConfigurationScope.INHERITED);
}

/**
* Return the level configuration for the given scope.
* @param scope the configuration scope
* @return the level configuration or {@code null} for
* {@link ConfigurationScope#DIRECT direct scope} results without applied
* configuration
* @since 2.7.13
*/
public LevelConfiguration getLevelConfiguration(ConfigurationScope scope) {
return (scope != ConfigurationScope.DIRECT) ? this.inheritedLevelConfiguration : this.levelConfiguration;
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
if (obj == null || getClass() != obj.getClass()) {
return false;
}
if (obj instanceof LoggerConfiguration other) {
boolean rtn = true;
rtn = rtn && ObjectUtils.nullSafeEquals(this.name, other.name);
rtn = rtn && ObjectUtils.nullSafeEquals(this.configuredLevel, other.configuredLevel);
rtn = rtn && ObjectUtils.nullSafeEquals(this.effectiveLevel, other.effectiveLevel);
return rtn;
}
return super.equals(obj);
LoggerConfiguration other = (LoggerConfiguration) obj;
return ObjectUtils.nullSafeEquals(this.name, other.name)
&& ObjectUtils.nullSafeEquals(this.levelConfiguration, other.levelConfiguration)
&& ObjectUtils.nullSafeEquals(this.inheritedLevelConfiguration, other.inheritedLevelConfiguration);
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ObjectUtils.nullSafeHashCode(this.name);
result = prime * result + ObjectUtils.nullSafeHashCode(this.configuredLevel);
result = prime * result + ObjectUtils.nullSafeHashCode(this.effectiveLevel);
return result;
return Objects.hash(this.name, this.levelConfiguration, this.inheritedLevelConfiguration);
}

@Override
public String toString() {
return "LoggerConfiguration [name=" + this.name + ", configuredLevel=" + this.configuredLevel
+ ", effectiveLevel=" + this.effectiveLevel + "]";
return "LoggerConfiguration [name=" + this.name + ", levelConfiguration=" + this.levelConfiguration
+ ", inheritedLevelConfiguration=" + this.inheritedLevelConfiguration + "]";
}

/**
* Supported logger configurations scopes.
*
* @since 2.7.13
*/
public enum ConfigurationScope {

/**
* Only return configuration that has been applied directly applied. Often
* referred to as 'configured' or 'assigned' configuration.
*/
DIRECT,

/**
* May return configuration that has been applied to a parent logger. Often
* referred to as 'effective' configuration.
*/
INHERITED

}

/**
* Logger level configuration.
*
* @since 2.7.13
*/
public static final class LevelConfiguration {

private final String name;

private final LogLevel logLevel;

private LevelConfiguration(String name, LogLevel logLevel) {
this.name = name;
this.logLevel = logLevel;
}

/**
* Return the name of the level.
* @return the level name
*/
public String getName() {
return this.name;
}

/**
* Return the actual level value if possible.
* @return the level value
* @throws IllegalStateException if this is a {@link #isCustom() custom} level
*/
public LogLevel getLevel() {
Assert.state(this.logLevel != null, "Unable to provide LogLevel for '" + this.name + "'");
return this.logLevel;
}

/**
* Return if this is a custom level and cannot be represented by {@link LogLevel}.
* @return if this is a custom level
*/
public boolean isCustom() {
return this.logLevel == null;
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
LevelConfiguration other = (LevelConfiguration) obj;
return this.logLevel == other.logLevel && ObjectUtils.nullSafeEquals(this.name, other.name);
}

@Override
public int hashCode() {
return Objects.hash(this.logLevel, this.name);
}

@Override
public String toString() {
return "LevelConfiguration [name=" + this.name + ", logLevel=" + this.logLevel + "]";
}

/**
* Create a new {@link LevelConfiguration} instance of the given {@link LogLevel}.
* @param logLevel the log level
* @return a new {@link LevelConfiguration} instance
*/
public static LevelConfiguration of(LogLevel logLevel) {
Assert.notNull(logLevel, "LogLevel must not be null");
return new LevelConfiguration(logLevel.name(), logLevel);
}

/**
* Create a new {@link LevelConfiguration} instance for a custom level name.
* @param name the log level name
* @return a new {@link LevelConfiguration} instance
*/
public static LevelConfiguration ofCustom(String name) {
Assert.hasText(name, "Name must not be empty");
return new LevelConfiguration(name, null);
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
*
* @author HaiTao Zhang
* @author Phillip Webb
* @since 2.2.0 #see {@link LoggerGroup}
* @since 2.2.0
* @see LoggerGroup
*/
public final class LoggerGroups implements Iterable<LoggerGroup> {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
import org.springframework.boot.logging.LogFile;
import org.springframework.boot.logging.LogLevel;
import org.springframework.boot.logging.LoggerConfiguration;
import org.springframework.boot.logging.LoggerConfiguration.LevelConfiguration;
import org.springframework.boot.logging.LoggingInitializationContext;
import org.springframework.boot.logging.LoggingSystem;
import org.springframework.boot.logging.LoggingSystemFactory;
Expand Down Expand Up @@ -432,13 +433,18 @@ private LoggerConfiguration convertLoggerConfig(String name, LoggerConfig logger
if (loggerConfig == null) {
return null;
}
LogLevel level = LEVELS.convertNativeToSystem(loggerConfig.getLevel());
LevelConfiguration effectiveLevelConfiguration = getLevelConfiguration(loggerConfig.getLevel());
if (!StringUtils.hasLength(name) || LogManager.ROOT_LOGGER_NAME.equals(name)) {
name = ROOT_LOGGER_NAME;
}
boolean isLoggerConfigured = loggerConfig.getName().equals(name);
LogLevel configuredLevel = (isLoggerConfigured) ? level : null;
return new LoggerConfiguration(name, configuredLevel, level);
boolean isAssigned = loggerConfig.getName().equals(name);
LevelConfiguration assignedLevelConfiguration = (!isAssigned) ? null : effectiveLevelConfiguration;
return new LoggerConfiguration(name, assignedLevelConfiguration, effectiveLevelConfiguration);
}

private LevelConfiguration getLevelConfiguration(Level level) {
LogLevel logLevel = LEVELS.convertNativeToSystem(level);
return (logLevel != null) ? LevelConfiguration.of(logLevel) : LevelConfiguration.ofCustom(level.name());
}

@Override
Expand Down
Loading

0 comments on commit 4c8b93b

Please sign in to comment.