diff --git a/spring-boot-cli/src/it/java/org/springframework/boot/cli/JarCommandIT.java b/spring-boot-cli/src/it/java/org/springframework/boot/cli/JarCommandIT.java
index e795fcd71d..d18d7dd36e 100644
--- a/spring-boot-cli/src/it/java/org/springframework/boot/cli/JarCommandIT.java
+++ b/spring-boot-cli/src/it/java/org/springframework/boot/cli/JarCommandIT.java
@@ -62,9 +62,12 @@ public class JarCommandIT {
@Test
public void jarCreationWithGrabResolver() throws Exception {
File jar = new File("target/test-app.jar");
- Invocation invocation = this.cli.invoke("jar", jar.getAbsolutePath(),
+ Invocation invocation = this.cli.invoke("run", jar.getAbsolutePath(),
"bad.groovy");
invocation.await();
+ assertThat(invocation.getErrorOutput(), equalTo(""));
+ invocation = this.cli.invoke("jar", jar.getAbsolutePath(), "bad.groovy");
+ invocation.await();
assertEquals(invocation.getErrorOutput(), 0, invocation.getErrorOutput().length());
assertTrue(jar.exists());
diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc
index 5be479bfb7..1ab5ee145e 100644
--- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc
+++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc
@@ -43,7 +43,8 @@ content into your application; rather pick only the properties that you need.
# LOGGING
logging.path=/var/logs
logging.file=myapp.log
- logging.config=
+ logging.config= # location of config file (default classpath:/logback.xml for logback)
+ logging.level.*= # levels for loggers, e.g. "logging.level.org.springframework=DEBUG" (TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF)
# IDENTITY ({sc-spring-boot}/context/ContextIdApplicationContextInitializer.{sc-ext}[ContextIdApplicationContextInitializer])
spring.application.name=
diff --git a/spring-boot-docs/src/main/asciidoc/howto.adoc b/spring-boot-docs/src/main/asciidoc/howto.adoc
index cd9508c0e7..727a87054e 100644
--- a/spring-boot-docs/src/main/asciidoc/howto.adoc
+++ b/spring-boot-docs/src/main/asciidoc/howto.adoc
@@ -833,10 +833,6 @@ Check out {sc-spring-boot-autoconfigure}/web/WebMvcAutoConfiguration.{sc-ext}[`W
[[howto-logging]]
== Logging
-
-
-[[howto-configure-logback-for-loggin]]
-=== Configure Logback for logging
Spring Boot has no mandatory logging dependence, except for the `commons-logging` API, of
which there are many implementations to choose from. To use http://logback.qos.ch[Logback]
you need to include it, and some bindings for `commons-logging` on the classpath. The
@@ -854,10 +850,32 @@ For example, using Maven:
----
Spring Boot has a `LoggingSystem` abstraction that attempts to configure logging based on
-the content of the classpath. If Logback is available it is the first choice. So if you
-put a `logback.xml` in the root of your classpath it will be picked up from there. Spring
-Boot provides a default base configuration that you can include if you just want to set
-levels, e.g.
+the content of the classpath. If Logback is available it is the first choice.
+
+If the only change you need to make to logging is to set the levels of various loggers
+then you can do that in `application.properties` using the "logging.level" prefix, e.g.
+
+[source,properties,indent=0,subs="verbatim,quotes,attributes"]
+----
+logging.level.org.springframework.web: DEBUG
+logging.level.org.hibernate: ERROR
+----
+
+You can also set the location of a file to log to (in addition to the console) using
+"logging.file".
+
+To configure the more fine grained settings of a logging system you need to use the native configuration
+format supported by the `LoggingSystem` in question. By default Spring Boot picks up the native
+configuration from its default location for the system (e.g. `classpath:/logback.xml` for Logback), but
+you can set the location of the config file using the "logging.config" property.
+
+
+[[howto-configure-logback-for-loggin]]
+=== Configure Logback for logging
+If you put a `logback.xml` in the root of your classpath it will be
+picked up from there. Spring Boot provides a default base
+configuration that you can include if you just want to set levels,
+e.g.
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
----
diff --git a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc
index a4237f05c5..061ee6f4b6 100644
--- a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc
+++ b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc
@@ -724,6 +724,18 @@ using a `logging.file` property.
As with console output, `ERROR`, `WARN` and `INFO` level messages are logged by default.
+[[boot-features-custom-log-levels]]
+=== Log Levels
+
+All the supported logging systems can have the logger levels set in the Spring `Environment`
+(so for example in `application.properties`) using "logging.level.*=LEVEL" where "LEVEL" is one of
+TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF. Example `application.properties`:
+
+[source,properties,indent=0,subs="verbatim,quotes,attributes"]
+----
+logging.level.org.springframework.web: DEBUG
+logging.level.org.hibernate: ERROR
+----
[[boot-features-custom-log-configuration]]
diff --git a/spring-boot-samples/spring-boot-sample-actuator/src/main/resources/application.properties b/spring-boot-samples/spring-boot-sample-actuator/src/main/resources/application.properties
index 87a55bc89d..49672f79a1 100644
--- a/spring-boot-samples/spring-boot-sample-actuator/src/main/resources/application.properties
+++ b/spring-boot-samples/spring-boot-sample-actuator/src/main/resources/application.properties
@@ -1,4 +1,5 @@
logging.file: /tmp/logs/app.log
+logging.level.org.springframework.security: INFO
management.address: 127.0.0.1
endpoints.shutdown.enabled: true
server.tomcat.basedir: target/tomcat
diff --git a/spring-boot-samples/spring-boot-sample-actuator/src/main/resources/logback.xml b/spring-boot-samples/spring-boot-sample-actuator/src/main/resources/logback.xml
deleted file mode 100644
index d1900162b3..0000000000
--- a/spring-boot-samples/spring-boot-sample-actuator/src/main/resources/logback.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
diff --git a/spring-boot-samples/spring-boot-sample-integration/src/main/resources/application.properties b/spring-boot-samples/spring-boot-sample-integration/src/main/resources/application.properties
index 1fd64e4d13..92dc00252b 100644
--- a/spring-boot-samples/spring-boot-sample-integration/src/main/resources/application.properties
+++ b/spring-boot-samples/spring-boot-sample-integration/src/main/resources/application.properties
@@ -1,3 +1,4 @@
logging.file: /tmp/logs/app.log
+logging.level.org.springframework.integration.file: DEBUG
service.greeting: Hello
debug: true
\ No newline at end of file
diff --git a/spring-boot-samples/spring-boot-sample-integration/src/main/resources/logback.xml b/spring-boot-samples/spring-boot-sample-integration/src/main/resources/logback.xml
deleted file mode 100644
index 178cf3322a..0000000000
--- a/spring-boot-samples/spring-boot-sample-integration/src/main/resources/logback.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/spring-boot-samples/spring-boot-sample-parent-context/src/main/resources/logback.xml b/spring-boot-samples/spring-boot-sample-parent-context/src/main/resources/logback.xml
deleted file mode 100644
index 178cf3322a..0000000000
--- a/spring-boot-samples/spring-boot-sample-parent-context/src/main/resources/logback.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/spring-boot-samples/spring-boot-sample-web-groovy-templates/src/main/resources/application.properties b/spring-boot-samples/spring-boot-sample-web-groovy-templates/src/main/resources/application.properties
index f1e67dc5f9..14bc33fa92 100644
--- a/spring-boot-samples/spring-boot-sample-web-groovy-templates/src/main/resources/application.properties
+++ b/spring-boot-samples/spring-boot-sample-web-groovy-templates/src/main/resources/application.properties
@@ -1,2 +1,3 @@
# Allow templates to be reloaded at dev time
spring.groovy.template.cache: false
+logging.level.org.springframework.web: INFO
\ No newline at end of file
diff --git a/spring-boot-samples/spring-boot-sample-web-groovy-templates/src/main/resources/logback.xml b/spring-boot-samples/spring-boot-sample-web-groovy-templates/src/main/resources/logback.xml
deleted file mode 100644
index 38ed210e2f..0000000000
--- a/spring-boot-samples/spring-boot-sample-web-groovy-templates/src/main/resources/logback.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/spring-boot-samples/spring-boot-sample-web-method-security/src/main/resources/application.properties b/spring-boot-samples/spring-boot-sample-web-method-security/src/main/resources/application.properties
index cce37b52b5..c19741f86f 100644
--- a/spring-boot-samples/spring-boot-sample-web-method-security/src/main/resources/application.properties
+++ b/spring-boot-samples/spring-boot-sample-web-method-security/src/main/resources/application.properties
@@ -1 +1,2 @@
spring.thymeleaf.cache: false
+logging.level.org.springframework.security: INFO
\ No newline at end of file
diff --git a/spring-boot-samples/spring-boot-sample-web-method-security/src/main/resources/logback.xml b/spring-boot-samples/spring-boot-sample-web-method-security/src/main/resources/logback.xml
deleted file mode 100644
index 92ea748a3e..0000000000
--- a/spring-boot-samples/spring-boot-sample-web-method-security/src/main/resources/logback.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
diff --git a/spring-boot-samples/spring-boot-sample-web-secure/src/main/resources/application.properties b/spring-boot-samples/spring-boot-sample-web-secure/src/main/resources/application.properties
index 521ecc4286..f6fecdb8b4 100644
--- a/spring-boot-samples/spring-boot-sample-web-secure/src/main/resources/application.properties
+++ b/spring-boot-samples/spring-boot-sample-web-secure/src/main/resources/application.properties
@@ -1,5 +1,5 @@
spring.thymeleaf.cache: false
-debug: true
security.basic.enabled: false
# demo only:
-security.user.password: password
\ No newline at end of file
+security.user.password: password
+logging.level.org.springframework.security: INFO
\ No newline at end of file
diff --git a/spring-boot-samples/spring-boot-sample-web-secure/src/main/resources/logback.xml b/spring-boot-samples/spring-boot-sample-web-secure/src/main/resources/logback.xml
deleted file mode 100644
index 6173a50684..0000000000
--- a/spring-boot-samples/spring-boot-sample-web-secure/src/main/resources/logback.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
diff --git a/spring-boot/src/main/java/org/springframework/boot/logging/LogLevel.java b/spring-boot/src/main/java/org/springframework/boot/logging/LogLevel.java
index 843cf2d749..1df44cbd30 100644
--- a/spring-boot/src/main/java/org/springframework/boot/logging/LogLevel.java
+++ b/spring-boot/src/main/java/org/springframework/boot/logging/LogLevel.java
@@ -23,6 +23,6 @@ package org.springframework.boot.logging;
*/
public enum LogLevel {
- TRACE, DEBUG, INFO, WARN, ERROR, FATAL
+ TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF
}
diff --git a/spring-boot/src/main/java/org/springframework/boot/logging/LoggingApplicationListener.java b/spring-boot/src/main/java/org/springframework/boot/logging/LoggingApplicationListener.java
index 6b92646461..b2c84c9345 100644
--- a/spring-boot/src/main/java/org/springframework/boot/logging/LoggingApplicationListener.java
+++ b/spring-boot/src/main/java/org/springframework/boot/logging/LoggingApplicationListener.java
@@ -19,11 +19,13 @@ package org.springframework.boot.logging;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.ApplicationPid;
import org.springframework.boot.SpringApplication;
+import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationEvent;
@@ -180,7 +182,6 @@ public class LoggingApplicationListener implements SmartApplicationListener {
try {
ResourceUtils.getURL(value).openStream().close();
system.initialize(value);
- return;
}
catch (Exception ex) {
// Swallow exception and continue
@@ -188,10 +189,31 @@ public class LoggingApplicationListener implements SmartApplicationListener {
this.logger.warn("Logging environment value '" + value
+ "' cannot be opened and will be ignored");
}
+ else {
- system.initialize();
- if (this.springBootLogging != null) {
- initializeLogLevel(system, this.springBootLogging);
+ system.initialize();
+ if (this.springBootLogging != null) {
+ initializeLogLevel(system, this.springBootLogging);
+ }
+
+ }
+
+ setLogLevels(system, environment);
+
+ }
+
+ public void setLogLevels(LoggingSystem system, Environment environment) {
+ Map levels = new RelaxedPropertyResolver(environment)
+ .getSubProperties("logging.level.");
+ for (Entry entry : levels.entrySet()) {
+ try {
+ LogLevel level = LogLevel.valueOf(entry.getValue().toString());
+ system.setLogLevel(entry.getKey(), level);
+ }
+ catch (RuntimeException e) {
+ this.logger.error("Cannot set level: " + entry.getValue() + " for '"
+ + entry.getKey() + "'");
+ }
}
}
diff --git a/spring-boot/src/main/java/org/springframework/boot/logging/java/JavaLoggingSystem.java b/spring-boot/src/main/java/org/springframework/boot/logging/java/JavaLoggingSystem.java
index 4186686670..d9a9b7629f 100644
--- a/spring-boot/src/main/java/org/springframework/boot/logging/java/JavaLoggingSystem.java
+++ b/spring-boot/src/main/java/org/springframework/boot/logging/java/JavaLoggingSystem.java
@@ -47,6 +47,7 @@ public class JavaLoggingSystem extends AbstractLoggingSystem {
levels.put(LogLevel.WARN, Level.WARNING);
levels.put(LogLevel.ERROR, Level.SEVERE);
levels.put(LogLevel.FATAL, Level.SEVERE);
+ levels.put(LogLevel.OFF, Level.OFF);
LEVELS = Collections.unmodifiableMap(levels);
}
diff --git a/spring-boot/src/main/java/org/springframework/boot/logging/log4j/Log4JLoggingSystem.java b/spring-boot/src/main/java/org/springframework/boot/logging/log4j/Log4JLoggingSystem.java
index b054ce8651..256464279e 100644
--- a/spring-boot/src/main/java/org/springframework/boot/logging/log4j/Log4JLoggingSystem.java
+++ b/spring-boot/src/main/java/org/springframework/boot/logging/log4j/Log4JLoggingSystem.java
@@ -49,6 +49,7 @@ public class Log4JLoggingSystem extends AbstractLoggingSystem {
levels.put(LogLevel.WARN, Level.WARN);
levels.put(LogLevel.ERROR, Level.ERROR);
levels.put(LogLevel.FATAL, Level.ERROR);
+ levels.put(LogLevel.OFF, Level.OFF);
LEVELS = Collections.unmodifiableMap(levels);
}
diff --git a/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystem.java b/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystem.java
index 3808ab226e..027002aac6 100644
--- a/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystem.java
+++ b/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystem.java
@@ -55,6 +55,7 @@ public class LogbackLoggingSystem extends AbstractLoggingSystem {
levels.put(LogLevel.WARN, Level.WARN);
levels.put(LogLevel.ERROR, Level.ERROR);
levels.put(LogLevel.FATAL, Level.ERROR);
+ levels.put(LogLevel.OFF, Level.OFF);
LEVELS = Collections.unmodifiableMap(levels);
}
diff --git a/spring-boot/src/test/java/org/springframework/boot/logging/LoggingApplicationListenerTests.java b/spring-boot/src/test/java/org/springframework/boot/logging/LoggingApplicationListenerTests.java
index 38be0ecf5c..35cff97a05 100644
--- a/spring-boot/src/test/java/org/springframework/boot/logging/LoggingApplicationListenerTests.java
+++ b/spring-boot/src/test/java/org/springframework/boot/logging/LoggingApplicationListenerTests.java
@@ -187,6 +187,42 @@ public class LoggingApplicationListenerTests {
assertThat(this.outputCapture.toString(), containsString("testattrace"));
}
+ @Test
+ public void parseLevels() throws Exception {
+ EnvironmentTestUtils.addEnvironment(this.context,
+ "logging.level.org.springframework.boot=TRACE");
+ this.initializer.initialize(this.context.getEnvironment(),
+ this.context.getClassLoader());
+ this.logger.debug("testatdebug");
+ this.logger.trace("testattrace");
+ assertThat(this.outputCapture.toString(), containsString("testatdebug"));
+ assertThat(this.outputCapture.toString(), containsString("testattrace"));
+ }
+
+ @Test
+ public void parseLevelsFails() throws Exception {
+ EnvironmentTestUtils.addEnvironment(this.context,
+ "logging.level.org.springframework.boot=GARBAGE");
+ this.initializer.initialize(this.context.getEnvironment(),
+ this.context.getClassLoader());
+ this.logger.debug("testatdebug");
+ assertThat(this.outputCapture.toString(), not(containsString("testatdebug")));
+ assertThat(this.outputCapture.toString(),
+ containsString("Cannot set level: GARBAGE"));
+ }
+
+ @Test
+ public void parseLevelsNone() throws Exception {
+ EnvironmentTestUtils.addEnvironment(this.context,
+ "logging.level.org.springframework.boot=OFF");
+ this.initializer.initialize(this.context.getEnvironment(),
+ this.context.getClassLoader());
+ this.logger.debug("testatdebug");
+ this.logger.fatal("testatfatal");
+ assertThat(this.outputCapture.toString(), not(containsString("testatdebug")));
+ assertThat(this.outputCapture.toString(), not(containsString("testatfatal")));
+ }
+
@Test
public void parseArgsDisabled() throws Exception {
this.initializer.setParseArgs(false);