问题
I am using the SystemPropertiesLookup lookup to configure my Log4J2 configuration. The system properties get set as the first line in my main method. The problem is that, when Log4J loads the configuration, the main method is not yet called, and so, the system properties are not yet filled in.
Here is my log4j2.xml:
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="WARN" packages="org.base">
<appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%highlight{%d [%c{1}] %-5level: %msg%n}{STYLE=Logback}"/>
</Console>
<File name="AppLog" fileName="logs/app-${sys:MIGRATION_ENV:-UNKNOWN}-${sys:MIGRATION_TITLE:-UNKNOWN}.log" append="false">
<PatternLayout pattern="%d [%c{1}] %-5level: %msg%n"/>
</File>
</appenders>
<loggers>
<root level="error">
<appender-ref ref="Console" level="error"/>
<appender-ref ref="AppLog" level="error"/>
</root>
<logger name="org.base" level="debug" additivity="false">
<appender-ref ref="Console" level="debug"/>
<appender-ref ref="AppLog" level="debug"/>
</logger>
</loggers>
</configuration>
The file will be called app-UNKNOWN-UNKNOWN because when Log4J fills it in, the properties are not yet available.
Is there a way to make Log4J wait, preferrably without moving configuration to Java code?
The properties must be set during runtime (the first line of the main method).
A possible fix could be to only call getLogger(..)
AFTER that method, instead of initializing it with the variable, but it doesn't really fit into my task.
回答1:
You can do what you want by using the RoutingAppender
. Here is some sample code:
package example;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class SomeClass {
private static final Logger log = LogManager.getLogger();
public static void main(String[] args){
System.setProperty("myProperty", "myFile.log");
if(log.isDebugEnabled())
log.debug("This is some debug!");
log.info("Here's some info!");
log.error("Some erorr happened!");
}
}
Here is the log4j2.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
</Console>
<Routing name="Routing">
<Routes pattern="$${sys:myProperty}">
<Route>
<File name="File" fileName="logs/${sys:myProperty}"
immediateFlush="false" append="false">
<PatternLayout
pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
</File>
</Route>
</Routes>
</Routing>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="Console" level="debug" />
<AppenderRef ref="Routing" level="debug" />
</Root>
</Loggers>
</Configuration>
Running the java code above creates a file called myFile.log in a logs folder within the current working directory. The content of the log file is something like the following:
2018-05-21 22:13:29.147 [main] DEBUG example.SomeClass - This is some debug!
2018-05-21 22:13:29.160 [main] INFO example.SomeClass - Here's some info!
2018-05-21 22:13:29.161 [main] ERROR example.SomeClass - Some erorr happened!
来源:https://stackoverflow.com/questions/50405298/log4j-2-lookup-values-are-used-in-config-before-they-are-loaded-present