Polish "Add support for configuring logging groups"
See gh-17515 Co-authored-by: Phillip Webb <pwebb@pivotal.io>
This commit is contained in:
parent
b9047c22e0
commit
61b86ff231
|
@ -57,6 +57,21 @@ include::{snippets}loggers/single/response-fields.adoc[]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[[loggers-group]]
|
||||||
|
== Retrieving a Single Group
|
||||||
|
|
||||||
|
To retrieve a single group, make a `GET` request to `/actuator/loggers/{group.name}`,
|
||||||
|
as shown in the following curl-based example:
|
||||||
|
|
||||||
|
include::{snippets}loggers/group/curl-request.adoc[]
|
||||||
|
|
||||||
|
The preceding example retrieves information about the logger group named `test`. The
|
||||||
|
resulting response is similar to the following:
|
||||||
|
|
||||||
|
include::{snippets}loggers/group/http-response.adoc[]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[[loggers-setting-level]]
|
[[loggers-setting-level]]
|
||||||
== Setting a Log Level
|
== Setting a Log Level
|
||||||
|
|
||||||
|
@ -81,6 +96,30 @@ include::{snippets}loggers/set/request-fields.adoc[]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[[loggers-setting-level]]
|
||||||
|
== Setting a Log Level for a Group
|
||||||
|
|
||||||
|
To set the level of a logger, make a `POST` request to
|
||||||
|
`/actuator/loggers/{group.name}` with a JSON body that specifies the configured level
|
||||||
|
for the logger group, as shown in the following curl-based example:
|
||||||
|
|
||||||
|
include::{snippets}loggers/setGroup/curl-request.adoc[]
|
||||||
|
|
||||||
|
The preceding example sets the `configuredLevel` of the `test` logger group to `DEBUG`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[[loggers-setting-level-request-structure]]
|
||||||
|
=== Request Structure
|
||||||
|
|
||||||
|
The request specifies the desired level of the logger group. The following table describes the
|
||||||
|
structure of the request:
|
||||||
|
|
||||||
|
[cols="3,1,3"]
|
||||||
|
include::{snippets}loggers/set/request-fields.adoc[]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[[loggers-clearing-level]]
|
[[loggers-clearing-level]]
|
||||||
== Clearing a Log Level
|
== Clearing a Log Level
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
||||||
import org.springframework.boot.logging.LoggingGroups;
|
import org.springframework.boot.logging.LoggerGroups;
|
||||||
import org.springframework.boot.logging.LoggingSystem;
|
import org.springframework.boot.logging.LoggingSystem;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.ConditionContext;
|
import org.springframework.context.annotation.ConditionContext;
|
||||||
|
@ -48,8 +48,8 @@ public class LoggersEndpointAutoConfiguration {
|
||||||
@Conditional(OnEnabledLoggingSystemCondition.class)
|
@Conditional(OnEnabledLoggingSystemCondition.class)
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
public LoggersEndpoint loggersEndpoint(LoggingSystem loggingSystem,
|
public LoggersEndpoint loggersEndpoint(LoggingSystem loggingSystem,
|
||||||
ObjectProvider<LoggingGroups> loggingGroupsObjectProvider) {
|
ObjectProvider<LoggerGroups> springBootLoggerGroups) {
|
||||||
return new LoggersEndpoint(loggingSystem, loggingGroupsObjectProvider.getIfAvailable());
|
return new LoggersEndpoint(loggingSystem, springBootLoggerGroups.getIfAvailable(LoggerGroups::new));
|
||||||
}
|
}
|
||||||
|
|
||||||
static class OnEnabledLoggingSystemCondition extends SpringBootCondition {
|
static class OnEnabledLoggingSystemCondition extends SpringBootCondition {
|
||||||
|
|
|
@ -20,14 +20,15 @@ import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.beans.factory.ObjectProvider;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.actuate.logging.LoggersEndpoint;
|
import org.springframework.boot.actuate.logging.LoggersEndpoint;
|
||||||
import org.springframework.boot.logging.LogLevel;
|
import org.springframework.boot.logging.LogLevel;
|
||||||
import org.springframework.boot.logging.LoggerConfiguration;
|
import org.springframework.boot.logging.LoggerConfiguration;
|
||||||
import org.springframework.boot.logging.LoggingGroups;
|
import org.springframework.boot.logging.LoggerGroups;
|
||||||
import org.springframework.boot.logging.LoggingSystem;
|
import org.springframework.boot.logging.LoggingSystem;
|
||||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
@ -57,18 +58,20 @@ class LoggersEndpointDocumentationTests extends MockMvcEndpointDocumentationTest
|
||||||
fieldWithPath("configuredLevel").description("Configured level of the logger, if any.").optional(),
|
fieldWithPath("configuredLevel").description("Configured level of the logger, if any.").optional(),
|
||||||
fieldWithPath("effectiveLevel").description("Effective level of the logger."));
|
fieldWithPath("effectiveLevel").description("Effective level of the logger."));
|
||||||
|
|
||||||
private static final List<FieldDescriptor> groupLevelFields = Arrays.asList(
|
private static final List<FieldDescriptor> groupLevelFields;
|
||||||
fieldWithPath("configuredLevel").description("Configured level of the logger group"),
|
|
||||||
fieldWithPath("members").description("Loggers that are part of this group").optional());
|
static {
|
||||||
|
groupLevelFields = Arrays.asList(
|
||||||
|
fieldWithPath("configuredLevel").description("Configured level of the logger group")
|
||||||
|
.type(LogLevel.class).optional(),
|
||||||
|
fieldWithPath("members").description("Loggers that are part of this group").optional());
|
||||||
|
}
|
||||||
|
|
||||||
@MockBean
|
@MockBean
|
||||||
private LoggingSystem loggingSystem;
|
private LoggingSystem loggingSystem;
|
||||||
|
|
||||||
@MockBean
|
@Autowired
|
||||||
private ObjectProvider<LoggingGroups> loggingGroupsObjectProvider;
|
private LoggerGroups loggerGroups;
|
||||||
|
|
||||||
@MockBean
|
|
||||||
LoggingGroups loggingGroups;
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void allLoggers() throws Exception {
|
void allLoggers() throws Exception {
|
||||||
|
@ -76,10 +79,6 @@ class LoggersEndpointDocumentationTests extends MockMvcEndpointDocumentationTest
|
||||||
given(this.loggingSystem.getLoggerConfigurations())
|
given(this.loggingSystem.getLoggerConfigurations())
|
||||||
.willReturn(Arrays.asList(new LoggerConfiguration("ROOT", LogLevel.INFO, LogLevel.INFO),
|
.willReturn(Arrays.asList(new LoggerConfiguration("ROOT", LogLevel.INFO, LogLevel.INFO),
|
||||||
new LoggerConfiguration("com.example", LogLevel.DEBUG, LogLevel.DEBUG)));
|
new LoggerConfiguration("com.example", LogLevel.DEBUG, LogLevel.DEBUG)));
|
||||||
given(this.loggingGroupsObjectProvider.getIfAvailable()).willReturn(this.loggingGroups);
|
|
||||||
given(this.loggingGroups.getLoggerGroupNames()).willReturn(Collections.singleton("test"));
|
|
||||||
given(this.loggingGroups.getLoggerGroup("test")).willReturn(Arrays.asList("test.member"));
|
|
||||||
given(this.loggingGroups.getLoggerGroupConfiguredLevel("test")).willReturn(LogLevel.INFO);
|
|
||||||
this.mockMvc.perform(get("/actuator/loggers")).andExpect(status().isOk())
|
this.mockMvc.perform(get("/actuator/loggers")).andExpect(status().isOk())
|
||||||
.andDo(MockMvcRestDocumentation.document("loggers/all",
|
.andDo(MockMvcRestDocumentation.document("loggers/all",
|
||||||
responseFields(fieldWithPath("levels").description("Levels support by the logging system."),
|
responseFields(fieldWithPath("levels").description("Levels support by the logging system."),
|
||||||
|
@ -91,7 +90,6 @@ class LoggersEndpointDocumentationTests extends MockMvcEndpointDocumentationTest
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void logger() throws Exception {
|
void logger() throws Exception {
|
||||||
given(this.loggingGroupsObjectProvider.getIfAvailable()).willReturn(this.loggingGroups);
|
|
||||||
given(this.loggingSystem.getLoggerConfiguration("com.example"))
|
given(this.loggingSystem.getLoggerConfiguration("com.example"))
|
||||||
.willReturn(new LoggerConfiguration("com.example", LogLevel.INFO, LogLevel.INFO));
|
.willReturn(new LoggerConfiguration("com.example", LogLevel.INFO, LogLevel.INFO));
|
||||||
this.mockMvc.perform(get("/actuator/loggers/com.example")).andExpect(status().isOk())
|
this.mockMvc.perform(get("/actuator/loggers/com.example")).andExpect(status().isOk())
|
||||||
|
@ -100,17 +98,12 @@ class LoggersEndpointDocumentationTests extends MockMvcEndpointDocumentationTest
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void loggerGroups() throws Exception {
|
void loggerGroups() throws Exception {
|
||||||
given(this.loggingGroupsObjectProvider.getIfAvailable()).willReturn(this.loggingGroups);
|
this.mockMvc.perform(get("/actuator/loggers/test")).andExpect(status().isOk())
|
||||||
given(this.loggingGroups.isGroup("com.example")).willReturn(true);
|
|
||||||
given(this.loggingGroups.getLoggerGroup("com.example")).willReturn(Arrays.asList("com.member", "com.member2"));
|
|
||||||
given(this.loggingGroups.getLoggerGroupConfiguredLevel("com.example")).willReturn(LogLevel.INFO);
|
|
||||||
this.mockMvc.perform(get("/actuator/loggers/com.example")).andExpect(status().isOk())
|
|
||||||
.andDo(MockMvcRestDocumentation.document("loggers/group", responseFields(groupLevelFields)));
|
.andDo(MockMvcRestDocumentation.document("loggers/group", responseFields(groupLevelFields)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void setLogLevel() throws Exception {
|
void setLogLevel() throws Exception {
|
||||||
given(this.loggingGroupsObjectProvider.getIfAvailable()).willReturn(this.loggingGroups);
|
|
||||||
this.mockMvc
|
this.mockMvc
|
||||||
.perform(post("/actuator/loggers/com.example").content("{\"configuredLevel\":\"debug\"}")
|
.perform(post("/actuator/loggers/com.example").content("{\"configuredLevel\":\"debug\"}")
|
||||||
.contentType(MediaType.APPLICATION_JSON))
|
.contentType(MediaType.APPLICATION_JSON))
|
||||||
|
@ -122,22 +115,26 @@ class LoggersEndpointDocumentationTests extends MockMvcEndpointDocumentationTest
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void setLogLevelOfLoggerGroup() throws Exception {
|
void setLogLevelOfLoggerGroup() throws Exception {
|
||||||
given(this.loggingGroupsObjectProvider.getIfAvailable()).willReturn(this.loggingGroups);
|
|
||||||
given(this.loggingGroups.isGroup("com.example")).willReturn(true);
|
|
||||||
this.mockMvc
|
this.mockMvc
|
||||||
.perform(post("/actuator/loggers/com.example")
|
.perform(post("/actuator/loggers/test")
|
||||||
.content("{\"configuredLevel\":\"debug\"}").contentType(MediaType.APPLICATION_JSON))
|
.content("{\"configuredLevel\":\"debug\"}").contentType(MediaType.APPLICATION_JSON))
|
||||||
.andExpect(status().isNoContent()).andDo(
|
.andExpect(status().isNoContent()).andDo(
|
||||||
MockMvcRestDocumentation.document("loggers/setGroup",
|
MockMvcRestDocumentation.document("loggers/setGroup",
|
||||||
requestFields(fieldWithPath("configuredLevel").description(
|
requestFields(fieldWithPath("configuredLevel").description(
|
||||||
"Level for the logger group. May be omitted to clear the level of the loggers.")
|
"Level for the logger group. May be omitted to clear the level of the loggers.")
|
||||||
.optional())));
|
.optional())));
|
||||||
verify(this.loggingGroups).setLoggerGroupLevel("com.example", LogLevel.DEBUG);
|
verify(this.loggingSystem).setLogLevel("test.member1", LogLevel.DEBUG);
|
||||||
|
verify(this.loggingSystem).setLogLevel("test.member2", LogLevel.DEBUG);
|
||||||
|
resetLogger();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetLogger() {
|
||||||
|
this.loggerGroups.get("test").configureLogLevel(null, (a, b) -> {
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void clearLogLevel() throws Exception {
|
void clearLogLevel() throws Exception {
|
||||||
given(this.loggingGroupsObjectProvider.getIfAvailable()).willReturn(this.loggingGroups);
|
|
||||||
this.mockMvc
|
this.mockMvc
|
||||||
.perform(post("/actuator/loggers/com.example").content("{}").contentType(MediaType.APPLICATION_JSON))
|
.perform(post("/actuator/loggers/com.example").content("{}").contentType(MediaType.APPLICATION_JSON))
|
||||||
.andExpect(status().isNoContent()).andDo(MockMvcRestDocumentation.document("loggers/clear"));
|
.andExpect(status().isNoContent()).andDo(MockMvcRestDocumentation.document("loggers/clear"));
|
||||||
|
@ -149,9 +146,13 @@ class LoggersEndpointDocumentationTests extends MockMvcEndpointDocumentationTest
|
||||||
static class TestConfiguration {
|
static class TestConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
LoggersEndpoint endpoint(LoggingSystem loggingSystem,
|
LoggersEndpoint endpoint(LoggingSystem loggingSystem, LoggerGroups groups) {
|
||||||
ObjectProvider<LoggingGroups> loggingGroupsObjectProvider) {
|
groups.putAll(getLoggerGroups());
|
||||||
return new LoggersEndpoint(loggingSystem, loggingGroupsObjectProvider.getIfAvailable());
|
return new LoggersEndpoint(loggingSystem, groups);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, List<String>> getLoggerGroups() {
|
||||||
|
return Collections.singletonMap("test", Arrays.asList("test.member1", "test.member2"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,8 @@ import org.springframework.boot.actuate.endpoint.annotation.Selector;
|
||||||
import org.springframework.boot.actuate.endpoint.annotation.WriteOperation;
|
import org.springframework.boot.actuate.endpoint.annotation.WriteOperation;
|
||||||
import org.springframework.boot.logging.LogLevel;
|
import org.springframework.boot.logging.LogLevel;
|
||||||
import org.springframework.boot.logging.LoggerConfiguration;
|
import org.springframework.boot.logging.LoggerConfiguration;
|
||||||
import org.springframework.boot.logging.LoggingGroups;
|
import org.springframework.boot.logging.LoggerGroup;
|
||||||
|
import org.springframework.boot.logging.LoggerGroups;
|
||||||
import org.springframework.boot.logging.LoggingSystem;
|
import org.springframework.boot.logging.LoggingSystem;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
@ -49,17 +50,18 @@ public class LoggersEndpoint {
|
||||||
|
|
||||||
private final LoggingSystem loggingSystem;
|
private final LoggingSystem loggingSystem;
|
||||||
|
|
||||||
private final LoggingGroups loggingGroups;
|
private final LoggerGroups loggerGroups;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new {@link LoggersEndpoint} instance.
|
* Create a new {@link LoggersEndpoint} instance.
|
||||||
* @param loggingSystem the logging system to expose
|
* @param loggingSystem the logging system to expose
|
||||||
* @param loggingGroups the logging group to expose if it exists
|
* @param loggerGroups the logger group to expose
|
||||||
*/
|
*/
|
||||||
public LoggersEndpoint(LoggingSystem loggingSystem, LoggingGroups loggingGroups) {
|
public LoggersEndpoint(LoggingSystem loggingSystem, LoggerGroups loggerGroups) {
|
||||||
Assert.notNull(loggingSystem, "LoggingSystem must not be null");
|
Assert.notNull(loggingSystem, "LoggingSystem must not be null");
|
||||||
|
Assert.notNull(loggerGroups, "LoggerGroups must not be null");
|
||||||
this.loggingSystem = loggingSystem;
|
this.loggingSystem = loggingSystem;
|
||||||
this.loggingGroups = loggingGroups;
|
this.loggerGroups = loggerGroups;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReadOperation
|
@ReadOperation
|
||||||
|
@ -71,20 +73,23 @@ public class LoggersEndpoint {
|
||||||
Map<String, Object> result = new LinkedHashMap<>();
|
Map<String, Object> result = new LinkedHashMap<>();
|
||||||
result.put("levels", getLevels());
|
result.put("levels", getLevels());
|
||||||
result.put("loggers", getLoggers(configurations));
|
result.put("loggers", getLoggers(configurations));
|
||||||
if (this.loggingGroups != null && this.loggingGroups.getLoggerGroupNames() != null) {
|
result.put("groups", getGroups());
|
||||||
Set<String> groups = this.loggingGroups.getLoggerGroupNames();
|
|
||||||
result.put("groups", getLoggerGroups(groups));
|
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Map<String, LoggerLevels> getGroups() {
|
||||||
|
Map<String, LoggerLevels> groups = new LinkedHashMap<>();
|
||||||
|
this.loggerGroups.forEach((group) -> groups.put(group.getName(),
|
||||||
|
new GroupLoggerLevels(group.getConfiguredLevel(), group.getMembers())));
|
||||||
|
return groups;
|
||||||
|
}
|
||||||
|
|
||||||
@ReadOperation
|
@ReadOperation
|
||||||
public LoggerLevels loggerLevels(@Selector String name) {
|
public LoggerLevels loggerLevels(@Selector String name) {
|
||||||
Assert.notNull(name, "Name must not be null");
|
Assert.notNull(name, "Name must not be null");
|
||||||
if (this.loggingGroups != null && this.loggingGroups.isGroup(name)) {
|
LoggerGroup group = this.loggerGroups.get(name);
|
||||||
List<String> members = this.loggingGroups.getLoggerGroup(name);
|
if (group != null) {
|
||||||
LogLevel groupConfiguredLevel = this.loggingGroups.getLoggerGroupConfiguredLevel(name);
|
return new GroupLoggerLevels(group.getConfiguredLevel(), group.getMembers());
|
||||||
return new GroupLoggerLevels(groupConfiguredLevel, members);
|
|
||||||
}
|
}
|
||||||
LoggerConfiguration configuration = this.loggingSystem.getLoggerConfiguration(name);
|
LoggerConfiguration configuration = this.loggingSystem.getLoggerConfiguration(name);
|
||||||
return (configuration != null) ? new SingleLoggerLevels(configuration) : null;
|
return (configuration != null) ? new SingleLoggerLevels(configuration) : null;
|
||||||
|
@ -93,8 +98,9 @@ public class LoggersEndpoint {
|
||||||
@WriteOperation
|
@WriteOperation
|
||||||
public void configureLogLevel(@Selector String name, @Nullable LogLevel configuredLevel) {
|
public void configureLogLevel(@Selector String name, @Nullable LogLevel configuredLevel) {
|
||||||
Assert.notNull(name, "Name must not be empty");
|
Assert.notNull(name, "Name must not be empty");
|
||||||
if (this.loggingGroups != null && this.loggingGroups.isGroup(name)) {
|
LoggerGroup group = this.loggerGroups.get(name);
|
||||||
this.loggingGroups.setLoggerGroupLevel(name, configuredLevel);
|
if (group != null && group.hasMembers()) {
|
||||||
|
group.configureLogLevel(configuredLevel, this.loggingSystem::setLogLevel);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.loggingSystem.setLogLevel(name, configuredLevel);
|
this.loggingSystem.setLogLevel(name, configuredLevel);
|
||||||
|
@ -113,16 +119,6 @@ public class LoggersEndpoint {
|
||||||
return loggers;
|
return loggers;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, LoggerLevels> getLoggerGroups(Set<String> groups) {
|
|
||||||
Map<String, LoggerLevels> loggerGroups = new LinkedHashMap<>(groups.size());
|
|
||||||
for (String name : groups) {
|
|
||||||
List<String> members = this.loggingGroups.getLoggerGroup(name);
|
|
||||||
LogLevel groupConfiguredLevel = this.loggingGroups.getLoggerGroupConfiguredLevel(name);
|
|
||||||
loggerGroups.put(name, new GroupLoggerLevels(groupConfiguredLevel, members));
|
|
||||||
}
|
|
||||||
return loggerGroups;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Levels configured for a given logger exposed in a JSON friendly way.
|
* Levels configured for a given logger exposed in a JSON friendly way.
|
||||||
*/
|
*/
|
||||||
|
@ -134,13 +130,12 @@ public class LoggersEndpoint {
|
||||||
this.configuredLevel = getName(configuredLevel);
|
this.configuredLevel = getName(configuredLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getName(LogLevel level) {
|
protected final String getName(LogLevel level) {
|
||||||
return (level != null) ? level.name() : null;
|
return (level != null) ? level.name() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getConfiguredLevel() {
|
public String getConfiguredLevel() {
|
||||||
return this.configuredLevel;
|
return this.configuredLevel;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -166,7 +161,7 @@ public class LoggersEndpoint {
|
||||||
|
|
||||||
public SingleLoggerLevels(LoggerConfiguration configuration) {
|
public SingleLoggerLevels(LoggerConfiguration configuration) {
|
||||||
super(configuration.getConfiguredLevel());
|
super(configuration.getConfiguredLevel());
|
||||||
this.effectiveLevel = super.getName(configuration.getEffectiveLevel());
|
this.effectiveLevel = getName(configuration.getEffectiveLevel());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getEffectiveLevel() {
|
public String getEffectiveLevel() {
|
||||||
|
|
|
@ -18,9 +18,11 @@ package org.springframework.boot.actuate.logging;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.boot.actuate.logging.LoggersEndpoint.GroupLoggerLevels;
|
import org.springframework.boot.actuate.logging.LoggersEndpoint.GroupLoggerLevels;
|
||||||
|
@ -28,7 +30,7 @@ import org.springframework.boot.actuate.logging.LoggersEndpoint.LoggerLevels;
|
||||||
import org.springframework.boot.actuate.logging.LoggersEndpoint.SingleLoggerLevels;
|
import org.springframework.boot.actuate.logging.LoggersEndpoint.SingleLoggerLevels;
|
||||||
import org.springframework.boot.logging.LogLevel;
|
import org.springframework.boot.logging.LogLevel;
|
||||||
import org.springframework.boot.logging.LoggerConfiguration;
|
import org.springframework.boot.logging.LoggerConfiguration;
|
||||||
import org.springframework.boot.logging.LoggingGroups;
|
import org.springframework.boot.logging.LoggerGroups;
|
||||||
import org.springframework.boot.logging.LoggingSystem;
|
import org.springframework.boot.logging.LoggingSystem;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
@ -42,12 +44,21 @@ import static org.mockito.Mockito.verify;
|
||||||
* @author Ben Hale
|
* @author Ben Hale
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
* @author HaiTao Zhang
|
* @author HaiTao Zhang
|
||||||
|
* @author Madhura Bhave
|
||||||
*/
|
*/
|
||||||
class LoggersEndpointTests {
|
class LoggersEndpointTests {
|
||||||
|
|
||||||
private final LoggingSystem loggingSystem = mock(LoggingSystem.class);
|
private final LoggingSystem loggingSystem = mock(LoggingSystem.class);
|
||||||
|
|
||||||
private final LoggingGroups loggingGroups = mock(LoggingGroups.class);
|
private LoggerGroups loggerGroups;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setup() {
|
||||||
|
Map<String, List<String>> groups = Collections.singletonMap("test", Collections.singletonList("test.member"));
|
||||||
|
this.loggerGroups = new LoggerGroups(groups);
|
||||||
|
this.loggerGroups.get("test").configureLogLevel(LogLevel.DEBUG, (a, b) -> {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
@ -55,8 +66,7 @@ class LoggersEndpointTests {
|
||||||
given(this.loggingSystem.getLoggerConfigurations())
|
given(this.loggingSystem.getLoggerConfigurations())
|
||||||
.willReturn(Collections.singletonList(new LoggerConfiguration("ROOT", null, LogLevel.DEBUG)));
|
.willReturn(Collections.singletonList(new LoggerConfiguration("ROOT", null, LogLevel.DEBUG)));
|
||||||
given(this.loggingSystem.getSupportedLogLevels()).willReturn(EnumSet.allOf(LogLevel.class));
|
given(this.loggingSystem.getSupportedLogLevels()).willReturn(EnumSet.allOf(LogLevel.class));
|
||||||
given(this.loggingGroups.getLoggerGroupNames()).willReturn(null);
|
Map<String, Object> result = new LoggersEndpoint(this.loggingSystem, new LoggerGroups()).loggers();
|
||||||
Map<String, Object> result = new LoggersEndpoint(this.loggingSystem, this.loggingGroups).loggers();
|
|
||||||
Map<String, LoggerLevels> loggers = (Map<String, LoggerLevels>) result.get("loggers");
|
Map<String, LoggerLevels> loggers = (Map<String, LoggerLevels>) result.get("loggers");
|
||||||
Set<LogLevel> levels = (Set<LogLevel>) result.get("levels");
|
Set<LogLevel> levels = (Set<LogLevel>) result.get("levels");
|
||||||
SingleLoggerLevels rootLevels = (SingleLoggerLevels) loggers.get("ROOT");
|
SingleLoggerLevels rootLevels = (SingleLoggerLevels) loggers.get("ROOT");
|
||||||
|
@ -64,7 +74,8 @@ class LoggersEndpointTests {
|
||||||
assertThat(rootLevels.getEffectiveLevel()).isEqualTo("DEBUG");
|
assertThat(rootLevels.getEffectiveLevel()).isEqualTo("DEBUG");
|
||||||
assertThat(levels).containsExactly(LogLevel.OFF, LogLevel.FATAL, LogLevel.ERROR, LogLevel.WARN, LogLevel.INFO,
|
assertThat(levels).containsExactly(LogLevel.OFF, LogLevel.FATAL, LogLevel.ERROR, LogLevel.WARN, LogLevel.INFO,
|
||||||
LogLevel.DEBUG, LogLevel.TRACE);
|
LogLevel.DEBUG, LogLevel.TRACE);
|
||||||
assertThat(result.get("groups")).isNull();
|
Map<String, LoggerGroups> groups = (Map<String, LoggerGroups>) result.get("groups");
|
||||||
|
assertThat(groups).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -73,12 +84,9 @@ class LoggersEndpointTests {
|
||||||
given(this.loggingSystem.getLoggerConfigurations())
|
given(this.loggingSystem.getLoggerConfigurations())
|
||||||
.willReturn(Collections.singletonList(new LoggerConfiguration("ROOT", null, LogLevel.DEBUG)));
|
.willReturn(Collections.singletonList(new LoggerConfiguration("ROOT", null, LogLevel.DEBUG)));
|
||||||
given(this.loggingSystem.getSupportedLogLevels()).willReturn(EnumSet.allOf(LogLevel.class));
|
given(this.loggingSystem.getSupportedLogLevels()).willReturn(EnumSet.allOf(LogLevel.class));
|
||||||
given(this.loggingGroups.getLoggerGroup("test")).willReturn(Collections.singletonList("test.member"));
|
Map<String, Object> result = new LoggersEndpoint(this.loggingSystem, this.loggerGroups).loggers();
|
||||||
given(this.loggingGroups.getLoggerGroupNames()).willReturn(Collections.singleton("test"));
|
Map<String, GroupLoggerLevels> loggerGroups = (Map<String, GroupLoggerLevels>) result.get("groups");
|
||||||
given(this.loggingGroups.getLoggerGroupConfiguredLevel("test")).willReturn(LogLevel.DEBUG);
|
GroupLoggerLevels groupLevel = loggerGroups.get("test");
|
||||||
Map<String, Object> result = new LoggersEndpoint(this.loggingSystem, this.loggingGroups).loggers();
|
|
||||||
Map<String, LoggerLevels> loggerGroups = (Map<String, LoggerLevels>) result.get("groups");
|
|
||||||
GroupLoggerLevels testLoggerLevel = (GroupLoggerLevels) loggerGroups.get("test");
|
|
||||||
Map<String, LoggerLevels> loggers = (Map<String, LoggerLevels>) result.get("loggers");
|
Map<String, LoggerLevels> loggers = (Map<String, LoggerLevels>) result.get("loggers");
|
||||||
Set<LogLevel> levels = (Set<LogLevel>) result.get("levels");
|
Set<LogLevel> levels = (Set<LogLevel>) result.get("levels");
|
||||||
SingleLoggerLevels rootLevels = (SingleLoggerLevels) loggers.get("ROOT");
|
SingleLoggerLevels rootLevels = (SingleLoggerLevels) loggers.get("ROOT");
|
||||||
|
@ -87,17 +95,15 @@ class LoggersEndpointTests {
|
||||||
assertThat(levels).containsExactly(LogLevel.OFF, LogLevel.FATAL, LogLevel.ERROR, LogLevel.WARN, LogLevel.INFO,
|
assertThat(levels).containsExactly(LogLevel.OFF, LogLevel.FATAL, LogLevel.ERROR, LogLevel.WARN, LogLevel.INFO,
|
||||||
LogLevel.DEBUG, LogLevel.TRACE);
|
LogLevel.DEBUG, LogLevel.TRACE);
|
||||||
assertThat(loggerGroups).isNotNull();
|
assertThat(loggerGroups).isNotNull();
|
||||||
assertThat(testLoggerLevel).isNotNull();
|
assertThat(groupLevel.getConfiguredLevel()).isEqualTo("DEBUG");
|
||||||
assertThat(testLoggerLevel.getConfiguredLevel()).isEqualTo("DEBUG");
|
assertThat(groupLevel.getMembers()).containsExactly("test.member");
|
||||||
assertThat(testLoggerLevel.getMembers()).isEqualTo(Collections.singletonList("test.member"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void loggerLevelsWhenNameSpecifiedShouldReturnLevels() {
|
void loggerLevelsWhenNameSpecifiedShouldReturnLevels() {
|
||||||
given(this.loggingGroups.isGroup("ROOT")).willReturn(false);
|
|
||||||
given(this.loggingSystem.getLoggerConfiguration("ROOT"))
|
given(this.loggingSystem.getLoggerConfiguration("ROOT"))
|
||||||
.willReturn(new LoggerConfiguration("ROOT", null, LogLevel.DEBUG));
|
.willReturn(new LoggerConfiguration("ROOT", null, LogLevel.DEBUG));
|
||||||
SingleLoggerLevels levels = (SingleLoggerLevels) new LoggersEndpoint(this.loggingSystem, this.loggingGroups)
|
SingleLoggerLevels levels = (SingleLoggerLevels) new LoggersEndpoint(this.loggingSystem, this.loggerGroups)
|
||||||
.loggerLevels("ROOT");
|
.loggerLevels("ROOT");
|
||||||
assertThat(levels.getConfiguredLevel()).isNull();
|
assertThat(levels.getConfiguredLevel()).isNull();
|
||||||
assertThat(levels.getEffectiveLevel()).isEqualTo("DEBUG");
|
assertThat(levels.getEffectiveLevel()).isEqualTo("DEBUG");
|
||||||
|
@ -105,10 +111,7 @@ class LoggersEndpointTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void groupNameSpecifiedShouldReturnConfiguredLevelAndMembers() {
|
void groupNameSpecifiedShouldReturnConfiguredLevelAndMembers() {
|
||||||
given(this.loggingGroups.isGroup("test")).willReturn(true);
|
GroupLoggerLevels levels = (GroupLoggerLevels) new LoggersEndpoint(this.loggingSystem, this.loggerGroups)
|
||||||
given(this.loggingGroups.getLoggerGroup("test")).willReturn(Collections.singletonList("test.member"));
|
|
||||||
given(this.loggingGroups.getLoggerGroupConfiguredLevel("test")).willReturn(LogLevel.DEBUG);
|
|
||||||
GroupLoggerLevels levels = (GroupLoggerLevels) new LoggersEndpoint(this.loggingSystem, this.loggingGroups)
|
|
||||||
.loggerLevels("test");
|
.loggerLevels("test");
|
||||||
assertThat(levels.getConfiguredLevel()).isEqualTo("DEBUG");
|
assertThat(levels.getConfiguredLevel()).isEqualTo("DEBUG");
|
||||||
assertThat(levels.getMembers()).isEqualTo(Collections.singletonList("test.member"));
|
assertThat(levels.getMembers()).isEqualTo(Collections.singletonList("test.member"));
|
||||||
|
@ -116,35 +119,26 @@ class LoggersEndpointTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void configureLogLevelShouldSetLevelOnLoggingSystem() {
|
void configureLogLevelShouldSetLevelOnLoggingSystem() {
|
||||||
given(this.loggingGroups.getLoggerGroup("ROOT")).willReturn(null);
|
new LoggersEndpoint(this.loggingSystem, this.loggerGroups).configureLogLevel("ROOT", LogLevel.DEBUG);
|
||||||
new LoggersEndpoint(this.loggingSystem, this.loggingGroups).configureLogLevel("ROOT", LogLevel.DEBUG);
|
|
||||||
verify(this.loggingSystem).setLogLevel("ROOT", LogLevel.DEBUG);
|
verify(this.loggingSystem).setLogLevel("ROOT", LogLevel.DEBUG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void configureLogLevelWithNullSetsLevelOnLoggingSystemToNull() {
|
void configureLogLevelWithNullSetsLevelOnLoggingSystemToNull() {
|
||||||
given(this.loggingGroups.getLoggerGroup("ROOT")).willReturn(null);
|
new LoggersEndpoint(this.loggingSystem, this.loggerGroups).configureLogLevel("ROOT", null);
|
||||||
new LoggersEndpoint(this.loggingSystem, this.loggingGroups).configureLogLevel("ROOT", null);
|
|
||||||
verify(this.loggingSystem).setLogLevel("ROOT", null);
|
verify(this.loggingSystem).setLogLevel("ROOT", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void configureLogLevelInLoggerGroupShouldSetLevelOnLoggingSystem() {
|
void configureLogLevelInLoggerGroupShouldSetLevelOnLoggingSystem() {
|
||||||
given(this.loggingGroups.isGroup("test")).willReturn(true);
|
new LoggersEndpoint(this.loggingSystem, this.loggerGroups).configureLogLevel("test", LogLevel.DEBUG);
|
||||||
given(this.loggingGroups.getLoggerGroup("test")).willReturn(Collections.singletonList("test.member"));
|
verify(this.loggingSystem).setLogLevel("test.member", LogLevel.DEBUG);
|
||||||
new LoggersEndpoint(this.loggingSystem, this.loggingGroups).configureLogLevel("test", LogLevel.DEBUG);
|
|
||||||
verify(this.loggingGroups).setLoggerGroupLevel("test", LogLevel.DEBUG);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void configureLogLevelWithNullInLoggerGroupShouldSetLevelOnLoggingSystem() {
|
void configureLogLevelWithNullInLoggerGroupShouldSetLevelOnLoggingSystem() {
|
||||||
given(this.loggingGroups.isGroup("test")).willReturn(true);
|
new LoggersEndpoint(this.loggingSystem, this.loggerGroups).configureLogLevel("test", null);
|
||||||
given(this.loggingGroups.getLoggerGroup("test")).willReturn(Collections.singletonList("test.member"));
|
verify(this.loggingSystem).setLogLevel("test.member", null);
|
||||||
new LoggersEndpoint(this.loggingSystem, this.loggingGroups).configureLogLevel("test", null);
|
|
||||||
verify(this.loggingGroups).setLoggerGroupLevel("test", null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Test
|
|
||||||
// void
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,9 @@ package org.springframework.boot.actuate.logging;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import net.minidev.json.JSONArray;
|
import net.minidev.json.JSONArray;
|
||||||
import org.hamcrest.collection.IsIterableContainingInAnyOrder;
|
import org.hamcrest.collection.IsIterableContainingInAnyOrder;
|
||||||
|
@ -31,7 +34,7 @@ import org.springframework.boot.actuate.endpoint.http.ActuatorMediaType;
|
||||||
import org.springframework.boot.actuate.endpoint.web.test.WebEndpointTest;
|
import org.springframework.boot.actuate.endpoint.web.test.WebEndpointTest;
|
||||||
import org.springframework.boot.logging.LogLevel;
|
import org.springframework.boot.logging.LogLevel;
|
||||||
import org.springframework.boot.logging.LoggerConfiguration;
|
import org.springframework.boot.logging.LoggerConfiguration;
|
||||||
import org.springframework.boot.logging.LoggingGroups;
|
import org.springframework.boot.logging.LoggerGroups;
|
||||||
import org.springframework.boot.logging.LoggingSystem;
|
import org.springframework.boot.logging.LoggingSystem;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
@ -54,6 +57,7 @@ import static org.mockito.Mockito.verifyZeroInteractions;
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
* @author HaiTao Zhang
|
* @author HaiTao Zhang
|
||||||
|
* @author Madhura Bhave
|
||||||
*/
|
*/
|
||||||
class LoggersEndpointWebIntegrationTests {
|
class LoggersEndpointWebIntegrationTests {
|
||||||
|
|
||||||
|
@ -61,41 +65,21 @@ class LoggersEndpointWebIntegrationTests {
|
||||||
|
|
||||||
private LoggingSystem loggingSystem;
|
private LoggingSystem loggingSystem;
|
||||||
|
|
||||||
private LoggingGroups loggingGroups;
|
private LoggerGroups loggerGroups;
|
||||||
|
|
||||||
private ObjectProvider<LoggingGroups> loggingGroupsObjectProvider;
|
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
@AfterEach
|
@AfterEach
|
||||||
void resetMocks(ConfigurableApplicationContext context, WebTestClient client) {
|
void resetMocks(ConfigurableApplicationContext context, WebTestClient client) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.loggingSystem = context.getBean(LoggingSystem.class);
|
this.loggingSystem = context.getBean(LoggingSystem.class);
|
||||||
this.loggingGroups = context.getBean(LoggingGroups.class);
|
this.loggerGroups = context.getBean(LoggerGroups.class);
|
||||||
this.loggingGroupsObjectProvider = context.getBean(ObjectProvider.class);
|
|
||||||
Mockito.reset(this.loggingSystem);
|
Mockito.reset(this.loggingSystem);
|
||||||
Mockito.reset(this.loggingGroups);
|
|
||||||
given(this.loggingSystem.getSupportedLogLevels()).willReturn(EnumSet.allOf(LogLevel.class));
|
given(this.loggingSystem.getSupportedLogLevels()).willReturn(EnumSet.allOf(LogLevel.class));
|
||||||
given(this.loggingGroupsObjectProvider.getIfAvailable()).willReturn(this.loggingGroups);
|
|
||||||
}
|
|
||||||
|
|
||||||
@WebEndpointTest
|
|
||||||
void getLoggerShouldReturnAllLoggerConfigurations() {
|
|
||||||
given(this.loggingGroups.getLoggerGroupNames()).willReturn(null);
|
|
||||||
given(this.loggingSystem.getLoggerConfigurations())
|
|
||||||
.willReturn(Collections.singletonList(new LoggerConfiguration("ROOT", null, LogLevel.DEBUG)));
|
|
||||||
this.client.get().uri("/actuator/loggers").exchange().expectStatus().isOk().expectBody().jsonPath("$.length()")
|
|
||||||
.isEqualTo(2).jsonPath("levels")
|
|
||||||
.isEqualTo(jsonArrayOf("OFF", "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE"))
|
|
||||||
.jsonPath("loggers.length()").isEqualTo(1).jsonPath("loggers.ROOT.length()").isEqualTo(2)
|
|
||||||
.jsonPath("loggers.ROOT.configuredLevel").isEqualTo(null).jsonPath("loggers.ROOT.effectiveLevel")
|
|
||||||
.isEqualTo("DEBUG");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@WebEndpointTest
|
@WebEndpointTest
|
||||||
void getLoggerShouldReturnAllLoggerConfigurationsWithLoggerGroups() {
|
void getLoggerShouldReturnAllLoggerConfigurationsWithLoggerGroups() {
|
||||||
given(this.loggingGroups.getLoggerGroupNames()).willReturn(Collections.singleton("test"));
|
setLogLevelToDebug("test");
|
||||||
given(this.loggingGroups.getLoggerGroup("test")).willReturn(Arrays.asList("test.member1", "test.member2"));
|
|
||||||
given(this.loggingGroups.getLoggerGroupConfiguredLevel("test")).willReturn(LogLevel.DEBUG);
|
|
||||||
given(this.loggingSystem.getLoggerConfigurations())
|
given(this.loggingSystem.getLoggerConfigurations())
|
||||||
.willReturn(Collections.singletonList(new LoggerConfiguration("ROOT", null, LogLevel.DEBUG)));
|
.willReturn(Collections.singletonList(new LoggerConfiguration("ROOT", null, LogLevel.DEBUG)));
|
||||||
this.client.get().uri("/actuator/loggers").exchange().expectStatus().isOk().expectBody().jsonPath("$.length()")
|
this.client.get().uri("/actuator/loggers").exchange().expectStatus().isOk().expectBody().jsonPath("$.length()")
|
||||||
|
@ -103,15 +87,13 @@ class LoggersEndpointWebIntegrationTests {
|
||||||
.isEqualTo(jsonArrayOf("OFF", "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE"))
|
.isEqualTo(jsonArrayOf("OFF", "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE"))
|
||||||
.jsonPath("loggers.length()").isEqualTo(1).jsonPath("loggers.ROOT.length()").isEqualTo(2)
|
.jsonPath("loggers.length()").isEqualTo(1).jsonPath("loggers.ROOT.length()").isEqualTo(2)
|
||||||
.jsonPath("loggers.ROOT.configuredLevel").isEqualTo(null).jsonPath("loggers.ROOT.effectiveLevel")
|
.jsonPath("loggers.ROOT.configuredLevel").isEqualTo(null).jsonPath("loggers.ROOT.effectiveLevel")
|
||||||
.isEqualTo("DEBUG").jsonPath("groups.length()").isEqualTo(1).jsonPath("groups.test.length()")
|
.isEqualTo("DEBUG").jsonPath("groups.length()").isEqualTo(2).jsonPath("groups.test.configuredLevel")
|
||||||
.isEqualTo(2).jsonPath("groups.test.configuredLevel").isEqualTo("DEBUG")
|
.isEqualTo("DEBUG");
|
||||||
.jsonPath("groups.test.members.length()").isEqualTo(2).jsonPath("groups.test.members")
|
|
||||||
.value(IsIterableContainingInAnyOrder.containsInAnyOrder("test.member1", "test.member2"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@WebEndpointTest
|
@WebEndpointTest
|
||||||
void getLoggerShouldReturnLogLevels() {
|
void getLoggerShouldReturnLogLevels() {
|
||||||
given(this.loggingGroups.isGroup("ROOT")).willReturn(false);
|
setLogLevelToDebug("test");
|
||||||
given(this.loggingSystem.getLoggerConfiguration("ROOT"))
|
given(this.loggingSystem.getLoggerConfiguration("ROOT"))
|
||||||
.willReturn(new LoggerConfiguration("ROOT", null, LogLevel.DEBUG));
|
.willReturn(new LoggerConfiguration("ROOT", null, LogLevel.DEBUG));
|
||||||
this.client.get().uri("/actuator/loggers/ROOT").exchange().expectStatus().isOk().expectBody()
|
this.client.get().uri("/actuator/loggers/ROOT").exchange().expectStatus().isOk().expectBody()
|
||||||
|
@ -126,9 +108,7 @@ class LoggersEndpointWebIntegrationTests {
|
||||||
|
|
||||||
@WebEndpointTest
|
@WebEndpointTest
|
||||||
void getLoggerGroupShouldReturnConfiguredLogLevelAndMembers() {
|
void getLoggerGroupShouldReturnConfiguredLogLevelAndMembers() {
|
||||||
given(this.loggingGroups.isGroup("test")).willReturn(true);
|
setLogLevelToDebug("test");
|
||||||
given(this.loggingGroups.getLoggerGroupConfiguredLevel("test")).willReturn(LogLevel.DEBUG);
|
|
||||||
given(this.loggingGroups.getLoggerGroup("test")).willReturn(Arrays.asList("test.member1", "test.member2"));
|
|
||||||
this.client.get().uri("actuator/loggers/test").exchange().expectStatus().isOk().expectBody()
|
this.client.get().uri("actuator/loggers/test").exchange().expectStatus().isOk().expectBody()
|
||||||
.jsonPath("$.length()").isEqualTo(2).jsonPath("members")
|
.jsonPath("$.length()").isEqualTo(2).jsonPath("members")
|
||||||
.value(IsIterableContainingInAnyOrder.containsInAnyOrder("test.member1", "test.member2"))
|
.value(IsIterableContainingInAnyOrder.containsInAnyOrder("test.member1", "test.member2"))
|
||||||
|
@ -137,7 +117,6 @@ class LoggersEndpointWebIntegrationTests {
|
||||||
|
|
||||||
@WebEndpointTest
|
@WebEndpointTest
|
||||||
void setLoggerUsingApplicationJsonShouldSetLogLevel() {
|
void setLoggerUsingApplicationJsonShouldSetLogLevel() {
|
||||||
given(this.loggingGroups.isGroup("ROOT")).willReturn(false);
|
|
||||||
this.client.post().uri("/actuator/loggers/ROOT").contentType(MediaType.APPLICATION_JSON)
|
this.client.post().uri("/actuator/loggers/ROOT").contentType(MediaType.APPLICATION_JSON)
|
||||||
.body(Collections.singletonMap("configuredLevel", "debug")).exchange().expectStatus().isNoContent();
|
.body(Collections.singletonMap("configuredLevel", "debug")).exchange().expectStatus().isNoContent();
|
||||||
verify(this.loggingSystem).setLogLevel("ROOT", LogLevel.DEBUG);
|
verify(this.loggingSystem).setLogLevel("ROOT", LogLevel.DEBUG);
|
||||||
|
@ -145,7 +124,6 @@ class LoggersEndpointWebIntegrationTests {
|
||||||
|
|
||||||
@WebEndpointTest
|
@WebEndpointTest
|
||||||
void setLoggerUsingActuatorV2JsonShouldSetLogLevel() {
|
void setLoggerUsingActuatorV2JsonShouldSetLogLevel() {
|
||||||
given(this.loggingGroups.isGroup("ROOT")).willReturn(false);
|
|
||||||
this.client.post().uri("/actuator/loggers/ROOT")
|
this.client.post().uri("/actuator/loggers/ROOT")
|
||||||
.contentType(MediaType.parseMediaType(ActuatorMediaType.V2_JSON))
|
.contentType(MediaType.parseMediaType(ActuatorMediaType.V2_JSON))
|
||||||
.body(Collections.singletonMap("configuredLevel", "debug")).exchange().expectStatus().isNoContent();
|
.body(Collections.singletonMap("configuredLevel", "debug")).exchange().expectStatus().isNoContent();
|
||||||
|
@ -154,21 +132,19 @@ class LoggersEndpointWebIntegrationTests {
|
||||||
|
|
||||||
@WebEndpointTest
|
@WebEndpointTest
|
||||||
void setLoggerGroupUsingActuatorV2JsonShouldSetLogLevel() {
|
void setLoggerGroupUsingActuatorV2JsonShouldSetLogLevel() {
|
||||||
given(this.loggingGroups.isGroup("test")).willReturn(true);
|
|
||||||
given(this.loggingGroups.getLoggerGroup("test")).willReturn(Arrays.asList("test.member1", "test.member2"));
|
|
||||||
this.client.post().uri("/actuator/loggers/test")
|
this.client.post().uri("/actuator/loggers/test")
|
||||||
.contentType(MediaType.parseMediaType(ActuatorMediaType.V2_JSON))
|
.contentType(MediaType.parseMediaType(ActuatorMediaType.V2_JSON))
|
||||||
.body(Collections.singletonMap("configuredLevel", "debug")).exchange().expectStatus().isNoContent();
|
.body(Collections.singletonMap("configuredLevel", "debug")).exchange().expectStatus().isNoContent();
|
||||||
verify(this.loggingGroups).setLoggerGroupLevel("test", LogLevel.DEBUG);
|
verify(this.loggingSystem).setLogLevel("test.member1", LogLevel.DEBUG);
|
||||||
|
verify(this.loggingSystem).setLogLevel("test.member2", LogLevel.DEBUG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@WebEndpointTest
|
@WebEndpointTest
|
||||||
void setLoggerGroupUsingApplicationJsonShouldSetLogLevel() {
|
void setLoggerGroupUsingApplicationJsonShouldSetLogLevel() {
|
||||||
given(this.loggingGroups.isGroup("test")).willReturn(true);
|
|
||||||
given(this.loggingGroups.getLoggerGroup("test")).willReturn(Arrays.asList("test.member1", "test.member2"));
|
|
||||||
this.client.post().uri("/actuator/loggers/test").contentType(MediaType.APPLICATION_JSON)
|
this.client.post().uri("/actuator/loggers/test").contentType(MediaType.APPLICATION_JSON)
|
||||||
.body(Collections.singletonMap("configuredLevel", "debug")).exchange().expectStatus().isNoContent();
|
.body(Collections.singletonMap("configuredLevel", "debug")).exchange().expectStatus().isNoContent();
|
||||||
verify(this.loggingGroups).setLoggerGroupLevel("test", LogLevel.DEBUG);
|
verify(this.loggingSystem).setLogLevel("test.member1", LogLevel.DEBUG);
|
||||||
|
verify(this.loggingSystem).setLogLevel("test.member2", LogLevel.DEBUG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@WebEndpointTest
|
@WebEndpointTest
|
||||||
|
@ -180,7 +156,6 @@ class LoggersEndpointWebIntegrationTests {
|
||||||
|
|
||||||
@WebEndpointTest
|
@WebEndpointTest
|
||||||
void setLoggerWithNullLogLevel() {
|
void setLoggerWithNullLogLevel() {
|
||||||
given(this.loggingGroups.isGroup("ROOT")).willReturn(false);
|
|
||||||
this.client.post().uri("/actuator/loggers/ROOT")
|
this.client.post().uri("/actuator/loggers/ROOT")
|
||||||
.contentType(MediaType.parseMediaType(ActuatorMediaType.V2_JSON))
|
.contentType(MediaType.parseMediaType(ActuatorMediaType.V2_JSON))
|
||||||
.body(Collections.singletonMap("configuredLevel", null)).exchange().expectStatus().isNoContent();
|
.body(Collections.singletonMap("configuredLevel", null)).exchange().expectStatus().isNoContent();
|
||||||
|
@ -189,7 +164,6 @@ class LoggersEndpointWebIntegrationTests {
|
||||||
|
|
||||||
@WebEndpointTest
|
@WebEndpointTest
|
||||||
void setLoggerWithNoLogLevel() {
|
void setLoggerWithNoLogLevel() {
|
||||||
given(this.loggingGroups.isGroup("ROOT")).willReturn(false);
|
|
||||||
this.client.post().uri("/actuator/loggers/ROOT")
|
this.client.post().uri("/actuator/loggers/ROOT")
|
||||||
.contentType(MediaType.parseMediaType(ActuatorMediaType.V2_JSON)).body(Collections.emptyMap())
|
.contentType(MediaType.parseMediaType(ActuatorMediaType.V2_JSON)).body(Collections.emptyMap())
|
||||||
.exchange().expectStatus().isNoContent();
|
.exchange().expectStatus().isNoContent();
|
||||||
|
@ -198,22 +172,20 @@ class LoggersEndpointWebIntegrationTests {
|
||||||
|
|
||||||
@WebEndpointTest
|
@WebEndpointTest
|
||||||
void setLoggerGroupWithNullLogLevel() {
|
void setLoggerGroupWithNullLogLevel() {
|
||||||
given(this.loggingGroups.isGroup("test")).willReturn(true);
|
|
||||||
given(this.loggingGroups.getLoggerGroup("test")).willReturn(Arrays.asList("test.member1", "test.member2"));
|
|
||||||
this.client.post().uri("/actuator/loggers/test")
|
this.client.post().uri("/actuator/loggers/test")
|
||||||
.contentType(MediaType.parseMediaType(ActuatorMediaType.V2_JSON))
|
.contentType(MediaType.parseMediaType(ActuatorMediaType.V2_JSON))
|
||||||
.body(Collections.singletonMap("configuredLevel", null)).exchange().expectStatus().isNoContent();
|
.body(Collections.singletonMap("configuredLevel", null)).exchange().expectStatus().isNoContent();
|
||||||
verify(this.loggingGroups).setLoggerGroupLevel("test", null);
|
verify(this.loggingSystem).setLogLevel("test.member1", null);
|
||||||
|
verify(this.loggingSystem).setLogLevel("test.member2", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@WebEndpointTest
|
@WebEndpointTest
|
||||||
void setLoggerGroupWithNoLogLevel() {
|
void setLoggerGroupWithNoLogLevel() {
|
||||||
given(this.loggingGroups.isGroup("test")).willReturn(true);
|
|
||||||
given(this.loggingGroups.getLoggerGroup("test")).willReturn(Arrays.asList("test.member1", "test.member2"));
|
|
||||||
this.client.post().uri("/actuator/loggers/test")
|
this.client.post().uri("/actuator/loggers/test")
|
||||||
.contentType(MediaType.parseMediaType(ActuatorMediaType.V2_JSON)).body(Collections.emptyMap())
|
.contentType(MediaType.parseMediaType(ActuatorMediaType.V2_JSON)).body(Collections.emptyMap())
|
||||||
.exchange().expectStatus().isNoContent();
|
.exchange().expectStatus().isNoContent();
|
||||||
verify(this.loggingGroups).setLoggerGroupLevel("test", null);
|
verify(this.loggingSystem).setLogLevel("test.member1", null);
|
||||||
|
verify(this.loggingSystem).setLogLevel("test.member2", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@WebEndpointTest
|
@WebEndpointTest
|
||||||
|
@ -227,12 +199,15 @@ class LoggersEndpointWebIntegrationTests {
|
||||||
|
|
||||||
@WebEndpointTest
|
@WebEndpointTest
|
||||||
void logLevelForLoggerGroupWithNameThatCouldBeMistakenForAPathExtension() {
|
void logLevelForLoggerGroupWithNameThatCouldBeMistakenForAPathExtension() {
|
||||||
given(this.loggingGroups.isGroup("com.png")).willReturn(true);
|
setLogLevelToDebug("group.png");
|
||||||
given(this.loggingGroups.getLoggerGroupConfiguredLevel("com.png")).willReturn(LogLevel.DEBUG);
|
this.client.get().uri("/actuator/loggers/group.png").exchange().expectStatus().isOk().expectBody()
|
||||||
given(this.loggingGroups.getLoggerGroup("com.png")).willReturn(Arrays.asList("test.member1", "test.member2"));
|
|
||||||
this.client.get().uri("/actuator/loggers/com.png").exchange().expectStatus().isOk().expectBody()
|
|
||||||
.jsonPath("$.length()").isEqualTo(2).jsonPath("configuredLevel").isEqualTo("DEBUG").jsonPath("members")
|
.jsonPath("$.length()").isEqualTo(2).jsonPath("configuredLevel").isEqualTo("DEBUG").jsonPath("members")
|
||||||
.value(IsIterableContainingInAnyOrder.containsInAnyOrder("test.member1", "test.member2"));
|
.value(IsIterableContainingInAnyOrder.containsInAnyOrder("png.member1", "png.member2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setLogLevelToDebug(String name) {
|
||||||
|
this.loggerGroups.get(name).configureLogLevel(LogLevel.DEBUG, (a, b) -> {
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private JSONArray jsonArrayOf(Object... entries) {
|
private JSONArray jsonArrayOf(Object... entries) {
|
||||||
|
@ -250,18 +225,20 @@ class LoggersEndpointWebIntegrationTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
ObjectProvider<LoggingGroups> loggingGroupsObjectProvider() {
|
LoggerGroups loggingGroups() {
|
||||||
return mock(ObjectProvider.class);
|
return getLoggerGroups();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
private LoggerGroups getLoggerGroups() {
|
||||||
LoggingGroups loggingGroups() {
|
Map<String, List<String>> groups = new LinkedHashMap<>();
|
||||||
return mock(LoggingGroups.class);
|
groups.put("test", Arrays.asList("test.member1", "test.member2"));
|
||||||
|
groups.put("group.png", Arrays.asList("png.member1", "png.member2"));
|
||||||
|
return new LoggerGroups(groups);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
LoggersEndpoint endpoint(LoggingSystem loggingSystem,
|
LoggersEndpoint endpoint(LoggingSystem loggingSystem,
|
||||||
ObjectProvider<LoggingGroups> loggingGroupsObjectProvider) {
|
ObjectProvider<LoggerGroups> loggingGroupsObjectProvider) {
|
||||||
return new LoggersEndpoint(loggingSystem, loggingGroupsObjectProvider.getIfAvailable());
|
return new LoggersEndpoint(loggingSystem, loggingGroupsObjectProvider.getIfAvailable());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,12 +16,11 @@
|
||||||
|
|
||||||
package org.springframework.boot.context.logging;
|
package org.springframework.boot.context.logging;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
@ -37,7 +36,8 @@ import org.springframework.boot.context.properties.bind.Binder;
|
||||||
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
|
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
|
||||||
import org.springframework.boot.logging.LogFile;
|
import org.springframework.boot.logging.LogFile;
|
||||||
import org.springframework.boot.logging.LogLevel;
|
import org.springframework.boot.logging.LogLevel;
|
||||||
import org.springframework.boot.logging.LoggingGroups;
|
import org.springframework.boot.logging.LoggerGroup;
|
||||||
|
import org.springframework.boot.logging.LoggerGroups;
|
||||||
import org.springframework.boot.logging.LoggingInitializationContext;
|
import org.springframework.boot.logging.LoggingInitializationContext;
|
||||||
import org.springframework.boot.logging.LoggingSystem;
|
import org.springframework.boot.logging.LoggingSystem;
|
||||||
import org.springframework.boot.logging.LoggingSystemProperties;
|
import org.springframework.boot.logging.LoggingSystemProperties;
|
||||||
|
@ -52,7 +52,6 @@ import org.springframework.core.env.ConfigurableEnvironment;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.util.LinkedMultiValueMap;
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
import org.springframework.util.MultiValueMap;
|
import org.springframework.util.MultiValueMap;
|
||||||
import org.springframework.util.ObjectUtils;
|
|
||||||
import org.springframework.util.ResourceUtils;
|
import org.springframework.util.ResourceUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
@ -85,6 +84,7 @@ import org.springframework.util.StringUtils;
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
* @author Madhura Bhave
|
* @author Madhura Bhave
|
||||||
|
* @author HaiTao Zhang
|
||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
* @see LoggingSystem#get(ClassLoader)
|
* @see LoggingSystem#get(ClassLoader)
|
||||||
*/
|
*/
|
||||||
|
@ -97,8 +97,8 @@ public class LoggingApplicationListener implements GenericApplicationListener {
|
||||||
private static final Bindable<Map<String, LogLevel>> STRING_LOGLEVEL_MAP = Bindable.mapOf(String.class,
|
private static final Bindable<Map<String, LogLevel>> STRING_LOGLEVEL_MAP = Bindable.mapOf(String.class,
|
||||||
LogLevel.class);
|
LogLevel.class);
|
||||||
|
|
||||||
private static final Bindable<Map<String, String[]>> STRING_STRINGS_MAP = Bindable.mapOf(String.class,
|
private static final Bindable<Map<String, List<String>>> STRING_STRINGS_MAP = Bindable
|
||||||
String[].class);
|
.of(ResolvableType.forClassWithGenerics(MultiValueMap.class, String.class, String.class).asMap());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default order for the LoggingApplicationListener.
|
* The default order for the LoggingApplicationListener.
|
||||||
|
@ -129,9 +129,10 @@ public class LoggingApplicationListener implements GenericApplicationListener {
|
||||||
public static final String LOGFILE_BEAN_NAME = "springBootLogFile";
|
public static final String LOGFILE_BEAN_NAME = "springBootLogFile";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the{@link LoggingGroups} bean.
|
* The name of the{@link LoggerGroups} bean.
|
||||||
|
* @since 2.2.0
|
||||||
*/
|
*/
|
||||||
public static final String LOGGING_GROUPS_BEAN_NAME = "springBootLoggingGroups";
|
public static final String LOGGER_GROUPS_BEAN_NAME = "springBootLoggerGroups";
|
||||||
|
|
||||||
private static final Map<String, List<String>> DEFAULT_GROUP_LOGGERS;
|
private static final Map<String, List<String>> DEFAULT_GROUP_LOGGERS;
|
||||||
static {
|
static {
|
||||||
|
@ -147,7 +148,7 @@ public class LoggingApplicationListener implements GenericApplicationListener {
|
||||||
DEFAULT_GROUP_LOGGERS = Collections.unmodifiableMap(loggers);
|
DEFAULT_GROUP_LOGGERS = Collections.unmodifiableMap(loggers);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Map<LogLevel, List<String>> LOG_LEVEL_LOGGERS;
|
private static final Map<LogLevel, List<String>> SPRING_BOOT_LOGGING_LOGGERS;
|
||||||
static {
|
static {
|
||||||
MultiValueMap<LogLevel, String> loggers = new LinkedMultiValueMap<>();
|
MultiValueMap<LogLevel, String> loggers = new LinkedMultiValueMap<>();
|
||||||
loggers.add(LogLevel.DEBUG, "sql");
|
loggers.add(LogLevel.DEBUG, "sql");
|
||||||
|
@ -158,7 +159,7 @@ public class LoggingApplicationListener implements GenericApplicationListener {
|
||||||
loggers.add(LogLevel.TRACE, "org.apache.catalina");
|
loggers.add(LogLevel.TRACE, "org.apache.catalina");
|
||||||
loggers.add(LogLevel.TRACE, "org.eclipse.jetty");
|
loggers.add(LogLevel.TRACE, "org.eclipse.jetty");
|
||||||
loggers.add(LogLevel.TRACE, "org.hibernate.tool.hbm2ddl");
|
loggers.add(LogLevel.TRACE, "org.hibernate.tool.hbm2ddl");
|
||||||
LOG_LEVEL_LOGGERS = Collections.unmodifiableMap(loggers);
|
SPRING_BOOT_LOGGING_LOGGERS = Collections.unmodifiableMap(loggers);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Class<?>[] EVENT_TYPES = { ApplicationStartingEvent.class,
|
private static final Class<?>[] EVENT_TYPES = { ApplicationStartingEvent.class,
|
||||||
|
@ -173,10 +174,10 @@ public class LoggingApplicationListener implements GenericApplicationListener {
|
||||||
|
|
||||||
private LoggingSystem loggingSystem;
|
private LoggingSystem loggingSystem;
|
||||||
|
|
||||||
private LoggingGroups loggingGroups;
|
|
||||||
|
|
||||||
private LogFile logFile;
|
private LogFile logFile;
|
||||||
|
|
||||||
|
private LoggerGroups loggerGroups;
|
||||||
|
|
||||||
private int order = DEFAULT_ORDER;
|
private int order = DEFAULT_ORDER;
|
||||||
|
|
||||||
private boolean parseArgs = true;
|
private boolean parseArgs = true;
|
||||||
|
@ -244,8 +245,8 @@ public class LoggingApplicationListener implements GenericApplicationListener {
|
||||||
if (this.logFile != null && !beanFactory.containsBean(LOGFILE_BEAN_NAME)) {
|
if (this.logFile != null && !beanFactory.containsBean(LOGFILE_BEAN_NAME)) {
|
||||||
beanFactory.registerSingleton(LOGFILE_BEAN_NAME, this.logFile);
|
beanFactory.registerSingleton(LOGFILE_BEAN_NAME, this.logFile);
|
||||||
}
|
}
|
||||||
if (this.loggingGroups != null && !beanFactory.containsBean(LOGGING_GROUPS_BEAN_NAME)) {
|
if (this.loggerGroups != null && !beanFactory.containsBean(LOGGER_GROUPS_BEAN_NAME)) {
|
||||||
beanFactory.registerSingleton(LOGGING_GROUPS_BEAN_NAME, this.loggingGroups);
|
beanFactory.registerSingleton(LOGGER_GROUPS_BEAN_NAME, this.loggerGroups);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,11 +270,11 @@ public class LoggingApplicationListener implements GenericApplicationListener {
|
||||||
*/
|
*/
|
||||||
protected void initialize(ConfigurableEnvironment environment, ClassLoader classLoader) {
|
protected void initialize(ConfigurableEnvironment environment, ClassLoader classLoader) {
|
||||||
new LoggingSystemProperties(environment).apply();
|
new LoggingSystemProperties(environment).apply();
|
||||||
this.loggingGroups = new LoggingGroups(this.loggingSystem);
|
|
||||||
this.logFile = LogFile.get(environment);
|
this.logFile = LogFile.get(environment);
|
||||||
if (this.logFile != null) {
|
if (this.logFile != null) {
|
||||||
this.logFile.applyToSystemProperties();
|
this.logFile.applyToSystemProperties();
|
||||||
}
|
}
|
||||||
|
this.loggerGroups = new LoggerGroups(DEFAULT_GROUP_LOGGERS);
|
||||||
initializeEarlyLoggingLevel(environment);
|
initializeEarlyLoggingLevel(environment);
|
||||||
initializeSystem(environment, this.loggingSystem, this.logFile);
|
initializeSystem(environment, this.loggingSystem, this.logFile);
|
||||||
initializeFinalLoggingLevels(environment, this.loggingSystem);
|
initializeFinalLoggingLevels(environment, this.loggingSystem);
|
||||||
|
@ -321,70 +322,95 @@ public class LoggingApplicationListener implements GenericApplicationListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeFinalLoggingLevels(ConfigurableEnvironment environment, LoggingSystem system) {
|
private void initializeFinalLoggingLevels(ConfigurableEnvironment environment, LoggingSystem system) {
|
||||||
|
bindLoggerGroups(environment);
|
||||||
if (this.springBootLogging != null) {
|
if (this.springBootLogging != null) {
|
||||||
initializeLogLevel(system, this.springBootLogging);
|
initializeLogLevel(system, this.springBootLogging);
|
||||||
}
|
}
|
||||||
setLogLevels(system, environment);
|
setLogLevels(system, environment);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void initializeLogLevel(LoggingSystem system, LogLevel level) {
|
private void bindLoggerGroups(ConfigurableEnvironment environment) {
|
||||||
LOG_LEVEL_LOGGERS.getOrDefault(level, Collections.emptyList())
|
if (this.loggerGroups != null) {
|
||||||
.forEach((logger) -> initializeLogLevel(system, level, logger));
|
Binder binder = Binder.get(environment);
|
||||||
}
|
binder.bind(LOGGING_GROUP, STRING_STRINGS_MAP).ifBound(this.loggerGroups::putAll);
|
||||||
|
|
||||||
private void initializeLogLevel(LoggingSystem system, LogLevel level, String logger) {
|
|
||||||
List<String> groupLoggers = DEFAULT_GROUP_LOGGERS.get(logger);
|
|
||||||
if (groupLoggers == null) {
|
|
||||||
system.setLogLevel(logger, level);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
this.loggingGroups.setLoggerGroup(logger, groupLoggers);
|
|
||||||
this.loggingGroups.setLoggerGroupLevel(logger, level);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize loggers based on the {@link #setSpringBootLogging(LogLevel)
|
||||||
|
* springBootLogging} setting.
|
||||||
|
* @param system the logging system
|
||||||
|
* @param springBootLogging the spring boot logging level requested
|
||||||
|
* @deprecated since 2.2.0 in favor of
|
||||||
|
* {@link #initializeSpringBootLogging(LoggingSystem, LogLevel)}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
protected void initializeLogLevel(LoggingSystem system, LogLevel springBootLogging) {
|
||||||
|
initializeSpringBootLogging(system, springBootLogging);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize loggers based on the {@link #setSpringBootLogging(LogLevel)
|
||||||
|
* springBootLogging} setting. By default this implementation will pick an appropriate
|
||||||
|
* set of loggers to configure based on the level.
|
||||||
|
* @param system the logging system
|
||||||
|
* @param springBootLogging the spring boot logging level requested
|
||||||
|
* @since 2.2.0
|
||||||
|
*/
|
||||||
|
protected void initializeSpringBootLogging(LoggingSystem system, LogLevel springBootLogging) {
|
||||||
|
BiConsumer<String, LogLevel> configurer = getLogLevelConfigurer(system);
|
||||||
|
SPRING_BOOT_LOGGING_LOGGERS.getOrDefault(springBootLogging, Collections.emptyList())
|
||||||
|
.forEach((name) -> configureLogLevel(name, springBootLogging, configurer));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set logging levels based on relevant {@link Environment} properties.
|
||||||
|
* @param system the logging system
|
||||||
|
* @param environment the environment
|
||||||
|
* @deprecated since 2.2.0 in favor of
|
||||||
|
* {@link #setLogLevels(LoggingSystem, ConfigurableEnvironment)}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
protected void setLogLevels(LoggingSystem system, Environment environment) {
|
protected void setLogLevels(LoggingSystem system, Environment environment) {
|
||||||
if (!(environment instanceof ConfigurableEnvironment)) {
|
if (environment instanceof ConfigurableEnvironment) {
|
||||||
return;
|
setLogLevels(system, (ConfigurableEnvironment) environment);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set logging levels based on relevant {@link Environment} properties.
|
||||||
|
* @param system the logging system
|
||||||
|
* @param environment the environment
|
||||||
|
* @since 2.2.0
|
||||||
|
*/
|
||||||
|
protected void setLogLevels(LoggingSystem system, ConfigurableEnvironment environment) {
|
||||||
|
BiConsumer<String, LogLevel> customizer = getLogLevelConfigurer(system);
|
||||||
Binder binder = Binder.get(environment);
|
Binder binder = Binder.get(environment);
|
||||||
Map<String, String[]> groups = getGroups();
|
|
||||||
binder.bind(LOGGING_GROUP, STRING_STRINGS_MAP.withExistingValue(groups));
|
|
||||||
Map<String, LogLevel> levels = binder.bind(LOGGING_LEVEL, STRING_LOGLEVEL_MAP).orElseGet(Collections::emptyMap);
|
Map<String, LogLevel> levels = binder.bind(LOGGING_LEVEL, STRING_LOGLEVEL_MAP).orElseGet(Collections::emptyMap);
|
||||||
levels.forEach((name, level) -> {
|
levels.forEach((name, level) -> configureLogLevel(name, level, customizer));
|
||||||
String[] groupedNames = groups.get(name);
|
}
|
||||||
if (ObjectUtils.isEmpty(groupedNames)) {
|
|
||||||
setLogLevel(system, name, level);
|
private void configureLogLevel(String name, LogLevel level, BiConsumer<String, LogLevel> configurer) {
|
||||||
|
if (this.loggerGroups != null) {
|
||||||
|
LoggerGroup group = this.loggerGroups.get(name);
|
||||||
|
if (group != null && group.hasMembers()) {
|
||||||
|
group.configureLogLevel(level, configurer);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
setLogLevel(groupedNames, level, name);
|
configurer.accept(name, level);
|
||||||
|
}
|
||||||
|
|
||||||
|
private BiConsumer<String, LogLevel> getLogLevelConfigurer(LoggingSystem system) {
|
||||||
|
return (name, level) -> {
|
||||||
|
try {
|
||||||
|
name = name.equalsIgnoreCase(LoggingSystem.ROOT_LOGGER_NAME) ? null : name;
|
||||||
|
system.setLogLevel(name, level);
|
||||||
}
|
}
|
||||||
});
|
catch (RuntimeException ex) {
|
||||||
}
|
this.logger.error("Cannot set level '" + level + "' for '" + name + "'");
|
||||||
|
}
|
||||||
private Map<String, String[]> getGroups() {
|
};
|
||||||
Map<String, String[]> groups = new LinkedHashMap<>();
|
|
||||||
DEFAULT_GROUP_LOGGERS.forEach((name, loggers) -> groups.put(name, StringUtils.toStringArray(loggers)));
|
|
||||||
return groups;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setLogLevel(String[] names, LogLevel level, String groupName) {
|
|
||||||
try {
|
|
||||||
this.loggingGroups.setLoggerGroup(groupName, Arrays.asList(names));
|
|
||||||
this.loggingGroups.setLoggerGroupLevel(groupName, level);
|
|
||||||
}
|
|
||||||
catch (RuntimeException ex) {
|
|
||||||
this.logger.error("Cannot set level '" + level + "' for '" + groupName + "'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setLogLevel(LoggingSystem system, String name, LogLevel level) {
|
|
||||||
try {
|
|
||||||
name = name.equalsIgnoreCase(LoggingSystem.ROOT_LOGGER_NAME) ? null : name;
|
|
||||||
system.setLogLevel(name, level);
|
|
||||||
}
|
|
||||||
catch (RuntimeException ex) {
|
|
||||||
this.logger.error("Cannot set level '" + level + "' for '" + name + "'");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerShutdownHookIfNecessary(Environment environment, LoggingSystem loggingSystem) {
|
private void registerShutdownHookIfNecessary(Environment environment, LoggingSystem loggingSystem) {
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2019 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.logging;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A single logger group.
|
||||||
|
*
|
||||||
|
* @author Madhura Bhave
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @since 2.2.0
|
||||||
|
*/
|
||||||
|
public final class LoggerGroup {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
private final List<String> members;
|
||||||
|
|
||||||
|
private LogLevel configuredLevel;
|
||||||
|
|
||||||
|
LoggerGroup(String name, List<String> members) {
|
||||||
|
this.name = name;
|
||||||
|
this.members = Collections.unmodifiableList(new ArrayList<>(members));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getMembers() {
|
||||||
|
return this.members;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasMembers() {
|
||||||
|
return !this.members.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public LogLevel getConfiguredLevel() {
|
||||||
|
return this.configuredLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void configureLogLevel(LogLevel level, BiConsumer<String, LogLevel> configurer) {
|
||||||
|
this.configuredLevel = level;
|
||||||
|
this.members.forEach((name) -> configurer.accept(name, level));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2019 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.logging;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logger groups configured via the Spring Environment.
|
||||||
|
*
|
||||||
|
* @author HaiTao Zhang
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @since 2.2.0 #see {@link LoggerGroup}
|
||||||
|
*/
|
||||||
|
public final class LoggerGroups implements Iterable<LoggerGroup> {
|
||||||
|
|
||||||
|
private final Map<String, LoggerGroup> groups = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public LoggerGroups() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoggerGroups(Map<String, List<String>> namesAndMembers) {
|
||||||
|
putAll(namesAndMembers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void putAll(Map<String, List<String>> namesAndMembers) {
|
||||||
|
namesAndMembers.forEach(this::put);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void put(String name, List<String> members) {
|
||||||
|
put(new LoggerGroup(name, members));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void put(LoggerGroup loggerGroup) {
|
||||||
|
this.groups.put(loggerGroup.getName(), loggerGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoggerGroup get(String name) {
|
||||||
|
return this.groups.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<LoggerGroup> iterator() {
|
||||||
|
return this.groups.values().iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,112 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2012-2019 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.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.boot.logging;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manage logger groups.
|
|
||||||
*
|
|
||||||
* @author HaiTao Zhang
|
|
||||||
* @since 2.2.0
|
|
||||||
*/
|
|
||||||
public class LoggingGroups {
|
|
||||||
|
|
||||||
private Map<String, LogLevel> loggerGroupConfigurations;
|
|
||||||
|
|
||||||
private Map<String, List<String>> loggerGroups;
|
|
||||||
|
|
||||||
private LoggingSystem loggingSystem;
|
|
||||||
|
|
||||||
public LoggingGroups(LoggingSystem loggingSystem) {
|
|
||||||
this.loggerGroupConfigurations = new ConcurrentHashMap<>();
|
|
||||||
this.loggerGroups = new ConcurrentHashMap<>();
|
|
||||||
this.loggingSystem = loggingSystem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Associate a name to a list of logger's name to create a logger group.
|
|
||||||
* @param groupName name of the logger group
|
|
||||||
* @param members list of the members names
|
|
||||||
*/
|
|
||||||
public void setLoggerGroup(String groupName, List<String> members) {
|
|
||||||
Assert.notNull(groupName, "Group name can not be null");
|
|
||||||
Assert.notNull(members, "Members can not be null");
|
|
||||||
this.loggerGroups.put(groupName, members);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the logging level for a given logger group.
|
|
||||||
* @param groupName the name of the group to set
|
|
||||||
* @param level the log level ({@code null}) can be used to remove any custom level
|
|
||||||
* for the logger group and use the default configuration instead.
|
|
||||||
*/
|
|
||||||
public void setLoggerGroupLevel(String groupName, LogLevel level) {
|
|
||||||
Assert.notNull(groupName, "Group name can not be null");
|
|
||||||
List<String> members = this.loggerGroups.get(groupName);
|
|
||||||
members.forEach((member) -> this.loggingSystem
|
|
||||||
.setLogLevel(member.equalsIgnoreCase(LoggingSystem.ROOT_LOGGER_NAME) ? null : member, level));
|
|
||||||
this.loggerGroupConfigurations.put(groupName, level);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether a groupName is associated to a logger group.
|
|
||||||
* @param groupName name of the logger group
|
|
||||||
* @return a boolean stating true when groupName is associated with a group of loggers
|
|
||||||
*/
|
|
||||||
public boolean isGroup(String groupName) {
|
|
||||||
Assert.notNull(groupName, "Group name can not be null");
|
|
||||||
return this.loggerGroups.containsKey(groupName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the all registered logger groups.
|
|
||||||
* @return a Set of the names of the logger groups
|
|
||||||
*/
|
|
||||||
public Set<String> getLoggerGroupNames() {
|
|
||||||
synchronized (this) {
|
|
||||||
return this.loggerGroups.isEmpty() ? null : Collections.unmodifiableSet(this.loggerGroups.keySet());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a logger group's members.
|
|
||||||
* @param groupName name of the logger group
|
|
||||||
* @return list of the members names associated with this group
|
|
||||||
*/
|
|
||||||
public List<String> getLoggerGroup(String groupName) {
|
|
||||||
Assert.notNull(groupName, "Group name can not be null");
|
|
||||||
return Collections.unmodifiableList(this.loggerGroups.get(groupName));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a logger group's configured level.
|
|
||||||
* @param groupName name of the logger group
|
|
||||||
* @return the logger groups configured level
|
|
||||||
*/
|
|
||||||
public LogLevel getLoggerGroupConfiguredLevel(String groupName) {
|
|
||||||
Assert.notNull(groupName, "Group name can not be null");
|
|
||||||
return this.loggerGroupConfigurations.get(groupName);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -50,6 +50,7 @@ import org.springframework.boot.logging.AbstractLoggingSystem;
|
||||||
import org.springframework.boot.logging.LogFile;
|
import org.springframework.boot.logging.LogFile;
|
||||||
import org.springframework.boot.logging.LogLevel;
|
import org.springframework.boot.logging.LogLevel;
|
||||||
import org.springframework.boot.logging.LoggerConfiguration;
|
import org.springframework.boot.logging.LoggerConfiguration;
|
||||||
|
import org.springframework.boot.logging.LoggerGroups;
|
||||||
import org.springframework.boot.logging.LoggingInitializationContext;
|
import org.springframework.boot.logging.LoggingInitializationContext;
|
||||||
import org.springframework.boot.logging.LoggingSystem;
|
import org.springframework.boot.logging.LoggingSystem;
|
||||||
import org.springframework.boot.logging.LoggingSystemProperties;
|
import org.springframework.boot.logging.LoggingSystemProperties;
|
||||||
|
@ -284,6 +285,8 @@ class LoggingApplicationListenerTests {
|
||||||
this.loggerContext.getLogger("org.hibernate.SQL").debug("testdebugsqlgroup");
|
this.loggerContext.getLogger("org.hibernate.SQL").debug("testdebugsqlgroup");
|
||||||
assertThat(this.output).contains("testdebugwebgroup");
|
assertThat(this.output).contains("testdebugwebgroup");
|
||||||
assertThat(this.output).contains("testdebugsqlgroup");
|
assertThat(this.output).contains("testdebugsqlgroup");
|
||||||
|
LoggerGroups loggerGroups = (LoggerGroups) ReflectionTestUtils.getField(this.initializer, "loggerGroups");
|
||||||
|
assertThat(loggerGroups.get("web").getConfiguredLevel()).isEqualTo(LogLevel.DEBUG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2019 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.logging;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link LoggerGroups}
|
||||||
|
*
|
||||||
|
* @author HaiTao Zhang
|
||||||
|
* @author Madhura Bhave
|
||||||
|
*/
|
||||||
|
class LoggerGroupsTests {
|
||||||
|
|
||||||
|
private LoggingSystem loggingSystem = mock(LoggingSystem.class);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void putAllShouldAddLoggerGroups() {
|
||||||
|
Map<String, List<String>> groups = Collections.singletonMap("test",
|
||||||
|
Arrays.asList("test.member", "test.member2"));
|
||||||
|
LoggerGroups loggerGroups = new LoggerGroups();
|
||||||
|
loggerGroups.putAll(groups);
|
||||||
|
LoggerGroup group = loggerGroups.get("test");
|
||||||
|
assertThat(group.getMembers()).containsExactly("test.member", "test.member2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void iteratorShouldReturnLoggerGroups() {
|
||||||
|
LoggerGroups groups = createLoggerGroups();
|
||||||
|
assertThat(groups).hasSize(3);
|
||||||
|
assertThat(groups).extracting("name").containsExactlyInAnyOrder("test0", "test1", "test2");
|
||||||
|
}
|
||||||
|
|
||||||
|
private LoggerGroups createLoggerGroups() {
|
||||||
|
Map<String, List<String>> groups = new LinkedHashMap<>();
|
||||||
|
groups.put("test0", Arrays.asList("test0.member", "test0.member2"));
|
||||||
|
groups.put("test1", Arrays.asList("test1.member", "test1.member2"));
|
||||||
|
groups.put("test2", Arrays.asList("test2.member", "test2.member2"));
|
||||||
|
return new LoggerGroups(groups);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,44 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2012-2019 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.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.boot.logging;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
import static org.mockito.Mockito.verify;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for {@link LoggingGroups}
|
|
||||||
*
|
|
||||||
* @author HaiTao Zhang
|
|
||||||
*/
|
|
||||||
public class LoggingGroupsTests {
|
|
||||||
|
|
||||||
private LoggingSystem loggingSystem = mock(LoggingSystem.class);
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void setLoggerGroupWithTheConfiguredLevelToAllMembers() {
|
|
||||||
LoggingGroups loggingGroups = new LoggingGroups(this.loggingSystem);
|
|
||||||
loggingGroups.setLoggerGroup("test", Arrays.asList("test.member", "test.member2"));
|
|
||||||
loggingGroups.setLoggerGroupLevel("test", LogLevel.DEBUG);
|
|
||||||
verify(this.loggingSystem).setLogLevel("test.member2", LogLevel.DEBUG);
|
|
||||||
verify(this.loggingSystem).setLogLevel("test.member", LogLevel.DEBUG);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue