Spring boot configuration log4j2 climbing pit

Version Springboot 2.11.1

logging.config parameter

logging.config configuration is valid in application.yml, and the specified path is valid

log4j2

log4j2 official website supports multiple automatic configuration modes, automatic scanning:

System properties (log4j. Configuration) - > in classpath (log4j2 test. Properties)
->In classpath (log4j2-test.yml/yaml/json/jsn/xml)
->In classpath (log4j2. YML / yaml / JSON / JSN / XML) - > default configuration

Log4j get ConfigurationFactory
// Get the ConfigurationFactory according to the test prefix log4j2 test and LoggerContext context context instance
Configuration config = getConfiguration(loggerContext, true, name);
if (config == null) {
    // Get the ConfigurationFactory according to the test prefix log4j2 test
    config = getConfiguration(loggerContext, true, null);
    if (config == null) {
        // Get the ConfigurationFactory according to the prefix log4j2 and LoggerContext context context instance
        config = getConfiguration(loggerContext, false, name);
        if (config == null) {
            // Get the ConfigurationFactory according to the prefix log4j2
            // The factory instance of spring boot loading Log4j2 is obtained here, pointing to the spring boot configuration factory in the spring boot package log4j2.springboot
            config = getConfiguration(loggerContext, false, null);
        }
    }
}
log4j2

The core code is as follows:


String ALL_TYPES = "*";
for (final ConfigurationFactory factory : getFactories()) {
    final String[] types = factory.getSupportedTypes();
    if (types != null) {
        for (final String type : types) {
            // Only XmlConfigurationFactory is eligible
            if (type.equals(ALL_TYPES)) {
                final Configuration config = factory.getConfiguration(loggerContext, name, configLocation);
                if (config != null) {
                    return config;
                }
            }
        }
    }
}
springboot logging

springboot uses the Common logging component to load the log module. It provides the default configuration of Java Util, Log4J2 and Logback logs. It configures the console output in advance and provides optional file output.

springboot default log profile

Logging System Customization
Logback logback-spring.xml, logback-spring.groovy, logback.xml, or logback.groovy
Log4j2 log4j2-spring.xml or log4j2.xml
JDK (Java Util Logging) logging.properties
Springboot log4j2 configuration factory

log4j2 loads the ConfigurationFactory inheritance class in log4j core. The order is as follows:

  • PropertiesConfigurationFactory
  • YamlConfigurationFactory
  • JsonConfigurationFactory
  • XmlConfigurationFactory
  • SpringBootConfigurationFactory (match. springboot)

The name of log4j2.xml is modified in springboot and does not take effect

The log4j2.xml file is modified to log4j2_dev.xml, and the logging.config path is specified in the application_dev.yml configuration file, but the result is still the spring default configuration.

Reason explanation
  1. Reading order of spring boot log4j2: logging.config - > classpath (log4j2-spring.xml or log4j2. XML) - > logging.log4j.log4j2.xml under spring boot package
  2. There is a log configuration file by default in the springboot project. When the project is started, the default log configuration file is read first, and the configuration file in the resource directory is not read. If you need to customize the log information, you need to specify to read the customized configuration file in the springboot configuration file
Unable to read Yml configuration reason
  1. When loading Log4J2, the ObjectMapper, JsonNode, JsonParser and YAMLFactory in jackson will be checked. Loading YAMLFactory will fail, so the yml file configured by yml cannot be parsed, resulting in failure
public class YamlConfigurationFactory extends ConfigurationFactory {

    /**
     * The file extensions supported by this factory.
     */
    private static final String[] SUFFIXES = new String[] {".yml", ".yaml"};

    private static final String[] dependencies = new String[] {
            "com.fasterxml.jackson.databind.ObjectMapper",
            "com.fasterxml.jackson.databind.JsonNode",
            "com.fasterxml.jackson.core.JsonParser",
            "com.fasterxml.jackson.dataformat.yaml.YAMLFactory"
    };

    private final boolean isActive;

    public YamlConfigurationFactory() {
        for (final String dependency : dependencies) {
            if (!Loader.isClassAvailable(dependency)) {
                LOGGER.debug("Missing dependencies for Yaml support, ConfigurationFactory {} is inactive", getClass().getName());
                isActive = false;
                return;
            }
        }
        isActive = true;
    }
During the test

Writing the logging.config configuration to application.yml found that the configuration location can be read


public class LoggingApplicationListener{
    // logFile specifies the log file output location
    private void initializeSystem(ConfigurableEnvironment environment,
                LoggingSystem system, LogFile logFile) {
            LoggingInitializationContext initializationContext = new LoggingInitializationContext(
                    environment);
            // Configuration can be read
            String logConfig = environment.getProperty(CONFIG_PROPERTY);
            if (ignoreLogConfig(logConfig)) {
                system.initialize(initializationContext, null, logFile);
            }
            ...
        }
}
Spring supports the code of Log4j2 default configuration
public abstract class AbstractLoggingSystem extends LoggingSystem {
    // Log4j initialization
    public void initialize(LoggingInitializationContext initializationContext,
            String configLocation, LogFile logFile) {
        if (StringUtils.hasLength(configLocation)) {
            
            initializeWithSpecificConfig(initializationContext, configLocation, logFile);
            return;
        }
        // No configuration, call default configuration
        initializeWithConventions(initializationContext, logFile);
    }



    private String[] getCurrentlySupportedConfigLocations() {
        List<String> supportedConfigLocations = new ArrayList<>();
        if (isClassAvailable("com.fasterxml.jackson.dataformat.yaml.YAMLParser")) {
            Collections.addAll(supportedConfigLocations, "log4j2.yaml", "log4j2.yml");
        }
        if (isClassAvailable("com.fasterxml.jackson.databind.ObjectMapper")) {
            Collections.addAll(supportedConfigLocations, "log4j2.json", "log4j2.jsn");
        }
        supportedConfigLocations.add("log4j2.xml");
        return StringUtils.toStringArray(supportedConfigLocations);
    }
    
    protected String[] getSpringConfigLocations() {
        String[] locations = getStandardConfigLocations();
        for (int i = 0; i < locations.length; i++) {
            String extension = StringUtils.getFilenameExtension(locations[i]);
            locations[i] = locations[i].substring(0,
                    locations[i].length() - extension.length() - 1) + "-spring."
                    + extension;
        }
        return locations;
    }
}
Spring final configuration file location

Spring looks up the configuration file under the classpath path through the default configuration. If it is not found, it will load the logging.log4j.log4j2.xml under the spring boot package. If the log output location is configured, it will be log4j2-file.xml

Tags: Java xml Spring SpringBoot log4j

Posted on Tue, 28 Apr 2020 19:35:37 -0700 by mospeed