OrangeDog
OrangeDog

Reputation: 38777

How to set Spring Boot's logging levels programmatically?

I know how to set the log level via environment variables and application properties.

Is there a way to set them programmatically?

I would like to set log levels for particular test classes (which are using SpringJUnit4ClassRunner and @SpringApplicationConfiguration), but not all of them, and without having a separate properties file for every combination.

I tried defining a non-lazy bean to add a new PropertySource to the environment; the method was called but it had no effect.

@Bean
@Lazy(false)
public PropertySource testProperties(ConfigurableEnvironment environment) {
  PropertySource properties = new MapPropertySource("testProperties", Collections.singletonMap(
      "logging.level.org.springframework.security", "DEBUG"
  ));

  environment.getPropertySources().addFirst(properties);
  return properties;
}

Upvotes: 4

Views: 7198

Answers (2)

OrangeDog
OrangeDog

Reputation: 38777

Credit to Boris the Spider for the hints.

First, add an element <jmxConfigurator /> to the logback.xml.

Then, this code will work:

@Before
public void configureLogging() throws JMException {
    ObjectName name = new ObjectName(String.format("ch.qos.logback.classic:Name=default,Type=%s", JMXConfigurator.class.getName()));
    JMXConfiguratorMBean logbackMBean = JMX.newMBeanProxy(ManagementFactory.getPlatformMBeanServer(), name, JMXConfiguratorMBean.class);
    logbackMBean.setLoggerLevel("org.springframework.security", "DEBUG");
}

Sadly, there doesn't appear to be a better way to build the object name: the Package hierarchy isn't traversable and the string "default" isn't accessible anywhere I can find.

Upvotes: 1

Andy Wilkinson
Andy Wilkinson

Reputation: 116091

You can use @TestPropertySource on your test classes. Unlike the bean-based approach that you tried, @TestPropertySource will add the property source to the environment before the context starts which allows the properties to be picked up when the logging system is initialized.

Something like this:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(YourApplication.class)
@TestPropertySource(properties = "logging.level.org.springframework.security:DEBUG")
public class YourApplicationTests {
    // …
}

Upvotes: 5

Related Questions