mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-08-29 03:06:45 +08:00
Allow auto-reload of log4j2 config
Log4j2 can auto-reload its configuration file as long as the reference to a `java.io.File` is provided in the `ConfigurationSource`. Previously, we always created such `ConfigurationSource` with only the URL regardless of its type. Detect when the configuration URL points to a File and create the `ConfigurationSource` accordingly. The `spring-boot-sample-actuator-log4j2` has been updated to reload the logging configuration every 30 sec if necessary. Fixes gh-3024, gh-3030
This commit is contained in:
parent
f0b203f6da
commit
04776232f7
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Configuration status="WARN">
|
||||
<Configuration status="WARN" monitorInterval="30">
|
||||
<Properties>
|
||||
<Property name="PID">????</Property>
|
||||
<Property name="LOG_PATTERN">[%d{yyyy-MM-dd HH:mm:ss.SSS}] log4j2%X{context} - ${sys:PID} %5p [%t] --- %c{1}: %m%n</Property>
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.boot.logging.log4j2;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@ -48,6 +50,7 @@ import org.springframework.util.ResourceUtils;
|
||||
*
|
||||
* @author Daniel Fullarton
|
||||
* @author Andy Wilkinson
|
||||
* @author Alexander Heusingfeld
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public class Log4J2LoggingSystem extends Slf4JLoggingSystem {
|
||||
@ -149,7 +152,7 @@ public class Log4J2LoggingSystem extends Slf4JLoggingSystem {
|
||||
try {
|
||||
LoggerContext ctx = getLoggerContext();
|
||||
URL url = ResourceUtils.getURL(location);
|
||||
ConfigurationSource source = new ConfigurationSource(url.openStream(), url);
|
||||
ConfigurationSource source = getConfigurationSource(url);
|
||||
ctx.start(ConfigurationFactory.getInstance().getConfiguration(source));
|
||||
}
|
||||
catch (Exception ex) {
|
||||
@ -158,6 +161,16 @@ public class Log4J2LoggingSystem extends Slf4JLoggingSystem {
|
||||
}
|
||||
}
|
||||
|
||||
private ConfigurationSource getConfigurationSource(URL url) throws IOException {
|
||||
InputStream stream = url.openStream();
|
||||
if (ResourceUtils.isFileURL(url)) {
|
||||
return new ConfigurationSource(stream,
|
||||
ResourceUtils.getFile(url));
|
||||
} else {
|
||||
return new ConfigurationSource(stream, url);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void reinitialize() {
|
||||
getLoggerContext().reconfigure();
|
||||
|
@ -21,22 +21,27 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.core.config.Configuration;
|
||||
import org.apache.logging.log4j.core.config.FileConfigurationMonitor;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.logging.AbstractLoggingSystemTests;
|
||||
import org.springframework.boot.logging.LogLevel;
|
||||
import org.springframework.boot.test.OutputCapture;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import static org.hamcrest.Matchers.arrayContaining;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.core.StringContains.containsString;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
@ -72,6 +77,8 @@ public class Log4J2LoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
assertTrue("Wrong output:\n" + output, output.contains("Hello world"));
|
||||
assertFalse("Output not hidden:\n" + output, output.contains("Hidden"));
|
||||
assertFalse(new File(tmpDir() + "/spring.log").exists());
|
||||
assertThat(this.loggingSystem.getConfiguration().getConfigurationSource()
|
||||
.getFile(), is(notNullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -84,6 +91,8 @@ public class Log4J2LoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
assertTrue("Wrong output:\n" + output, output.contains("Hello world"));
|
||||
assertFalse("Output not hidden:\n" + output, output.contains("Hidden"));
|
||||
assertTrue(new File(tmpDir() + "/spring.log").exists());
|
||||
assertThat(this.loggingSystem.getConfiguration().getConfigurationSource()
|
||||
.getFile(), is(notNullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -96,6 +105,12 @@ public class Log4J2LoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
assertTrue("Wrong output:\n" + output, output.contains("Hello world"));
|
||||
assertTrue("Wrong output:\n" + output, output.contains(tmpDir() + "/tmp.log"));
|
||||
assertFalse(new File(tmpDir() + "/tmp.log").exists());
|
||||
assertThat(this.loggingSystem.getConfiguration().getConfigurationSource()
|
||||
.getFile().getAbsolutePath(), containsString("log4j2-nondefault.xml"));
|
||||
// we assume that "log4j2-nondefault.xml" contains the 'monitorInterval'
|
||||
// attribute, so we check that a monitor is created
|
||||
assertThat(this.loggingSystem.getConfiguration().getConfigurationMonitor(),
|
||||
is(instanceOf(FileConfigurationMonitor.class)));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
@ -167,6 +182,10 @@ public class Log4J2LoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
super(TestLog4J2LoggingSystem.class.getClassLoader());
|
||||
}
|
||||
|
||||
public Configuration getConfiguration() {
|
||||
return ((org.apache.logging.log4j.core.LoggerContext) LogManager.getContext(false)).getConfiguration();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isClassAvailable(String className) {
|
||||
return this.availableClasses.contains(className);
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Configuration status="WARN">
|
||||
<Configuration status="WARN" monitorInterval="30">
|
||||
<Properties>
|
||||
<Property name="PID">????</Property>
|
||||
<Property name="LOG_PATTERN">${sys:LOG_FILE} %d{yyyy-MM-dd HH:mm:ss.SSS}] service%X{context} - ${sys:PID} %5p [%t] --- %c{1}: %m%n</Property>
|
||||
|
Loading…
Reference in New Issue
Block a user