Как переключать программные конфигурации регистрации - PullRequest
0 голосов
/ 03 января 2019

Я пытаюсь использовать log4j версии 2.11.1.У меня есть код, который может успешно войти в консоль или в файл журнала.Тем не менее, я хочу начать с одного и переключиться на другой частично через код.

Пример в https://logging.apache.org/log4j/2.x/manual/customconfig.html в разделе «Программное изменение текущей конфигурации после инициализации» использует устаревший код, и я имеюНе удалось найти другой полезный пример.

public class testLogs {

  protected static Logger logger;

  private static void setupLogging(boolean useConsole) {
    if (useConsole) {
        ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
        builder.setStatusLevel(Level.ERROR);
        builder.setConfigurationName("BuilderTest");
        builder.add(builder.newFilter("ThresholdFilter", Filter.Result.ACCEPT, Filter.Result.NEUTRAL)
                .addAttribute("level", Level.DEBUG));
        AppenderComponentBuilder appenderBuilder = builder.newAppender("Stdout", "CONSOLE").addAttribute("target",
                ConsoleAppender.Target.SYSTEM_OUT);
        appenderBuilder.add(builder.newLayout("PatternLayout")
                .addAttribute("pattern", "%d [%t] %-5level: %msg%n%throwable"));
        appenderBuilder.add(builder.newFilter("MarkerFilter", Filter.Result.DENY, Filter.Result.NEUTRAL)
                .addAttribute("marker", "FLOW"));
        builder.add(appenderBuilder);
        builder.add(builder.newLogger("org.apache.logging.log4j", Level.DEBUG)
                .add(builder.newAppenderRef("Stdout")).addAttribute("additivity", false));
        builder.add(builder.newRootLogger(Level.ERROR).add(builder.newAppenderRef("Stdout")));
        LoggerContext ctx = Configurator.initialize(builder.build());
        ctx.updateLoggers();
    } else {
        // from https://stackoverflow.com/a/34969778/10863944
        ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory
                .newConfigurationBuilder();

        builder.setStatusLevel(Level.ERROR);
        builder.setConfigurationName("RollingBuilder");
        // create the console appender
        AppenderComponentBuilder appenderBuilder = builder.newAppender(
                "Stdout", "CONSOLE").addAttribute("target",
                ConsoleAppender.Target.SYSTEM_OUT);
        appenderBuilder.add(builder.newLayout("PatternLayout").addAttribute(
                "pattern", "%d [%t] %-5level: %msg%n%throwable"));
        builder.add(appenderBuilder);

        LayoutComponentBuilder layoutBuilder = builder.newLayout(
                "PatternLayout").addAttribute("pattern",
                "%d [%t] %-5level: %msg%n");
        @SuppressWarnings("rawtypes")
        ComponentBuilder triggeringPolicy = builder
                .newComponent("Policies")
                .addComponent(
                        builder.newComponent("CronTriggeringPolicy")
                                .addAttribute("schedule", "0 0 0 * * ?"))
                .addComponent(
                        builder.newComponent("SizeBasedTriggeringPolicy")
                                .addAttribute("size", "100M"));
        appenderBuilder = builder
                .newAppender("rolling", "RollingFile")
                .addAttribute("fileName", "logs/mylog.log")
                .addAttribute("filePattern",
                        "logs/mylog-%d{MM-dd-yy}.log.gz").add(layoutBuilder)
                .addComponent(triggeringPolicy);
        builder.add(appenderBuilder);

        // create the new logger
        builder.add(builder.newLogger("TestLogger", Level.DEBUG)
                .add(builder.newAppenderRef("rolling"))
                .addAttribute("additivity", false));

        builder.add(builder.newRootLogger(Level.DEBUG).add(
                builder.newAppenderRef("rolling")));
        LoggerContext ctx = Configurator.initialize(builder.build());
        ctx.updateLoggers();
    }
    logger = LogManager.getLogger();
  }

  public static void main(String[] args) {
    setupLogging(true); // use the console
    logger.info("logging should be on the console");
    setupLogging(false); // do not use the console
    logger.info("logging should be in the log file");
  }

}

