mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-09-03 04:26:12 +08:00
Log file location should be evaluated just once
Using a random value for the logfile name caused the logfile endpoint to return a 404 as the name was resolved from the environment on every request. This commit registers a bean for LogFile which is then used by the logfile endpoint. Fixes gh-17434
This commit is contained in:
parent
7854876608
commit
773dda3d55
@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.boot.actuate.autoconfigure.logging;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint;
|
||||
import org.springframework.boot.actuate.logging.LogFileWebEndpoint;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
@ -24,6 +25,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.logging.LogFile;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
@ -52,8 +54,8 @@ public class LogFileWebEndpointAutoConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@Conditional(LogFileCondition.class)
|
||||
public LogFileWebEndpoint logFileWebEndpoint(Environment environment) {
|
||||
return new LogFileWebEndpoint(environment, this.properties.getExternalFile());
|
||||
public LogFileWebEndpoint logFileWebEndpoint(ObjectProvider<LogFile> logFile) {
|
||||
return new LogFileWebEndpoint(logFile.getIfAvailable(), this.properties.getExternalFile());
|
||||
}
|
||||
|
||||
private static class LogFileCondition extends SpringBootCondition {
|
||||
|
@ -19,6 +19,7 @@ package org.springframework.boot.actuate.autoconfigure.endpoint.web.documentatio
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.actuate.logging.LogFileWebEndpoint;
|
||||
import org.springframework.boot.logging.LogFile;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
@ -56,7 +57,7 @@ public class LogFileWebEndpointDocumentationTests extends MockMvcEndpointDocumen
|
||||
|
||||
@Bean
|
||||
public LogFileWebEndpoint endpoint(Environment environment) {
|
||||
return new LogFileWebEndpoint(environment);
|
||||
return new LogFileWebEndpoint(LogFile.get(environment), null);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpoint;
|
||||
import org.springframework.boot.logging.LogFile;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
@ -42,17 +41,13 @@ public class LogFileWebEndpoint {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(LogFileWebEndpoint.class);
|
||||
|
||||
private final Environment environment;
|
||||
|
||||
private File externalFile;
|
||||
|
||||
public LogFileWebEndpoint(Environment environment, File externalFile) {
|
||||
this.environment = environment;
|
||||
this.externalFile = externalFile;
|
||||
}
|
||||
private final LogFile logFile;
|
||||
|
||||
public LogFileWebEndpoint(Environment environment) {
|
||||
this(environment, null);
|
||||
public LogFileWebEndpoint(LogFile logFile, File externalFile) {
|
||||
this.externalFile = externalFile;
|
||||
this.logFile = logFile;
|
||||
}
|
||||
|
||||
@ReadOperation(produces = "text/plain; charset=UTF-8")
|
||||
@ -68,12 +63,11 @@ public class LogFileWebEndpoint {
|
||||
if (this.externalFile != null) {
|
||||
return new FileSystemResource(this.externalFile);
|
||||
}
|
||||
LogFile logFile = LogFile.get(this.environment);
|
||||
if (logFile == null) {
|
||||
if (this.logFile == null) {
|
||||
logger.debug("Missing 'logging.file' or 'logging.path' properties");
|
||||
return null;
|
||||
}
|
||||
return new FileSystemResource(logFile.toString());
|
||||
return new FileSystemResource(this.logFile.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
import org.springframework.boot.logging.LogFile;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
@ -46,8 +47,6 @@ public class LogFileWebEndpointTests {
|
||||
|
||||
private final MockEnvironment environment = new MockEnvironment();
|
||||
|
||||
private final LogFileWebEndpoint endpoint = new LogFileWebEndpoint(this.environment);
|
||||
|
||||
private File logFile;
|
||||
|
||||
@Before
|
||||
@ -58,26 +57,29 @@ public class LogFileWebEndpointTests {
|
||||
|
||||
@Test
|
||||
public void nullResponseWithoutLogFile() {
|
||||
assertThat(this.endpoint.logFile()).isNull();
|
||||
LogFileWebEndpoint endpoint = new LogFileWebEndpoint(null, null);
|
||||
assertThat(endpoint.logFile()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullResponseWithMissingLogFile() {
|
||||
this.environment.setProperty("logging.file", "no_test.log");
|
||||
assertThat(this.endpoint.logFile()).isNull();
|
||||
LogFileWebEndpoint endpoint = new LogFileWebEndpoint(LogFile.get(this.environment), null);
|
||||
assertThat(endpoint.logFile()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resourceResponseWithLogFile() throws Exception {
|
||||
this.environment.setProperty("logging.file", this.logFile.getAbsolutePath());
|
||||
Resource resource = this.endpoint.logFile();
|
||||
LogFileWebEndpoint endpoint = new LogFileWebEndpoint(LogFile.get(this.environment), null);
|
||||
Resource resource = endpoint.logFile();
|
||||
assertThat(resource).isNotNull();
|
||||
assertThat(StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8)).isEqualTo("--TEST--");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resourceResponseWithExternalLogFile() throws Exception {
|
||||
LogFileWebEndpoint endpoint = new LogFileWebEndpoint(this.environment, this.logFile);
|
||||
LogFileWebEndpoint endpoint = new LogFileWebEndpoint(null, this.logFile);
|
||||
Resource resource = endpoint.logFile();
|
||||
assertThat(resource).isNotNull();
|
||||
assertThat(StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8)).isEqualTo("--TEST--");
|
||||
|
@ -17,21 +17,19 @@
|
||||
package org.springframework.boot.actuate.logging;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.web.test.WebEndpointRunners;
|
||||
import org.springframework.boot.test.util.TestPropertyValues;
|
||||
import org.springframework.boot.logging.LogFile;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
|
||||
@ -48,32 +46,19 @@ public class LogFileWebEndpointWebIntegrationTests {
|
||||
|
||||
private static WebTestClient client;
|
||||
|
||||
@Rule
|
||||
public final TemporaryFolder temp = new TemporaryFolder();
|
||||
@ClassRule
|
||||
public static final TemporaryFolder temp = new TemporaryFolder();
|
||||
|
||||
private File logFile;
|
||||
|
||||
@Before
|
||||
public void setUp() throws IOException {
|
||||
this.logFile = this.temp.newFile();
|
||||
FileCopyUtils.copy("--TEST--".getBytes(), this.logFile);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequestProduces404ResponseWhenLogFileNotFound() {
|
||||
client.get().uri("/actuator/logfile").exchange().expectStatus().isNotFound();
|
||||
}
|
||||
private static File logFile;
|
||||
|
||||
@Test
|
||||
public void getRequestProducesResponseWithLogFile() {
|
||||
TestPropertyValues.of("logging.file:" + this.logFile.getAbsolutePath()).applyTo(context);
|
||||
client.get().uri("/actuator/logfile").exchange().expectStatus().isOk().expectHeader()
|
||||
.contentType("text/plain; charset=UTF-8").expectBody(String.class).isEqualTo("--TEST--");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequestThatAcceptsTextPlainProducesResponseWithLogFile() {
|
||||
TestPropertyValues.of("logging.file:" + this.logFile.getAbsolutePath()).applyTo(context);
|
||||
client.get().uri("/actuator/logfile").accept(MediaType.TEXT_PLAIN).exchange().expectStatus().isOk()
|
||||
.expectHeader().contentType("text/plain; charset=UTF-8").expectBody(String.class).isEqualTo("--TEST--");
|
||||
}
|
||||
@ -82,8 +67,12 @@ public class LogFileWebEndpointWebIntegrationTests {
|
||||
static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
public LogFileWebEndpoint logFileEndpoint(Environment environment) {
|
||||
return new LogFileWebEndpoint(environment);
|
||||
public LogFileWebEndpoint logFileEndpoint() throws Exception {
|
||||
logFile = temp.newFile();
|
||||
FileCopyUtils.copy("--TEST--".getBytes(), logFile);
|
||||
MockEnvironment environment = new MockEnvironment();
|
||||
environment.setProperty("logging.file", logFile.getAbsolutePath());
|
||||
return new LogFileWebEndpoint(LogFile.get(environment), null);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -121,6 +121,11 @@ public class LoggingApplicationListener implements GenericApplicationListener {
|
||||
*/
|
||||
public static final String LOGGING_SYSTEM_BEAN_NAME = "springBootLoggingSystem";
|
||||
|
||||
/**
|
||||
* The name of the {@link LogFile} bean.
|
||||
*/
|
||||
public static final String LOGFILE_BEAN_NAME = "springBootLogFile";
|
||||
|
||||
private static final Map<String, List<String>> DEFAULT_GROUP_LOGGERS;
|
||||
static {
|
||||
MultiValueMap<String, String> loggers = new LinkedMultiValueMap<>();
|
||||
@ -160,6 +165,8 @@ public class LoggingApplicationListener implements GenericApplicationListener {
|
||||
|
||||
private LoggingSystem loggingSystem;
|
||||
|
||||
private LogFile logFile;
|
||||
|
||||
private int order = DEFAULT_ORDER;
|
||||
|
||||
private boolean parseArgs = true;
|
||||
@ -224,6 +231,9 @@ public class LoggingApplicationListener implements GenericApplicationListener {
|
||||
if (!beanFactory.containsBean(LOGGING_SYSTEM_BEAN_NAME)) {
|
||||
beanFactory.registerSingleton(LOGGING_SYSTEM_BEAN_NAME, this.loggingSystem);
|
||||
}
|
||||
if (this.logFile != null && !beanFactory.containsBean(LOGFILE_BEAN_NAME)) {
|
||||
beanFactory.registerSingleton(LOGFILE_BEAN_NAME, this.logFile);
|
||||
}
|
||||
}
|
||||
|
||||
private void onContextClosedEvent() {
|
||||
@ -246,12 +256,12 @@ public class LoggingApplicationListener implements GenericApplicationListener {
|
||||
*/
|
||||
protected void initialize(ConfigurableEnvironment environment, ClassLoader classLoader) {
|
||||
new LoggingSystemProperties(environment).apply();
|
||||
LogFile logFile = LogFile.get(environment);
|
||||
if (logFile != null) {
|
||||
logFile.applyToSystemProperties();
|
||||
this.logFile = LogFile.get(environment);
|
||||
if (this.logFile != null) {
|
||||
this.logFile.applyToSystemProperties();
|
||||
}
|
||||
initializeEarlyLoggingLevel(environment);
|
||||
initializeSystem(environment, this.loggingSystem, logFile);
|
||||
initializeSystem(environment, this.loggingSystem, this.logFile);
|
||||
initializeFinalLoggingLevels(environment, this.loggingSystem);
|
||||
registerShutdownHookIfNecessary(environment, this.loggingSystem);
|
||||
}
|
||||
|
@ -66,6 +66,13 @@ public class EndpointsPropertiesSampleActuatorApplicationTests {
|
||||
assertThat(entity.getBody()).contains("\"hello\":\"world\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void logfileWithRandomName() {
|
||||
ResponseEntity<String> entity = this.restTemplate.withBasicAuth("user", getPassword())
|
||||
.getForEntity("/admin/logfile", String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
}
|
||||
|
||||
private String getPassword() {
|
||||
return "password";
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
server.error.path: /oops
|
||||
management.endpoint.health.show-details: always
|
||||
management.endpoints.web.base-path: /admin
|
||||
logging.file=./target/${spring.application.instance_id}.log
|
||||
spring.application.instance_id=${random.value}
|
||||
|
Loading…
Reference in New Issue
Block a user