问题描述
我正在使用SystemPropertieslookup查找来配置我的Log4j2配置.系统属性被设置为我的主要方法中的第一行.问题是,当Log4J加载配置时,尚未调用主要方法,因此,系统属性尚未填写.
这是我的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>
该文件将被称为app inspnown nocknown,因为当log4j填写时,这些属性尚未可用.
有没有办法使log4j等待,最好不要将配置移至Java代码?
必须在运行时设置属性(主方法的第一行).
可能的解决方法可能是在该方法之后仅调用getLogger(..),而不是使用变量初始化它,但它并不适合我的任务.
推荐答案
您可以使用RoutingAppender来完成您想做的事情.这是一些示例代码:
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!"); } }
这是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>
在上面运行Java代码在当前工作目录中的日志文件夹中创建一个名为myfile.log的文件.日志文件的内容如下:
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!
问题描述
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.
推荐答案
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!