Hi,

We have a Spring boot application deployed into a tomcat instance. A tomcat instance can contain multiple webapp instances. We noticed that Spring Boot logger system was setting system properties using System.setProperty in LoggingSystemProperties. This is very bad in our case since a system property is global to the JVM and therefore to all deployed web applications.

This looks like a major bug to us. Is there at least a way to disable LoggingApplicationListener?

Comment From: wilkinsona

How are you configuring logging in your Spring Boot applications and which logging-related system properties are problematic?

Comment From: spring-projects-issues

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

Comment From: reda-alaoui

Hi @wilkinsona ,

We use logback.

Here is what I found inside org.springframework.boot.logging.LoggingSystemProperties:

public void apply(LogFile logFile) {
        PropertyResolver resolver = getPropertyResolver();
        setSystemProperty(resolver, EXCEPTION_CONVERSION_WORD, "exception-conversion-word");
        setSystemProperty(PID_KEY, new ApplicationPid().toString());
        setSystemProperty(resolver, CONSOLE_LOG_PATTERN, "pattern.console");
        setSystemProperty(resolver, FILE_LOG_PATTERN, "pattern.file");
        setSystemProperty(resolver, FILE_CLEAN_HISTORY_ON_START, "file.clean-history-on-start");
        setSystemProperty(resolver, FILE_MAX_HISTORY, "file.max-history");
        setSystemProperty(resolver, FILE_MAX_SIZE, "file.max-size");
        setSystemProperty(resolver, FILE_TOTAL_SIZE_CAP, "file.total-size-cap");
        setSystemProperty(resolver, LOG_LEVEL_PATTERN, "pattern.level");
        setSystemProperty(resolver, LOG_DATEFORMAT_PATTERN, "pattern.dateformat");
        setSystemProperty(resolver, ROLLING_FILE_NAME_PATTERN, "pattern.rolling-file-name");
        if (logFile != null) {
            logFile.applyToSystemProperties();
        }
    }

    private PropertyResolver getPropertyResolver() {
        if (this.environment instanceof ConfigurableEnvironment) {
            PropertySourcesPropertyResolver resolver = new PropertySourcesPropertyResolver(
                    ((ConfigurableEnvironment) this.environment).getPropertySources());
            resolver.setIgnoreUnresolvableNestedPlaceholders(true);
            return resolver;
        }
        return this.environment;
    }

    private void setSystemProperty(PropertyResolver resolver, String systemPropertyName, String propertyName) {
        setSystemProperty(systemPropertyName, resolver.getProperty("logging." + propertyName));
    }

    private void setSystemProperty(String name, String value) {
        if (System.getProperty(name) == null && value != null) {
            System.setProperty(name, value);
        }
    }

All these values act as global values. On one Tomcat instance, we cannot configure one value per property and per Spring boot application.

Comment From: wilkinsona

Thanks for the additional information. I asked how you were configuring logging and you didn't directly answer that. From the above, it sounds like you're using the logging.* properties to do so. This contradicts your suggestion to provide a way to disable LoggingApplicationListener as doing so would make all logging.* properties ineffective.

Given the documented behaviour of logging.* properties being transferred from the Spring environment to System properties, I don't think you should use them. You'd also have to stop using them if it was possible to disable LoggingApplicationListener and you had done so due to the becoming ineffective. Instead, I would recommend using logback.xml to configure each application's logging.

We can also consider an enhancement to disable the transfer of the logging.* properties from the Spring environment to system properties, while leaving the rest of LoggingApplicationListener's functionality intact.

Comment From: reda-alaoui

Thanks for the additional information. I asked how you were configuring logging and you didn't directly answer that. From the above, it sounds like you're using the logging.* properties to do so.

No we don't. We use a logback xml file with a custom name because we need to boot logback with the webapp context path as a variable. This variable allows logback to send a webapp logs to a directory named as the webapp context path.

We have now been using the following for years to prevent Spring Boot logging from kicking off:

public class App extends SpringBootServletInitializer {

  // ...

  @Override
  protected WebApplicationContext run(SpringApplication application) {
    List<ApplicationListener<?>> filteredListeners =
        application.getListeners().stream()
            .filter(
                // Spring Boot logging configuration does not support multi applications JVM
                // See https://github.com/spring-projects/spring-boot/issues/20304
                // We exclude it
                applicationListener -> !(applicationListener instanceof LoggingApplicationListener))
            .filter(
                applicationListener ->
                    !(applicationListener instanceof LoggingSystemShutdownListener))
            .collect(Collectors.toList());

    application.setListeners(filteredListeners);
    return super.run(application);
  }

  // ...
}