如何切换编程日志记录配置

时间:2019-01-03 19:46:58

标签: java log4j2

我正在尝试使用log4j版本2.11.1。 我有可以成功登录到控制台或日志文件的代码。但是,我想从一个开始,然后在代码中途切换到另一个。

https://logging.apache.org/log4j/2.x/manual/customconfig.html下“初始化后以编程方式修改当前配置”下的示例使用了不赞成使用的代码,而我无法找到另一个可用的示例。

for

我希望第一条日志消息在控制台上,第二条日志消息在文件中。 实际结果是所有输出都在控制台上,并且文件为空。

3 个答案:

答案 0 :(得分:0)

根据评论,我的理解是以下是您想要的结果:

  

用户可能从错误的目录启动了我的程序,其中   情况下,我对此进行了测试,并且不希望创建日志文件。在那里面   的情况下,我希望日志记录转到控制台。完成所有设置后   验证并完成后,我希望日志记录转到相应的文件。

不采用编程解决方案的主要原因是,它使您的代码依赖于log4j2实现细节。如果稍后实现上的更改并且您希望使用log4j2的最新版本,则您的代码也必须更改。这使得升级到较新版本的log4j2更加困难,为您带来更多工作。

您可以使用RoutingAppender而不是通过编程方式更改配置,类似于在one of the examples上的log4j2 FAQ page中使用它。这样,您就可以使用供公众使用的功能。您的代码不受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>

上面的结果是,第一条日志消息仅按预期方式出现在控制台中,第二条消息仅出现在日志文件中。

我希望这会有所帮助!

答案 1 :(得分:-1)

我不知道您正在做什么,但是您可以通过以下简单步骤完成描述中的所有操作

// 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.");

最后,我们已经成功设置了两个记录器,并且通过它们的定义名称,您可以使用它们在任意位置来回切换。

谢谢。

答案 2 :(得分:-1)

感谢@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");
    }
}

谢谢! :-)