Как да замените програмно конфигурацията по подразбиране log4j2?

Днес имам проблем да преконфигурирам правилно конфигурацията на log4j2. За да обясня проблема, създадох примерно приложение, което съответства почти на нашия продуктивен код. Примерната структура на проекта е показана на следната снимка:

въведете описание на изображението тук

За целите на разработчиците искаме да стартираме основното приложение с клас обвивка, за да конфигурираме някакъв параметър като конфигурация на регистриране или системни свойства, които не трябва да се поставят в продуктивния код. Следователно продуктивната конфигурация log4j2 трябва да бъде заменена от тази за разработчици, за да се зададе по-специфично нивото на регистрационния файл и да се избегне добавянето на файлове към записите в журнала. Следва кодът за продуктивния основен клас:

package logging.log4j2;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class MainApp {

    private final Log LOG = LogFactory.getLog(MainApp.class);
    private final String[] commandLineArgs;

    public static void main(String[] args) {
        MainApp app = new MainApp(args);
        app.start();
    }

    protected MainApp(String[] args) {
        commandLineArgs = args;
    }

    public void start() {
        LOG.info("Starting MainApp application ...");

        // ... do main application stuff here
        LOG.debug("This is only for DEBUG mode.");
    }
}

Сега кодът за главния клас на обвивката на разработчиците:

package logging.log4j2;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.net.URL;

public class DevWrapperMainApp extends MainApp {

    private static final Log LOG = LogFactory.getLog(DevWrapperMainApp.class);
    public static final String PROP_LOG4J_CONFIGURATION_FILE = "log4j.configurationFile";

    protected DevWrapperMainApp(String[] args) {
        super(args);
    }

    public static void main(String[] args) {
        preconfigureDevMode();
        DevWrapperMainApp devApp = new DevWrapperMainApp(args);
        devApp.start();
    }

    private static void preconfigureDevMode() {
        LOG.debug("Preconfigure application for deveoper mode ...");
        String log4j2ConfigFilePath =    System.getProperty(PROP_LOG4J_CONFIGURATION_FILE);
        if(log4j2ConfigFilePath == null || log4j2ConfigFilePath.isEmpty()) {
            URL configResource = DevWrapperMainApp.class.getResource("/dev-log4j2.xml");
            if(configResource != null) {
                System.setProperty(PROP_LOG4J_CONFIGURATION_FILE, configResource.toExternalForm());
            } else {
                LOG.error("Set log4j2 configuration file property failed. Resource file could not be detected correctly.");
            }
        }
    }
}

Регистрирането на продуктивното приложение се конфигурира от log4j2.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration name="productiveConfig" status="WARN" monitorInterval="5">
    <properties>
        <property name="log.pattern.layout">%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</property>
    </properties>

    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="${sys:log.pattern.layout}"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="INFO">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

За примерното приложение няма приложение за добавяне на файлове, но нивото на регистриране и името на конфигурацията е различно от следното dev-log4j2.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration name="developerConfig" status="DEBUG" monitorInterval="5">
    <properties>
        <property name="log.pattern.layout">DEV-MODE: %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</property>
    </properties>

    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="${sys:log.pattern.layout}"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="DEBUG">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

Като стартирам класа DevWrapperMainApp, получавам следния резултат:

"C:\Program Files\Java\jdk1.8.0_66\bin\java" ...
11:40:14.553 [main] INFO  logging.log4j2.MainApp - Starting MainApp application ...

Process finished with exit code 0

В допълнение към регистрирането на INFO, очаквах изхода и от регистрирането на DEBUG. Следователно конфигурацията на регистрационния файл изглежда не е преконфигурирана чрез замяна на системното свойство в този момент. Може би е твърде късно и log4j2 вече е конфигуриран от продуктивния конфигурационен файл? Как мога да променя цялата конфигурация в момента на стартиране на моето приложение? В документацията се казва:

Въпреки това, ако се направи опит за регистриране, преди Configurator.initialize() да бъде извикан, тогава конфигурацията по подразбиране ще се използва за тези регистрационни събития. (Част: Преконфигуриране на Log4j с помощта на ConfigurationBuilder с конфигуратора

Може би някой има намек да тръгна в правилната посока? Знам също възможността за създаване на log4j2-test.xml за целите на разработването, но искам да избегна това и да задам системното свойство. Кодът трябва да се знае къде да се намери конфигурационният файл.

Благодаря предварително.

Харди


person Hardie82    schedule 26.07.2016    source източник


Отговори (1)


Log4j 2 поддържа отделна конфигурация за тестване. Можете да имате два конфигурационни файла, един с име log4j2.xml за производство и един с име log4j2-test.xml за тестване. Ако и двете съществуват, Log4j 2 ще използва тестовата конфигурация. В производството просто не внедрявате тестовата конфигурация. Вижте документите за точния ред, в който Log4j 2 се инициализира.

person Remko Popma    schedule 26.07.2016