Я ожидал, что первое сообщение журнала будет на консоли, а второе сообщение журнала будет в файле.Фактические результаты таковы, что весь вывод находится на консоли, а файл пуст.

Ответы [ 3 ]

0 голосов
/ 04 января 2019

Спасибо @markspace за то, что заставили меня смотреть в правильном направлении.Вот решение, если кому-то еще нужно такое:

public class testLogs {

    protected static Logger logger;
    private static boolean logInitialized = false;

    private static void setupLogging(boolean useConsole) {
        if (logInitialized) {
            LogManager.shutdown();
        }
        if (useConsole) {
            ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
            builder.setStatusLevel(Level.ERROR);
            builder.setConfigurationName("BuilderTest");
            builder.add(builder.newFilter("ThresholdFilter", Filter.Result.ACCEPT, Filter.Result.NEUTRAL)
                    .addAttribute("level", Level.DEBUG));
            AppenderComponentBuilder appenderBuilder = builder.newAppender("Stdout", "CONSOLE").addAttribute("target",
                    ConsoleAppender.Target.SYSTEM_OUT);
            appenderBuilder.add(builder.newLayout("PatternLayout")
                    .addAttribute("pattern", "%d{yyyy/MM/dd HH:mm:ss} %-5level: %msg%n%throwable"));
            appenderBuilder.add(builder.newFilter("MarkerFilter", Filter.Result.DENY, Filter.Result.NEUTRAL)
                    .addAttribute("marker", "FLOW"));
            builder.add(appenderBuilder);
            builder.add(builder.newLogger("org.apache.logging.log4j", Level.DEBUG)
                    .add(builder.newAppenderRef("Stdout")).addAttribute("additivity", false));
            builder.add(builder.newRootLogger(Level.ERROR).add(builder.newAppenderRef("Stdout")));
            LoggerContext ctx = Configurator.initialize(builder.build());
            ctx.updateLoggers();
        } else {
            // from https://stackoverflow.com/a/34969778/10863944
            ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory
                    .newConfigurationBuilder();

            builder.setStatusLevel(Level.ERROR);
            builder.setConfigurationName("RollingBuilder");
            // create the console appender
            AppenderComponentBuilder appenderBuilder = builder.newAppender(
                    "Stdout", "CONSOLE").addAttribute("target",
                    ConsoleAppender.Target.SYSTEM_OUT);
            appenderBuilder.add(builder.newLayout("PatternLayout").addAttribute(
                    "pattern", "%d{yyyy/MM/dd HH:mm:ss} %-5level: %msg%n%throwable"));
            builder.add(appenderBuilder);

            LayoutComponentBuilder layoutBuilder = builder.newLayout(
                    "PatternLayout").addAttribute("pattern",
                    "%d{yyyy/MM/dd HH:mm:ss} %-5level: %msg%n");
            @SuppressWarnings("rawtypes")
            ComponentBuilder triggeringPolicy = builder
                    .newComponent("Policies")
                    .addComponent(
                            builder.newComponent("CronTriggeringPolicy")
                                    .addAttribute("schedule", "0 0 0 * * ?"))
                    .addComponent(
                            builder.newComponent("SizeBasedTriggeringPolicy")
                                    .addAttribute("size", "100M"));
            appenderBuilder = builder
                    .newAppender("rolling", "RollingFile")
                    .addAttribute("fileName", "logs/myfile.log")
                    .addAttribute("filePattern",
                            "logs/myfile-%d{MM-dd-yy}.log.gz").add(layoutBuilder)
                    .addComponent(triggeringPolicy);
            builder.add(appenderBuilder);

            // create the new logger
            builder.add(builder.newLogger("TestLogger", Level.DEBUG)
                    .add(builder.newAppenderRef("rolling"))
                    .addAttribute("additivity", false));

            builder.add(builder.newRootLogger(Level.DEBUG).add(
                    builder.newAppenderRef("rolling")));
            LoggerContext ctx = Configurator.initialize(builder.build());
            ctx.updateLoggers();
        }
        logger = LogManager.getLogger();
        logInitialized = true;
    }

    public static void main(String[] args) {
        setupLogging(true); // use the console
        logger.info("logging should be on the console");
        setupLogging(false); // do not use the console
        logger.info("logging should be in the log file");
    }
}

