Merge branch '1.5.x'
This commit is contained in:
61
spring-boot-actuator-docs/src/main/asciidoc/loggers.adoc
Normal file
61
spring-boot-actuator-docs/src/main/asciidoc/loggers.adoc
Normal file
@@ -0,0 +1,61 @@
|
||||
=== /loggers
|
||||
This endpoint allows you to view and modify the log levels for the loggers in your
|
||||
application. It builds on top of the `LoggingSystem` abstraction and supports the same
|
||||
logging frameworks. The logging levels are defined by the `LogLevel` enumeration and
|
||||
consists of the following values (although not all logging systems support the full set):
|
||||
|
||||
* `TRACE`
|
||||
* `DEBUG`
|
||||
* `INFO`
|
||||
* `WARN`
|
||||
* `ERROR`
|
||||
* `FATAL`
|
||||
* `OFF`
|
||||
* `null`
|
||||
|
||||
The `configuredLevel` property reflects an explicitly configured logger level, while the
|
||||
`effectiveLevel` property reflects the logger level inherited from parent loggers. The
|
||||
`effectiveLevel` is managed by each logging framework and reflects the propagation rules
|
||||
inherent to and configured in that framework. `null` indicates that there is no explicit
|
||||
configuration defined.
|
||||
|
||||
|
||||
|
||||
==== Listing All Loggers
|
||||
Example curl request:
|
||||
include::{generated}/loggers/curl-request.adoc[]
|
||||
|
||||
Example HTTP request: [small]##link:../health[icon:external-link[role="silver"]]##
|
||||
include::{generated}/loggers/http-request.adoc[]
|
||||
|
||||
Example HTTP response:
|
||||
include::{generated}/loggers/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
==== Getting a Single Logger
|
||||
Example curl request:
|
||||
include::{generated}/single-logger/curl-request.adoc[]
|
||||
|
||||
Example HTTP request: [small]##link:../health[icon:external-link[role="silver"]]##
|
||||
include::{generated}/single-logger/http-request.adoc[]
|
||||
|
||||
Example HTTP response:
|
||||
include::{generated}/single-logger/http-response.adoc[]
|
||||
|
||||
|
||||
|
||||
==== Configuring a Logger
|
||||
Setting the `configuredLevel` of a logger requires `POSTing` a partial payload to the
|
||||
resource. The `configuredLevel` property must contain a string representation of the
|
||||
enumeration described above. `null` indicates that the log level should be unset,
|
||||
allowing it to inherit configuration from it's parent.
|
||||
|
||||
Example curl request:
|
||||
include::{generated}/set-logger/curl-request.adoc[]
|
||||
|
||||
Example HTTP request: [small]##link:../health[icon:external-link[role="silver"]]##
|
||||
include::{generated}/set-logger/http-request.adoc[]
|
||||
|
||||
Example HTTP response:
|
||||
include::{generated}/set-logger/http-response.adoc[]
|
||||
@@ -58,6 +58,7 @@ import org.springframework.util.StringUtils;
|
||||
|
||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@@ -108,6 +109,23 @@ public class EndpointDocumentation {
|
||||
.andDo(document("partial-logfile"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleLogger() throws Exception {
|
||||
this.mockMvc
|
||||
.perform(get("/loggers/org.springframework.boot")
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk()).andDo(document("single-logger"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setLogger() throws Exception {
|
||||
this.mockMvc
|
||||
.perform(post("/loggers/org.springframework.boot")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("{\"configuredLevel\": \"DEBUG\"}"))
|
||||
.andExpect(status().isOk()).andDo(document("set-logger"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void endpoints() throws Exception {
|
||||
final File docs = new File("src/main/asciidoc");
|
||||
|
||||
@@ -324,6 +324,11 @@
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.skyscreamer</groupId>
|
||||
<artifactId>jsonassert</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
|
||||
@@ -16,12 +16,14 @@
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoints;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.NamedMvcEndpoint;
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
|
||||
@@ -30,6 +32,7 @@ import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
|
||||
* Adds endpoint links to {@link ResourceSupport}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
class LinksEnhancer {
|
||||
|
||||
@@ -47,23 +50,34 @@ class LinksEnhancer {
|
||||
resource.add(linkTo(LinksEnhancer.class).slash(this.rootPath + self)
|
||||
.withSelfRel());
|
||||
}
|
||||
Set<String> added = new HashSet<String>();
|
||||
MultiValueMap<String, String> added = new LinkedMultiValueMap<String, String>();
|
||||
for (MvcEndpoint endpoint : this.endpoints.getEndpoints()) {
|
||||
if (!endpoint.getPath().equals(self) && !added.contains(endpoint.getPath())) {
|
||||
addEndpointLink(resource, endpoint);
|
||||
if (!endpoint.getPath().equals(self)) {
|
||||
String rel = getRel(endpoint);
|
||||
List<String> paths = added.get(rel);
|
||||
if (paths == null || !paths.contains(endpoint.getPath())) {
|
||||
addEndpointLink(resource, endpoint, rel);
|
||||
added.add(rel, endpoint.getPath());
|
||||
}
|
||||
}
|
||||
added.add(endpoint.getPath());
|
||||
}
|
||||
}
|
||||
|
||||
private void addEndpointLink(ResourceSupport resource, MvcEndpoint endpoint) {
|
||||
private String getRel(MvcEndpoint endpoint) {
|
||||
if (endpoint instanceof NamedMvcEndpoint) {
|
||||
return ((NamedMvcEndpoint) endpoint).getName();
|
||||
}
|
||||
String path = endpoint.getPath();
|
||||
return (path.startsWith("/") ? path.substring(1) : path);
|
||||
}
|
||||
|
||||
private void addEndpointLink(ResourceSupport resource, MvcEndpoint endpoint,
|
||||
String rel) {
|
||||
Class<?> type = endpoint.getEndpointType();
|
||||
type = (type == null ? Object.class : type);
|
||||
String path = endpoint.getPath();
|
||||
String rel = (path.startsWith("/") ? path.substring(1) : path);
|
||||
if (StringUtils.hasText(rel)) {
|
||||
String fullPath = this.rootPath + endpoint.getPath();
|
||||
resource.add(linkTo(type).slash(fullPath).withRel(rel));
|
||||
String href = this.rootPath + endpoint.getPath();
|
||||
resource.add(linkTo(type).slash(href).withRel(rel));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,9 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.logging.LogLevel;
|
||||
@@ -35,8 +38,7 @@ import org.springframework.util.Assert;
|
||||
* @since 1.5.0
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "endpoints.loggers")
|
||||
public class LoggersEndpoint
|
||||
extends AbstractEndpoint<Map<String, LoggersEndpoint.LoggerLevels>> {
|
||||
public class LoggersEndpoint extends AbstractEndpoint<Map<String, Object>> {
|
||||
|
||||
private final LoggingSystem loggingSystem;
|
||||
|
||||
@@ -51,18 +53,31 @@ public class LoggersEndpoint
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, LoggerLevels> invoke() {
|
||||
public Map<String, Object> invoke() {
|
||||
Collection<LoggerConfiguration> configurations = this.loggingSystem
|
||||
.getLoggerConfigurations();
|
||||
if (configurations == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Map<String, LoggerLevels> result = new LinkedHashMap<String, LoggerLevels>(
|
||||
Map<String, Object> result = new LinkedHashMap<String, Object>();
|
||||
result.put("levels", getLevels());
|
||||
result.put("loggers", getLoggers(configurations));
|
||||
return result;
|
||||
}
|
||||
|
||||
private NavigableSet<LogLevel> getLevels() {
|
||||
Set<LogLevel> levels = this.loggingSystem.getSupportedLogLevels();
|
||||
return new TreeSet<LogLevel>(levels).descendingSet();
|
||||
}
|
||||
|
||||
private Map<String, LoggerLevels> getLoggers(
|
||||
Collection<LoggerConfiguration> configurations) {
|
||||
Map<String, LoggerLevels> loggers = new LinkedHashMap<String, LoggerLevels>(
|
||||
configurations.size());
|
||||
for (LoggerConfiguration configuration : configurations) {
|
||||
result.put(configuration.getName(), new LoggerLevels(configuration));
|
||||
loggers.put(configuration.getName(), new LoggerLevels(configuration));
|
||||
}
|
||||
return result;
|
||||
return loggers;
|
||||
}
|
||||
|
||||
public LoggerLevels invoke(String name) {
|
||||
|
||||
@@ -130,7 +130,9 @@ public class EndpointAutoConfigurationTests {
|
||||
public void loggersEndpointHasLoggers() throws Exception {
|
||||
load(CustomLoggingConfig.class, EndpointAutoConfiguration.class);
|
||||
LoggersEndpoint endpoint = this.context.getBean(LoggersEndpoint.class);
|
||||
Map<String, LoggerLevels> loggers = endpoint.invoke();
|
||||
Map<String, Object> result = endpoint.invoke();
|
||||
Map<String, LoggerLevels> loggers = (Map<String, LoggerLevels>) result
|
||||
.get("loggers");
|
||||
assertThat(loggers.size()).isGreaterThan(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://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.actuate.autoconfigure;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.assertj.core.api.Condition;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.AbstractEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.AbstractMvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoints;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
import org.springframework.web.context.support.StaticWebApplicationContext;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link LinksEnhancer}.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
public class LinksEnhancerTests {
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void useNameAsRelIfAvailable() throws Exception {
|
||||
TestMvcEndpoint endpoint = new TestMvcEndpoint(new TestEndpoint("a"));
|
||||
endpoint.setPath("something-else");
|
||||
LinksEnhancer enhancer = getLinksEnhancer(
|
||||
Collections.singletonList((MvcEndpoint) endpoint));
|
||||
ResourceSupport support = new ResourceSupport();
|
||||
enhancer.addEndpointLinks(support, "");
|
||||
assertThat(support.getLink("a").getHref()).contains("/something-else");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void usePathAsRelIfNameNotAvailable() throws Exception {
|
||||
MvcEndpoint endpoint = new NoNameTestMvcEndpoint("/a", false);
|
||||
LinksEnhancer enhancer = getLinksEnhancer(Collections.singletonList(endpoint));
|
||||
ResourceSupport support = new ResourceSupport();
|
||||
enhancer.addEndpointLinks(support, "");
|
||||
assertThat(support.getLink("a").getHref()).contains("/a");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hrefNotAddedToRelTwice() throws Exception {
|
||||
MvcEndpoint endpoint = new TestMvcEndpoint(new TestEndpoint("a"));
|
||||
MvcEndpoint otherEndpoint = new TestMvcEndpoint(new TestEndpoint("a"));
|
||||
LinksEnhancer enhancer = getLinksEnhancer(Arrays.asList(endpoint, otherEndpoint));
|
||||
ResourceSupport support = new ResourceSupport();
|
||||
enhancer.addEndpointLinks(support, "");
|
||||
assertThat(support.getLinks()).haveExactly(1, getCondition("a", "a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleHrefsForSameRelWhenPathIsDifferent() throws Exception {
|
||||
TestMvcEndpoint endpoint = new TestMvcEndpoint(new TestEndpoint("a"));
|
||||
endpoint.setPath("endpoint");
|
||||
TestMvcEndpoint otherEndpoint = new TestMvcEndpoint(new TestEndpoint("a"));
|
||||
otherEndpoint.setPath("other-endpoint");
|
||||
LinksEnhancer enhancer = getLinksEnhancer(
|
||||
Arrays.asList((MvcEndpoint) endpoint, otherEndpoint));
|
||||
ResourceSupport support = new ResourceSupport();
|
||||
enhancer.addEndpointLinks(support, "");
|
||||
assertThat(support.getLinks()).haveExactly(1, getCondition("a", "endpoint"));
|
||||
assertThat(support.getLinks()).haveExactly(1,
|
||||
getCondition("a", "other-endpoint"));
|
||||
}
|
||||
|
||||
private LinksEnhancer getLinksEnhancer(List<MvcEndpoint> endpoints) throws Exception {
|
||||
StaticWebApplicationContext context = new StaticWebApplicationContext();
|
||||
for (MvcEndpoint endpoint : endpoints) {
|
||||
context.getDefaultListableBeanFactory().registerSingleton(endpoint.toString(),
|
||||
endpoint);
|
||||
}
|
||||
MvcEndpoints mvcEndpoints = new MvcEndpoints();
|
||||
mvcEndpoints.setApplicationContext(context);
|
||||
mvcEndpoints.afterPropertiesSet();
|
||||
return new LinksEnhancer("", mvcEndpoints);
|
||||
}
|
||||
|
||||
private Condition<Link> getCondition(final String rel, final String href) {
|
||||
return new Condition<Link>() {
|
||||
|
||||
@Override
|
||||
public boolean matches(Link link) {
|
||||
return link.getRel().equals(rel)
|
||||
&& link.getHref().equals("http://localhost/" + href);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
private static class TestEndpoint extends AbstractEndpoint<Object> {
|
||||
|
||||
TestEndpoint(String id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class TestMvcEndpoint extends EndpointMvcAdapter {
|
||||
|
||||
TestMvcEndpoint(TestEndpoint delegate) {
|
||||
super(delegate);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class NoNameTestMvcEndpoint extends AbstractMvcEndpoint {
|
||||
|
||||
NoNameTestMvcEndpoint(String path, boolean sensitive) {
|
||||
super(path, sensitive);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -48,17 +48,16 @@ public class ManagementServerPropertiesAutoConfigurationNoSecurityTests {
|
||||
|
||||
@Test
|
||||
public void securitySettingsIgnoredWithoutSpringSecurity() {
|
||||
ManagementServerProperties properties =
|
||||
load("management.security.enabled=false");
|
||||
ManagementServerProperties properties = load("management.security.enabled=false");
|
||||
assertThat(properties.getSecurity().isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
public ManagementServerProperties load(String... environment) {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
EnvironmentTestUtils.addEnvironment(ctx, environment);
|
||||
ctx.register(ManagementServerPropertiesAutoConfiguration.class);
|
||||
ctx.refresh();
|
||||
this.context = ctx;
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
EnvironmentTestUtils.addEnvironment(context, environment);
|
||||
context.register(ManagementServerPropertiesAutoConfiguration.class);
|
||||
context.refresh();
|
||||
this.context = context;
|
||||
return this.context.getBean(ManagementServerProperties.class);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
package org.springframework.boot.actuate.endpoint;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -45,12 +48,21 @@ public class LoggersEndpointTests extends AbstractEndpointTests<LoggersEndpoint>
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void invokeShouldReturnConfigurations() throws Exception {
|
||||
given(getLoggingSystem().getLoggerConfigurations()).willReturn(Collections
|
||||
.singletonList(new LoggerConfiguration("ROOT", null, LogLevel.DEBUG)));
|
||||
LoggerLevels levels = getEndpointBean().invoke().get("ROOT");
|
||||
assertThat(levels.getConfiguredLevel()).isNull();
|
||||
assertThat(levels.getEffectiveLevel()).isEqualTo("DEBUG");
|
||||
given(getLoggingSystem().getSupportedLogLevels())
|
||||
.willReturn(EnumSet.allOf(LogLevel.class));
|
||||
Map<String, Object> result = getEndpointBean().invoke();
|
||||
Map<String, LoggerLevels> loggers = (Map<String, LoggerLevels>) result
|
||||
.get("loggers");
|
||||
Set<LogLevel> levels = (Set<LogLevel>) result.get("levels");
|
||||
LoggerLevels rootLevels = loggers.get("ROOT");
|
||||
assertThat(rootLevels.getConfiguredLevel()).isNull();
|
||||
assertThat(rootLevels.getEffectiveLevel()).isEqualTo("DEBUG");
|
||||
assertThat(levels).containsExactly(LogLevel.OFF, LogLevel.FATAL, LogLevel.ERROR,
|
||||
LogLevel.WARN, LogLevel.INFO, LogLevel.DEBUG, LogLevel.TRACE);
|
||||
}
|
||||
|
||||
public void invokeWhenNameSpecifiedShouldReturnLevels() throws Exception {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.boot.actuate.endpoint.mvc;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
@@ -80,18 +81,23 @@ public class LoggersMvcEndpointTests {
|
||||
.alwaysDo(MockMvcResultHandlers.print()).build();
|
||||
}
|
||||
|
||||
@Before
|
||||
@After
|
||||
public void reset() {
|
||||
public void resetMocks() {
|
||||
Mockito.reset(this.loggingSystem);
|
||||
given(this.loggingSystem.getSupportedLogLevels())
|
||||
.willReturn(EnumSet.allOf(LogLevel.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getLoggerShouldReturnAllLoggerConfigurations() throws Exception {
|
||||
given(this.loggingSystem.getLoggerConfigurations()).willReturn(Collections
|
||||
.singletonList(new LoggerConfiguration("ROOT", null, LogLevel.DEBUG)));
|
||||
String expected = "{\"levels\":[\"OFF\",\"FATAL\",\"ERROR\",\"WARN\",\"INFO\",\"DEBUG\",\"TRACE\"],"
|
||||
+ "\"loggers\":{\"ROOT\":{\"configuredLevel\":null,\"effectiveLevel\":\"DEBUG\"}}}";
|
||||
System.out.println(expected);
|
||||
this.mvc.perform(get("/loggers")).andExpect(status().isOk())
|
||||
.andExpect(content().string(equalTo("{\"ROOT\":{\"configuredLevel\":"
|
||||
+ "null,\"effectiveLevel\":\"DEBUG\"}}")));
|
||||
.andExpect(content().json(expected));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -19,7 +19,7 @@ package org.springframework.boot.devtools.restart;
|
||||
import org.springframework.boot.context.event.ApplicationFailedEvent;
|
||||
import org.springframework.boot.context.event.ApplicationPreparedEvent;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.boot.context.event.ApplicationStartedEvent;
|
||||
import org.springframework.boot.context.event.ApplicationStartingEvent;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.core.Ordered;
|
||||
@@ -41,8 +41,8 @@ public class RestartApplicationListener
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationEvent event) {
|
||||
if (event instanceof ApplicationStartedEvent) {
|
||||
onApplicationStartedEvent((ApplicationStartedEvent) event);
|
||||
if (event instanceof ApplicationStartingEvent) {
|
||||
onApplicationStartingEvent((ApplicationStartingEvent) event);
|
||||
}
|
||||
if (event instanceof ApplicationPreparedEvent) {
|
||||
Restarter.getInstance()
|
||||
@@ -57,7 +57,7 @@ public class RestartApplicationListener
|
||||
}
|
||||
}
|
||||
|
||||
private void onApplicationStartedEvent(ApplicationStartedEvent event) {
|
||||
private void onApplicationStartingEvent(ApplicationStartingEvent event) {
|
||||
// It's too early to use the Spring environment but we should still allow
|
||||
// users to disable restart using a System property.
|
||||
String enabled = System.getProperty(ENABLED_PROPERTY);
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.context.event.ApplicationFailedEvent;
|
||||
import org.springframework.boot.context.event.ApplicationPreparedEvent;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.boot.context.event.ApplicationStartedEvent;
|
||||
import org.springframework.boot.context.event.ApplicationStartingEvent;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
@@ -92,7 +92,7 @@ public class RestartApplicationListenerTests {
|
||||
SpringApplication application = new SpringApplication();
|
||||
ConfigurableApplicationContext context = mock(
|
||||
ConfigurableApplicationContext.class);
|
||||
listener.onApplicationEvent(new ApplicationStartedEvent(application, ARGS));
|
||||
listener.onApplicationEvent(new ApplicationStartingEvent(application, ARGS));
|
||||
assertThat(Restarter.getInstance()).isNotEqualTo(nullValue());
|
||||
assertThat(Restarter.getInstance().isFinished()).isFalse();
|
||||
listener.onApplicationEvent(
|
||||
|
||||
@@ -108,6 +108,10 @@ authenticated).
|
||||
|Displays arbitrary application info.
|
||||
|false
|
||||
|
||||
|`loggers`
|
||||
|Shows and modifies the configuration of loggers in the application.
|
||||
|true
|
||||
|
||||
|`liquibase`
|
||||
|Shows any Liquibase database migrations that have been applied.
|
||||
|true
|
||||
@@ -803,6 +807,39 @@ If you are using Jolokia but you don't want Spring Boot to configure it, simply
|
||||
|
||||
|
||||
|
||||
[[production-ready-loggers]]
|
||||
== Loggers
|
||||
Spring Boot Actuator includes the ability to view and configure the log levels of your
|
||||
application at runtime. You can view either the entire list or an individual logger's
|
||||
configuration which is made up of both the explictily configured logging level as well as
|
||||
the effective logging level given to it by the logging framework. These levels can be:
|
||||
|
||||
* `TRACE`
|
||||
* `DEBUG`
|
||||
* `INFO`
|
||||
* `WARN`
|
||||
* `ERROR`
|
||||
* `FATAL`
|
||||
* `OFF`
|
||||
* `null`
|
||||
|
||||
with `null` indicating that there is no explict configuration.
|
||||
|
||||
|
||||
|
||||
[[production-ready-logger-configuration]]
|
||||
=== Configure a Logger
|
||||
In order to configure a given logger, you `POST` a partial entity to the resource's URI:
|
||||
|
||||
[source,json,indent=0]
|
||||
----
|
||||
{
|
||||
"configuredLevel": "DEBUG"
|
||||
}
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[production-ready-metrics]]
|
||||
== Metrics
|
||||
Spring Boot Actuator includes a metrics service with '`gauge`' and '`counter`' support.
|
||||
|
||||
@@ -51,6 +51,7 @@ import org.springframework.web.servlet.DispatcherServlet;
|
||||
public class MockMvcAutoConfiguration {
|
||||
|
||||
private final WebApplicationContext context;
|
||||
|
||||
private final WebMvcProperties webMvcProperties;
|
||||
|
||||
MockMvcAutoConfiguration(WebApplicationContext context,
|
||||
|
||||
@@ -299,7 +299,7 @@ public class SpringApplication {
|
||||
FailureAnalyzers analyzers = null;
|
||||
configureHeadlessProperty();
|
||||
SpringApplicationRunListeners listeners = getRunListeners(args);
|
||||
listeners.started();
|
||||
listeners.starting();
|
||||
try {
|
||||
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
|
||||
args);
|
||||
|
||||
@@ -37,7 +37,7 @@ public interface SpringApplicationRunListener {
|
||||
* Called immediately when the run method has first started. Can be used for very
|
||||
* early initialization.
|
||||
*/
|
||||
void started();
|
||||
void starting();
|
||||
|
||||
/**
|
||||
* Called once the environment has been prepared, but before the
|
||||
|
||||
@@ -43,9 +43,9 @@ class SpringApplicationRunListeners {
|
||||
this.listeners = new ArrayList<SpringApplicationRunListener>(listeners);
|
||||
}
|
||||
|
||||
public void started() {
|
||||
public void starting() {
|
||||
for (SpringApplicationRunListener listener : this.listeners) {
|
||||
listener.started();
|
||||
listener.starting();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,9 +29,11 @@ import org.springframework.core.env.Environment;
|
||||
* state too much at this early stage since it might be modified later in the lifecycle.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @deprecated since 1.5.0 in favor of {@link ApplicationStartingEvent}
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("serial")
|
||||
public class ApplicationStartedEvent extends SpringApplicationEvent {
|
||||
public class ApplicationStartedEvent extends ApplicationStartingEvent {
|
||||
|
||||
/**
|
||||
* Create a new {@link ApplicationStartedEvent} instance.
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://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.context.event;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
/**
|
||||
* Event published as early as conceivably possible as soon as a {@link SpringApplication}
|
||||
* has been started - before the {@link Environment} or {@link ApplicationContext} is
|
||||
* available, but after the {@link ApplicationListener}s have been registered. The source
|
||||
* of the event is the {@link SpringApplication} itself, but beware of using its internal
|
||||
* state too much at this early stage since it might be modified later in the lifecycle.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Madhura Bhave
|
||||
* @since 1.5.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class ApplicationStartingEvent extends SpringApplicationEvent {
|
||||
|
||||
/**
|
||||
* Create a new {@link ApplicationStartingEvent} instance.
|
||||
* @param application the current application
|
||||
* @param args the arguments the application is running with
|
||||
*/
|
||||
public ApplicationStartingEvent(SpringApplication application, String[] args) {
|
||||
super(application, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -58,7 +58,8 @@ public class EventPublishingRunListener implements SpringApplicationRunListener,
|
||||
}
|
||||
|
||||
@Override
|
||||
public void started() {
|
||||
@SuppressWarnings("deprecation")
|
||||
public void starting() {
|
||||
this.initialMulticaster
|
||||
.multicastEvent(new ApplicationStartedEvent(this.application, this.args));
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import liquibase.servicelocator.ServiceLocator;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.boot.context.event.ApplicationStartedEvent;
|
||||
import org.springframework.boot.context.event.ApplicationStartingEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
@@ -33,13 +33,13 @@ import org.springframework.util.ClassUtils;
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class LiquibaseServiceLocatorApplicationListener
|
||||
implements ApplicationListener<ApplicationStartedEvent> {
|
||||
implements ApplicationListener<ApplicationStartingEvent> {
|
||||
|
||||
private static final Log logger = LogFactory
|
||||
.getLog(LiquibaseServiceLocatorApplicationListener.class);
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationStartedEvent event) {
|
||||
public void onApplicationEvent(ApplicationStartingEvent event) {
|
||||
if (ClassUtils.isPresent("liquibase.servicelocator.ServiceLocator", null)) {
|
||||
new LiquibasePresent().replaceServiceLocator();
|
||||
}
|
||||
|
||||
@@ -16,8 +16,11 @@
|
||||
|
||||
package org.springframework.boot.logging;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
@@ -33,6 +36,9 @@ import org.springframework.util.SystemPropertyUtils;
|
||||
*/
|
||||
public abstract class AbstractLoggingSystem extends LoggingSystem {
|
||||
|
||||
protected static final Comparator<LoggerConfiguration> CONFIGURATION_COMPARATOR = new LoggerConfigurationComparator(
|
||||
ROOT_LOGGER_NAME);
|
||||
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
public AbstractLoggingSystem(ClassLoader classLoader) {
|
||||
@@ -193,7 +199,9 @@ public abstract class AbstractLoggingSystem extends LoggingSystem {
|
||||
|
||||
public void map(LogLevel system, T nativeLevel) {
|
||||
this.systemToNative.put(system, nativeLevel);
|
||||
this.nativeToSystem.put(nativeLevel, system);
|
||||
if (!this.nativeToSystem.containsKey(nativeLevel)) {
|
||||
this.nativeToSystem.put(nativeLevel, system);
|
||||
}
|
||||
}
|
||||
|
||||
public LogLevel convertNativeToSystem(T level) {
|
||||
@@ -204,6 +212,10 @@ public abstract class AbstractLoggingSystem extends LoggingSystem {
|
||||
return this.systemToNative.get(level);
|
||||
}
|
||||
|
||||
public Set<LogLevel> getSupported() {
|
||||
return new LinkedHashSet<LogLevel>(this.nativeToSystem.values());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,9 +25,8 @@ import org.springframework.util.Assert;
|
||||
* Sorts the "root" logger as the first logger and then lexically by name after that.
|
||||
*
|
||||
* @author Ben Hale
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public class LoggerConfigurationComparator implements Comparator<LoggerConfiguration> {
|
||||
class LoggerConfigurationComparator implements Comparator<LoggerConfiguration> {
|
||||
|
||||
private final String rootLoggerName;
|
||||
|
||||
@@ -35,7 +34,7 @@ public class LoggerConfigurationComparator implements Comparator<LoggerConfigura
|
||||
* Create a new {@link LoggerConfigurationComparator} instance.
|
||||
* @param rootLoggerName the name of the "root" logger
|
||||
*/
|
||||
public LoggerConfigurationComparator(String rootLoggerName) {
|
||||
LoggerConfigurationComparator(String rootLoggerName) {
|
||||
Assert.notNull(rootLoggerName, "RootLoggerName must not be null");
|
||||
this.rootLoggerName = rootLoggerName;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
|
||||
import org.springframework.boot.context.event.ApplicationFailedEvent;
|
||||
import org.springframework.boot.context.event.ApplicationPreparedEvent;
|
||||
import org.springframework.boot.context.event.ApplicationStartedEvent;
|
||||
import org.springframework.boot.context.event.ApplicationStartingEvent;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
@@ -161,7 +161,7 @@ public class LoggingApplicationListener implements GenericApplicationListener {
|
||||
LOG_LEVEL_LOGGERS.add(LogLevel.DEBUG, "org.hibernate.SQL");
|
||||
}
|
||||
|
||||
private static Class<?>[] EVENT_TYPES = { ApplicationStartedEvent.class,
|
||||
private static Class<?>[] EVENT_TYPES = { ApplicationStartingEvent.class,
|
||||
ApplicationEnvironmentPreparedEvent.class, ApplicationPreparedEvent.class,
|
||||
ContextClosedEvent.class };
|
||||
|
||||
@@ -201,8 +201,8 @@ public class LoggingApplicationListener implements GenericApplicationListener {
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationEvent event) {
|
||||
if (event instanceof ApplicationStartedEvent) {
|
||||
onApplicationStartedEvent((ApplicationStartedEvent) event);
|
||||
if (event instanceof ApplicationStartingEvent) {
|
||||
onApplicationStartingEvent((ApplicationStartingEvent) event);
|
||||
}
|
||||
else if (event instanceof ApplicationEnvironmentPreparedEvent) {
|
||||
onApplicationEnvironmentPreparedEvent(
|
||||
@@ -220,7 +220,7 @@ public class LoggingApplicationListener implements GenericApplicationListener {
|
||||
}
|
||||
}
|
||||
|
||||
private void onApplicationStartedEvent(ApplicationStartedEvent event) {
|
||||
private void onApplicationStartingEvent(ApplicationStartingEvent event) {
|
||||
this.loggingSystem = LoggingSystem
|
||||
.get(event.getSpringApplication().getClassLoader());
|
||||
this.loggingSystem.beforeInitialize();
|
||||
@@ -350,7 +350,7 @@ public class LoggingApplicationListener implements GenericApplicationListener {
|
||||
private void setLogLevel(LoggingSystem system, Environment environment, String name,
|
||||
String level) {
|
||||
try {
|
||||
if (name.equalsIgnoreCase("root")) {
|
||||
if (name.equalsIgnoreCase(LoggingSystem.ROOT_LOGGER_NAME)) {
|
||||
name = null;
|
||||
}
|
||||
level = environment.resolvePlaceholders(level);
|
||||
|
||||
@@ -17,9 +17,11 @@
|
||||
package org.springframework.boot.logging;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -45,6 +47,13 @@ public abstract class LoggingSystem {
|
||||
*/
|
||||
public static final String NONE = "none";
|
||||
|
||||
/**
|
||||
* The name used to for the root logger. LoggingSystem implementations should ensure
|
||||
* that this is the name used to represent the root logger, regardless of the
|
||||
* underlying implementation.
|
||||
*/
|
||||
public static final String ROOT_LOGGER_NAME = "ROOT";
|
||||
|
||||
private static final Map<String, String> SYSTEMS;
|
||||
|
||||
static {
|
||||
@@ -94,9 +103,19 @@ public abstract class LoggingSystem {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a set of the {@link LogLevel LogLevels} that are actually supported by the
|
||||
* logging system.
|
||||
* @return the supported levels
|
||||
*/
|
||||
public Set<LogLevel> getSupportedLogLevels() {
|
||||
return EnumSet.allOf(LogLevel.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the logging level for a given logger.
|
||||
* @param loggerName the name of the logger to set
|
||||
* @param loggerName the name of the logger to set ({@code null} can be used for the
|
||||
* root logger).
|
||||
* @param level the log level
|
||||
*/
|
||||
public void setLogLevel(String loggerName, LogLevel level) {
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogManager;
|
||||
import java.util.logging.Logger;
|
||||
@@ -30,7 +31,6 @@ import org.springframework.boot.logging.AbstractLoggingSystem;
|
||||
import org.springframework.boot.logging.LogFile;
|
||||
import org.springframework.boot.logging.LogLevel;
|
||||
import org.springframework.boot.logging.LoggerConfiguration;
|
||||
import org.springframework.boot.logging.LoggerConfigurationComparator;
|
||||
import org.springframework.boot.logging.LoggingInitializationContext;
|
||||
import org.springframework.boot.logging.LoggingSystem;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -48,9 +48,6 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public class JavaLoggingSystem extends AbstractLoggingSystem {
|
||||
|
||||
private static final LoggerConfigurationComparator COMPARATOR = new LoggerConfigurationComparator(
|
||||
"");
|
||||
|
||||
private static final LogLevels<Level> LEVELS = new LogLevels<Level>();
|
||||
|
||||
static {
|
||||
@@ -113,11 +110,18 @@ public class JavaLoggingSystem extends AbstractLoggingSystem {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<LogLevel> getSupportedLogLevels() {
|
||||
return LEVELS.getSupported();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLogLevel(String loggerName, LogLevel level) {
|
||||
Assert.notNull(level, "Level must not be null");
|
||||
String name = (StringUtils.hasText(loggerName) ? loggerName : "");
|
||||
Logger logger = Logger.getLogger(name);
|
||||
if (loggerName == null || ROOT_LOGGER_NAME.equals(loggerName)) {
|
||||
loggerName = "";
|
||||
}
|
||||
Logger logger = Logger.getLogger(loggerName);
|
||||
if (logger != null) {
|
||||
logger.setLevel(LEVELS.convertSystemToNative(level));
|
||||
}
|
||||
@@ -130,7 +134,7 @@ public class JavaLoggingSystem extends AbstractLoggingSystem {
|
||||
while (names.hasMoreElements()) {
|
||||
result.add(getLoggerConfiguration(names.nextElement()));
|
||||
}
|
||||
Collections.sort(result, COMPARATOR);
|
||||
Collections.sort(result, CONFIGURATION_COMPARATOR);
|
||||
return Collections.unmodifiableList(result);
|
||||
}
|
||||
|
||||
@@ -142,7 +146,9 @@ public class JavaLoggingSystem extends AbstractLoggingSystem {
|
||||
}
|
||||
LogLevel level = LEVELS.convertNativeToSystem(logger.getLevel());
|
||||
LogLevel effectiveLevel = LEVELS.convertNativeToSystem(getEffectiveLevel(logger));
|
||||
return new LoggerConfiguration(logger.getName(), level, effectiveLevel);
|
||||
String name = (StringUtils.hasLength(logger.getName()) ? logger.getName()
|
||||
: ROOT_LOGGER_NAME);
|
||||
return new LoggerConfiguration(name, level, effectiveLevel);
|
||||
}
|
||||
|
||||
private Level getEffectiveLevel(Logger root) {
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
@@ -40,7 +41,6 @@ import org.apache.logging.log4j.message.Message;
|
||||
import org.springframework.boot.logging.LogFile;
|
||||
import org.springframework.boot.logging.LogLevel;
|
||||
import org.springframework.boot.logging.LoggerConfiguration;
|
||||
import org.springframework.boot.logging.LoggerConfigurationComparator;
|
||||
import org.springframework.boot.logging.LoggingInitializationContext;
|
||||
import org.springframework.boot.logging.LoggingSystem;
|
||||
import org.springframework.boot.logging.Slf4JLoggingSystem;
|
||||
@@ -60,9 +60,6 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public class Log4J2LoggingSystem extends Slf4JLoggingSystem {
|
||||
|
||||
private static final LoggerConfigurationComparator COMPARATOR = new LoggerConfigurationComparator(
|
||||
LogManager.ROOT_LOGGER_NAME);
|
||||
|
||||
private static final String FILE_PROTOCOL = "file";
|
||||
|
||||
private static final LogLevels<Level> LEVELS = new LogLevels<Level>();
|
||||
@@ -197,6 +194,11 @@ public class Log4J2LoggingSystem extends Slf4JLoggingSystem {
|
||||
getLoggerContext().reconfigure();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<LogLevel> getSupportedLogLevels() {
|
||||
return LEVELS.getSupported();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLogLevel(String loggerName, LogLevel logLevel) {
|
||||
Level level = LEVELS.convertSystemToNative(logLevel);
|
||||
@@ -218,7 +220,7 @@ public class Log4J2LoggingSystem extends Slf4JLoggingSystem {
|
||||
for (LoggerConfig loggerConfig : configuration.getLoggers().values()) {
|
||||
result.add(convertLoggerConfiguration(loggerConfig));
|
||||
}
|
||||
Collections.sort(result, COMPARATOR);
|
||||
Collections.sort(result, CONFIGURATION_COMPARATOR);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -232,7 +234,11 @@ public class Log4J2LoggingSystem extends Slf4JLoggingSystem {
|
||||
return null;
|
||||
}
|
||||
LogLevel level = LEVELS.convertNativeToSystem(loggerConfig.getLevel());
|
||||
return new LoggerConfiguration(loggerConfig.getName(), level, level);
|
||||
String name = loggerConfig.getName();
|
||||
if (!StringUtils.hasLength(name) || LogManager.ROOT_LOGGER_NAME.equals(name)) {
|
||||
name = ROOT_LOGGER_NAME;
|
||||
}
|
||||
return new LoggerConfiguration(name, level, level);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -248,7 +254,9 @@ public class Log4J2LoggingSystem extends Slf4JLoggingSystem {
|
||||
}
|
||||
|
||||
private LoggerConfig getLoggerConfig(String name) {
|
||||
name = (StringUtils.hasText(name) ? name : LogManager.ROOT_LOGGER_NAME);
|
||||
if (!StringUtils.hasLength(name) || ROOT_LOGGER_NAME.equals(name)) {
|
||||
name = LogManager.ROOT_LOGGER_NAME;
|
||||
}
|
||||
return getLoggerContext().getConfiguration().getLoggers().get(name);
|
||||
}
|
||||
|
||||
|
||||
@@ -95,7 +95,6 @@ class DefaultLogbackConfiguration {
|
||||
"org.springframework.boot");
|
||||
config.start(debugRemapAppender);
|
||||
config.appender("DEBUG_LEVEL_REMAPPER", debugRemapAppender);
|
||||
config.logger("", Level.ERROR);
|
||||
config.logger("org.apache.catalina.startup.DigesterFactory", Level.ERROR);
|
||||
config.logger("org.apache.catalina.util.LifecycleBase", Level.ERROR);
|
||||
config.logger("org.apache.coyote.http11.Http11NioProtocol", Level.WARN);
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.security.ProtectionDomain;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import ch.qos.logback.classic.Level;
|
||||
import ch.qos.logback.classic.LoggerContext;
|
||||
@@ -40,7 +41,6 @@ import org.slf4j.impl.StaticLoggerBinder;
|
||||
import org.springframework.boot.logging.LogFile;
|
||||
import org.springframework.boot.logging.LogLevel;
|
||||
import org.springframework.boot.logging.LoggerConfiguration;
|
||||
import org.springframework.boot.logging.LoggerConfigurationComparator;
|
||||
import org.springframework.boot.logging.LoggingInitializationContext;
|
||||
import org.springframework.boot.logging.LoggingSystem;
|
||||
import org.springframework.boot.logging.Slf4JLoggingSystem;
|
||||
@@ -58,9 +58,6 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public class LogbackLoggingSystem extends Slf4JLoggingSystem {
|
||||
|
||||
private static final LoggerConfigurationComparator COMPARATOR = new LoggerConfigurationComparator(
|
||||
Logger.ROOT_LOGGER_NAME);
|
||||
|
||||
private static final String CONFIGURATION_FILE_PROPERTY = "logback.configurationFile";
|
||||
|
||||
private static final LogLevels<Level> LEVELS = new LogLevels<Level>();
|
||||
@@ -218,7 +215,7 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem {
|
||||
for (ch.qos.logback.classic.Logger logger : getLoggerContext().getLoggerList()) {
|
||||
result.add(getLoggerConfiguration(logger));
|
||||
}
|
||||
Collections.sort(result, COMPARATOR);
|
||||
Collections.sort(result, CONFIGURATION_COMPARATOR);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -235,7 +232,16 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem {
|
||||
LogLevel level = LEVELS.convertNativeToSystem(logger.getLevel());
|
||||
LogLevel effectiveLevel = LEVELS
|
||||
.convertNativeToSystem(logger.getEffectiveLevel());
|
||||
return new LoggerConfiguration(logger.getName(), level, effectiveLevel);
|
||||
String name = logger.getName();
|
||||
if (!StringUtils.hasLength(name) || Logger.ROOT_LOGGER_NAME.equals(name)) {
|
||||
name = ROOT_LOGGER_NAME;
|
||||
}
|
||||
return new LoggerConfiguration(name, level, effectiveLevel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<LogLevel> getSupportedLogLevels() {
|
||||
return LEVELS.getSupported();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -253,7 +259,9 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem {
|
||||
|
||||
private ch.qos.logback.classic.Logger getLogger(String name) {
|
||||
LoggerContext factory = getLoggerContext();
|
||||
name = (StringUtils.isEmpty(name) ? Logger.ROOT_LOGGER_NAME : name);
|
||||
if (StringUtils.isEmpty(name) || ROOT_LOGGER_NAME.equals(name)) {
|
||||
name = Logger.ROOT_LOGGER_NAME;
|
||||
}
|
||||
return factory.getLogger(name);
|
||||
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletCon
|
||||
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
|
||||
import org.springframework.boot.context.event.ApplicationPreparedEvent;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.boot.context.event.ApplicationStartedEvent;
|
||||
import org.springframework.boot.context.event.ApplicationStartingEvent;
|
||||
import org.springframework.boot.testutil.InternalOutputCapture;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
@@ -302,6 +302,7 @@ public class SpringApplicationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
public void eventsOrder() {
|
||||
SpringApplication application = new SpringApplication(ExampleConfig.class);
|
||||
application.setWebEnvironment(false);
|
||||
@@ -316,7 +317,9 @@ public class SpringApplicationTests {
|
||||
application.addListeners(new ApplicationRunningEventListener());
|
||||
this.context = application.run();
|
||||
assertThat(events).hasSize(5);
|
||||
assertThat(events.get(0)).isInstanceOf(ApplicationStartedEvent.class);
|
||||
assertThat(events.get(0)).isInstanceOf(
|
||||
org.springframework.boot.context.event.ApplicationStartedEvent.class);
|
||||
assertThat(events.get(0)).isInstanceOf(ApplicationStartingEvent.class);
|
||||
assertThat(events.get(1)).isInstanceOf(ApplicationEnvironmentPreparedEvent.class);
|
||||
assertThat(events.get(2)).isInstanceOf(ApplicationPreparedEvent.class);
|
||||
assertThat(events.get(3)).isInstanceOf(ContextRefreshedEvent.class);
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.context.event.ApplicationStartedEvent;
|
||||
import org.springframework.boot.context.event.ApplicationStartingEvent;
|
||||
import org.springframework.boot.testutil.InternalOutputCapture;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
@@ -56,16 +56,18 @@ public class LoggingApplicationListenerIntegrationTests {
|
||||
@Test
|
||||
public void loggingPerformedDuringChildApplicationStartIsNotLost() {
|
||||
new SpringApplicationBuilder(Config.class).web(false).child(Config.class)
|
||||
.web(false).listeners(new ApplicationListener<ApplicationStartedEvent>() {
|
||||
.web(false)
|
||||
.listeners(new ApplicationListener<ApplicationStartingEvent>() {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationStartedEvent event) {
|
||||
this.logger.info("Child application started");
|
||||
public void onApplicationEvent(ApplicationStartingEvent event) {
|
||||
this.logger.info("Child application starting");
|
||||
}
|
||||
|
||||
}).run();
|
||||
assertThat(this.outputCapture.toString()).contains("Child application started");
|
||||
assertThat(this.outputCapture.toString()).contains("Child application starting");
|
||||
}
|
||||
|
||||
@Component
|
||||
|
||||
@@ -39,7 +39,7 @@ import org.slf4j.bridge.SLF4JBridgeHandler;
|
||||
import org.springframework.boot.ApplicationPid;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.context.event.ApplicationFailedEvent;
|
||||
import org.springframework.boot.context.event.ApplicationStartedEvent;
|
||||
import org.springframework.boot.context.event.ApplicationStartingEvent;
|
||||
import org.springframework.boot.logging.java.JavaLoggingSystem;
|
||||
import org.springframework.boot.testutil.InternalOutputCapture;
|
||||
import org.springframework.context.event.ContextClosedEvent;
|
||||
@@ -86,7 +86,7 @@ public class LoggingApplicationListenerTests {
|
||||
LogManager.getLogManager().readConfiguration(
|
||||
JavaLoggingSystem.class.getResourceAsStream("logging.properties"));
|
||||
this.initializer.onApplicationEvent(
|
||||
new ApplicationStartedEvent(new SpringApplication(), NO_ARGS));
|
||||
new ApplicationStartingEvent(new SpringApplication(), NO_ARGS));
|
||||
new File("target/foo.log").delete();
|
||||
new File(tmpDir() + "/spring.log").delete();
|
||||
}
|
||||
@@ -342,7 +342,7 @@ public class LoggingApplicationListenerTests {
|
||||
public void parseArgsDoesntReplace() throws Exception {
|
||||
this.initializer.setSpringBootLogging(LogLevel.ERROR);
|
||||
this.initializer.setParseArgs(false);
|
||||
this.initializer.onApplicationEvent(new ApplicationStartedEvent(
|
||||
this.initializer.onApplicationEvent(new ApplicationStartingEvent(
|
||||
this.springApplication, new String[] { "--debug" }));
|
||||
this.initializer.initialize(this.context.getEnvironment(),
|
||||
this.context.getClassLoader());
|
||||
@@ -387,7 +387,7 @@ public class LoggingApplicationListenerTests {
|
||||
System.setProperty(LoggingSystem.class.getName(),
|
||||
TestShutdownHandlerLoggingSystem.class.getName());
|
||||
listener.onApplicationEvent(
|
||||
new ApplicationStartedEvent(new SpringApplication(), NO_ARGS));
|
||||
new ApplicationStartingEvent(new SpringApplication(), NO_ARGS));
|
||||
listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
|
||||
assertThat(listener.shutdownHook).isNull();
|
||||
}
|
||||
@@ -400,7 +400,7 @@ public class LoggingApplicationListenerTests {
|
||||
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context,
|
||||
"logging.register_shutdown_hook=true");
|
||||
listener.onApplicationEvent(
|
||||
new ApplicationStartedEvent(new SpringApplication(), NO_ARGS));
|
||||
new ApplicationStartingEvent(new SpringApplication(), NO_ARGS));
|
||||
listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
|
||||
assertThat(listener.shutdownHook).isNotNull();
|
||||
listener.shutdownHook.start();
|
||||
@@ -413,7 +413,7 @@ public class LoggingApplicationListenerTests {
|
||||
System.setProperty(LoggingSystem.SYSTEM_PROPERTY,
|
||||
TestCleanupLoggingSystem.class.getName());
|
||||
this.initializer.onApplicationEvent(
|
||||
new ApplicationStartedEvent(this.springApplication, new String[0]));
|
||||
new ApplicationStartingEvent(this.springApplication, new String[0]));
|
||||
TestCleanupLoggingSystem loggingSystem = (TestCleanupLoggingSystem) ReflectionTestUtils
|
||||
.getField(this.initializer, "loggingSystem");
|
||||
assertThat(loggingSystem.cleanedUp).isFalse();
|
||||
@@ -426,7 +426,7 @@ public class LoggingApplicationListenerTests {
|
||||
System.setProperty(LoggingSystem.SYSTEM_PROPERTY,
|
||||
TestCleanupLoggingSystem.class.getName());
|
||||
this.initializer.onApplicationEvent(
|
||||
new ApplicationStartedEvent(this.springApplication, new String[0]));
|
||||
new ApplicationStartingEvent(this.springApplication, new String[0]));
|
||||
TestCleanupLoggingSystem loggingSystem = (TestCleanupLoggingSystem) ReflectionTestUtils
|
||||
.getField(this.initializer, "loggingSystem");
|
||||
assertThat(loggingSystem.cleanedUp).isFalse();
|
||||
@@ -472,7 +472,7 @@ public class LoggingApplicationListenerTests {
|
||||
System.setProperty(LoggingSystem.SYSTEM_PROPERTY,
|
||||
TestCleanupLoggingSystem.class.getName());
|
||||
this.initializer.onApplicationEvent(
|
||||
new ApplicationStartedEvent(this.springApplication, new String[0]));
|
||||
new ApplicationStartingEvent(this.springApplication, new String[0]));
|
||||
TestCleanupLoggingSystem loggingSystem = (TestCleanupLoggingSystem) ReflectionTestUtils
|
||||
.getField(this.initializer, "loggingSystem");
|
||||
assertThat(loggingSystem.cleanedUp).isFalse();
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.springframework.boot.logging.java;
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.IOException;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.logging.Level;
|
||||
@@ -32,6 +33,7 @@ import org.junit.Test;
|
||||
import org.springframework.boot.logging.AbstractLoggingSystemTests;
|
||||
import org.springframework.boot.logging.LogLevel;
|
||||
import org.springframework.boot.logging.LoggerConfiguration;
|
||||
import org.springframework.boot.logging.LoggingSystem;
|
||||
import org.springframework.boot.testutil.InternalOutputCapture;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -148,6 +150,13 @@ public class JavaLoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSupportedLevels() {
|
||||
assertThat(this.loggingSystem.getSupportedLogLevels())
|
||||
.isEqualTo(EnumSet.of(LogLevel.TRACE, LogLevel.DEBUG, LogLevel.INFO,
|
||||
LogLevel.WARN, LogLevel.ERROR, LogLevel.OFF));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setLevel() throws Exception {
|
||||
this.loggingSystem.beforeInitialize();
|
||||
@@ -167,7 +176,7 @@ public class JavaLoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
List<LoggerConfiguration> configurations = this.loggingSystem
|
||||
.getLoggerConfigurations();
|
||||
assertThat(configurations).isNotEmpty();
|
||||
assertThat(configurations.get(0).getName()).isEmpty();
|
||||
assertThat(configurations.get(0).getName()).isEqualTo(LoggingSystem.ROOT_LOGGER_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
@@ -39,6 +40,7 @@ import org.junit.Test;
|
||||
import org.springframework.boot.logging.AbstractLoggingSystemTests;
|
||||
import org.springframework.boot.logging.LogLevel;
|
||||
import org.springframework.boot.logging.LoggerConfiguration;
|
||||
import org.springframework.boot.logging.LoggingSystem;
|
||||
import org.springframework.boot.testutil.InternalOutputCapture;
|
||||
import org.springframework.boot.testutil.Matched;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
@@ -122,6 +124,12 @@ public class Log4J2LoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
this.loggingSystem.initialize(null, "classpath:log4j2-nonexistent.xml", null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSupportedLevels() {
|
||||
assertThat(this.loggingSystem.getSupportedLogLevels())
|
||||
.isEqualTo(EnumSet.allOf(LogLevel.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setLevel() throws Exception {
|
||||
this.loggingSystem.beforeInitialize();
|
||||
@@ -141,7 +149,8 @@ public class Log4J2LoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
List<LoggerConfiguration> configurations = this.loggingSystem
|
||||
.getLoggerConfigurations();
|
||||
assertThat(configurations).isNotEmpty();
|
||||
assertThat(configurations.get(0).getName()).isEmpty();
|
||||
assertThat(configurations.get(0).getName())
|
||||
.isEqualTo(LoggingSystem.ROOT_LOGGER_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.boot.logging.logback;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.LogManager;
|
||||
@@ -42,6 +43,7 @@ import org.springframework.boot.logging.LogFile;
|
||||
import org.springframework.boot.logging.LogLevel;
|
||||
import org.springframework.boot.logging.LoggerConfiguration;
|
||||
import org.springframework.boot.logging.LoggingInitializationContext;
|
||||
import org.springframework.boot.logging.LoggingSystem;
|
||||
import org.springframework.boot.testutil.InternalOutputCapture;
|
||||
import org.springframework.boot.testutil.Matched;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
@@ -162,6 +164,13 @@ public class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
"classpath:logback-nonexistent.xml", null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSupportedLevels() {
|
||||
assertThat(this.loggingSystem.getSupportedLogLevels())
|
||||
.isEqualTo(EnumSet.of(LogLevel.TRACE, LogLevel.DEBUG, LogLevel.INFO,
|
||||
LogLevel.WARN, LogLevel.ERROR, LogLevel.OFF));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setLevel() throws Exception {
|
||||
this.loggingSystem.beforeInitialize();
|
||||
@@ -182,7 +191,7 @@ public class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
.getLoggerConfigurations();
|
||||
assertThat(configurations).isNotEmpty();
|
||||
assertThat(configurations.get(0).getName())
|
||||
.isEqualTo(org.slf4j.Logger.ROOT_LOGGER_NAME);
|
||||
.isEqualTo(LoggingSystem.ROOT_LOGGER_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -30,7 +30,7 @@ import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
|
||||
import org.springframework.boot.context.event.ApplicationPreparedEvent;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.boot.context.event.ApplicationStartedEvent;
|
||||
import org.springframework.boot.context.event.ApplicationStartingEvent;
|
||||
import org.springframework.boot.context.event.SpringApplicationEvent;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
@@ -129,9 +129,9 @@ public class ApplicationPidFileWriterTests {
|
||||
public void withNoEnvironment() throws Exception {
|
||||
File file = this.temporaryFolder.newFile();
|
||||
ApplicationPidFileWriter listener = new ApplicationPidFileWriter(file);
|
||||
listener.setTriggerEventType(ApplicationStartedEvent.class);
|
||||
listener.setTriggerEventType(ApplicationStartingEvent.class);
|
||||
listener.onApplicationEvent(
|
||||
new ApplicationStartedEvent(new SpringApplication(), new String[] {}));
|
||||
new ApplicationStartingEvent(new SpringApplication(), new String[] {}));
|
||||
assertThat(FileCopyUtils.copyToString(new FileReader(file))).isNotEmpty();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user