Browse Source

Fail fast when a Logback configuration file is missing or malformed

Closes gh-3309
pull/3333/head
Andy Wilkinson 11 years ago
parent
commit
c3d93f70b8
  1. 9
      spring-boot/src/main/java/org/springframework/boot/logging/LoggingApplicationListener.java
  2. 18
      spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystem.java
  3. 25
      spring-boot/src/test/java/org/springframework/boot/logging/LoggingApplicationListenerTests.java
  4. 11
      spring-boot/src/test/resources/logback-broken.xml

9
spring-boot/src/main/java/org/springframework/boot/logging/LoggingApplicationListener.java

@ -206,10 +206,11 @@ public class LoggingApplicationListener implements GenericApplicationListener {
system.initialize(logConfig, logFile); system.initialize(logConfig, logFile);
} }
catch (Exception ex) { catch (Exception ex) {
this.logger.warn("Logging environment value '" + logConfig System.err
+ "' cannot be opened and will be ignored " .println("Logging system failed to initialize using configuration from '"
+ "(using default location instead)"); + logConfig + "'");
system.initialize(null, logFile); ex.printStackTrace(System.err);
throw new IllegalStateException(ex);
} }
} }
else { else {

18
spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystem.java

@ -21,6 +21,7 @@ import java.security.CodeSource;
import java.security.ProtectionDomain; import java.security.ProtectionDomain;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import org.slf4j.ILoggerFactory; import org.slf4j.ILoggerFactory;
@ -40,6 +41,7 @@ import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.turbo.TurboFilter; import ch.qos.logback.classic.turbo.TurboFilter;
import ch.qos.logback.classic.util.ContextInitializer; import ch.qos.logback.classic.util.ContextInitializer;
import ch.qos.logback.core.spi.FilterReply; import ch.qos.logback.core.spi.FilterReply;
import ch.qos.logback.core.status.Status;
/** /**
* {@link LoggingSystem} for <a href="http://logback.qos.ch">logback</a>. * {@link LoggingSystem} for <a href="http://logback.qos.ch">logback</a>.
@ -122,6 +124,22 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem {
throw new IllegalStateException("Could not initialize Logback logging from " throw new IllegalStateException("Could not initialize Logback logging from "
+ location, ex); + location, ex);
} }
List<Status> statuses = context.getStatusManager().getCopyOfStatusList();
if (containsError(statuses)) {
for (Status status : statuses) {
System.err.println(status);
}
throw new IllegalStateException("Logback configuration error detected");
}
}
private boolean containsError(List<Status> statuses) {
for (Status status : statuses) {
if (status.getLevel() == Status.ERROR) {
return true;
}
}
return false;
} }
@Override @Override

25
spring-boot/src/test/java/org/springframework/boot/logging/LoggingApplicationListenerTests.java

@ -29,6 +29,7 @@ import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder; import org.junit.rules.TemporaryFolder;
import org.slf4j.bridge.SLF4JBridgeHandler; import org.slf4j.bridge.SLF4JBridgeHandler;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
@ -56,6 +57,9 @@ public class LoggingApplicationListenerTests {
private static final String[] NO_ARGS = {}; private static final String[] NO_ARGS = {};
@Rule
public ExpectedException thrown = ExpectedException.none();
@Rule @Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder(); public TemporaryFolder temporaryFolder = new TemporaryFolder();
@ -129,14 +133,23 @@ public class LoggingApplicationListenerTests {
public void overrideConfigDoesNotExist() throws Exception { public void overrideConfigDoesNotExist() throws Exception {
EnvironmentTestUtils.addEnvironment(this.context, EnvironmentTestUtils.addEnvironment(this.context,
"logging.config: doesnotexist.xml"); "logging.config: doesnotexist.xml");
this.thrown.expect(IllegalStateException.class);
this.outputCapture
.expect(containsString("Logging system failed to initialize using configuration from 'doesnotexist.xml'"));
this.initializer.initialize(this.context.getEnvironment(),
this.context.getClassLoader());
}
@Test
public void overrideConfigBroken() throws Exception {
EnvironmentTestUtils.addEnvironment(this.context,
"logging.config: classpath:logback-broken.xml");
this.thrown.expect(IllegalStateException.class);
this.outputCapture
.expect(containsString("Logging system failed to initialize using configuration from 'classpath:logback-broken.xml'"));
this.outputCapture.expect(containsString("ConsolAppender"));
this.initializer.initialize(this.context.getEnvironment(), this.initializer.initialize(this.context.getEnvironment(),
this.context.getClassLoader()); this.context.getClassLoader());
// Should not throw
this.logger.info("Hello world");
String output = this.outputCapture.toString().trim();
assertTrue("Wrong output:\n" + output, output.contains("Hello world"));
assertFalse("Wrong output:\n" + output, output.contains("???"));
assertFalse(new File(tmpDir() + "/spring.log").exists());
} }
@Test @Test

11
spring-boot/src/test/resources/logback-broken.xml

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsolAppender">
<encoder>
<pattern>${LOG_FILE} [%t] ${PID:-????} %c{1}: %m%n BOOTBOOT</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE" />
</root>
</configuration>
Loading…
Cancel
Save