Спасибо!: -)

0 голосов
/ 10 января 2019

Из комментариев я понимаю, что желаемый результат следующий:

Возможно, пользователь запустил мою программу из неправильного каталога, и в этом случае я проверяю это и не хочуфайл журнала создан.В этом случае я хочу, чтобы регистрация шла на консоль.После того, как все настройки проверены и завершены, я хочу войти в соответствующий файл.

Основная причина , а не , чтобы пойти с программным решением, заключается в том, что он делает ваш кодзависит от деталей реализации log4j2.Если позднее реализация изменится и вы захотите использовать последнюю версию log4j2, ваш код также должен измениться.Это делает обновление до новой версии log4j2 более трудным и более трудоемким для вас.

Вместо программного изменения конфигурации вы можете использовать RoutingAppender , аналогично тому, как это используется в одном изпримеры на странице часто задаваемых вопросов log4j2 .Таким образом, вы используете функции, предназначенные для публичного использования.На ваш код не влияет внутренняя реализация log4j2, потому что вы просто используете предоставленный общедоступный интерфейс.

Вот пример кода Java, который генерирует сообщения журнала:

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;

public class Log4j2DiffAppenderPerCtxVarMain {
    private static final Logger LOG = LogManager.getLogger();

    public static void main(String[] args){

        //This is before validation
        LOG.info("This should appear in console only.");

        //Check if everything is valid then add the routing key
        ThreadContext.put("ROUTINGKEY", "anyValueYouWant");
        LOG.info("This should appear in the log file");
    }
}

Вотфайл конфигурации log4j2:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Routing name="myAppender">
            <Routes pattern="$${ctx:ROUTINGKEY}">

                <!-- This route is chosen if ThreadContext has no value for key ROUTINGKEY. -->
                <Route key="$${ctx:ROUTINGKEY}">
                    <Console name="Console" target="SYSTEM_OUT">
                        <PatternLayout
                            pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
                    </Console>
                </Route>

                <!-- This route is chosen if ThreadContext has a value for ROUTINGKEY -->
                <Route>
                    <RollingFile name="RollingLog" fileName="myLogFile.log"
                        filePattern="%d{yyyy-MM-dd}-%i.log.gz">
                        <PatternLayout
                            pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
                        <Policies>
                            <TimeBasedTriggeringPolicy interval="6"
                                modulate="true" />
                            <SizeBasedTriggeringPolicy size="10 MB" />
                        </Policies>
                    </RollingFile>
                </Route>
            </Routes>
        </Routing>
    </Appenders>
    <Loggers>
        <Root level="trace">
            <AppenderRef ref="myAppender" />
        </Root>
    </Loggers>
</Configuration>

Результатом вышеизложенного является то, что первое сообщение журнала отображается только в консоли, как и ожидалось, а второе - только в файле журнала.

Надеюсь, это поможет!

0 голосов
/ 04 января 2019

Я не знаю, что все это вы делаете, но все, что вы хотите сделать из вашего описания, может быть сделано с помощью этих простых шагов,

// File Appender setup
FileAppender fileAppender = new FileAppender();
fileAppender.setName("filelogging");
fileAppender.setFile("filelogging.log");
fileAppender.setLayout(new PatternLayout("%d %-5p [%c{1}] %m%n"));
fileAppender.setAppend(true);
fileAppender.activateOptions();

// add appender
Logger.getLogger("filelogging").addAppender(fileAppender);
// get instance of logger
Logger fileLogger = Logger.getLogger("filelogging");

// Console Appender setup
ConsoleAppender consoleAppender = new ConsoleAppender();
consoleAppender.setLayout(new PatternLayout("%d %-5p [%c{1}] %m%n"));
consoleAppender.activateOptions();

// add appender
Logger.getLogger("console").addAppender(consoleAppender);
// get instance of logger
Logger consoleLogger = Logger.getLogger("console");

// use
fileLogger.warn("Hey this will print in file.");
consoleLogger.warn("Hey this will print in console.");

В конце мы успешно настроили два регистратора.И по их определенному имени вы можете использовать их для переключения туда и обратно, куда хотите.

Спасибо.

...