我正在尝试使用log4j版本2.11.1。 我有可以成功登录到控制台或日志文件的代码。但是,我想从一个开始,然后在代码中途切换到另一个。
https://logging.apache.org/log4j/2.x/manual/customconfig.html下“初始化后以编程方式修改当前配置”下的示例使用了不赞成使用的代码,而我无法找到另一个可用的示例。
for
我希望第一条日志消息在控制台上,第二条日志消息在文件中。 实际结果是所有输出都在控制台上,并且文件为空。
答案 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");
}
}
谢谢! :-)