Log4J2 - 在运行时分配文件附加程序文件名
Posted
技术标签:
【中文标题】Log4J2 - 在运行时分配文件附加程序文件名【英文标题】:Log4J2 - assigning file appender filename at runtime 【发布时间】:2013-01-29 13:02:15 【问题描述】:我在类路径中有一个 log4j2.xml 配置文件。其中一个附加程序是文件附加程序,我想在 Java 应用程序的运行时设置目标文件名。
根据docs,我应该可以在 log4j2.xml 文件中使用双“$”和上下文前缀:
<appenders>
<File name="MyFile" fileName="$$sys:logFilename">
<PatternLayout pattern="%-4r %d$datestamp [%t] %-5level %logger36 - %msg%n"/>
</File>
</appenders>
其中“sys”前缀表示配置器将在系统属性中查找属性“logFilename”。所以在应用程序中,我调用(相当早):
System.setProperty("logFilename", filename);
我还在 xml 文件中开启了 log4j2 的自动重新配置:
<configuration status="debug" monitorInterval="5">>
不幸的是,这没有任何效果,并且永远不会创建日志文件。部分 log4j2 状态输出如下:
2013-02-13 15:36:37,574 调试在类 org.apache.logging.log4j.core.appender.FileAppender 上为元素文件调用 createAppender 参数(fileName="$sys:logFilename", append= “null”,locking="null",name="MyFile",immediateFlush="null",suppressExceptions="null",bufferedIO="null",PatternLayout(%-4r %dyyyy-MM-dd/HH: mm:ss.SSS/zzz [%t] %-5level %logger36 - %msg%n), null)
2013-02-13 15:36:37,576 调试启动文件管理器 $sys:logFilename
如何在运行时设置 File Appender 中“fileName”的值? 或者,如何在运行时简单地将新的 File Appender 添加到根记录器?在 Log4j 2.0 中大部分用于更改配置的 API 都是隐藏的。
【问题讨论】:
进行 SO 搜索。已经回答:***.com/questions/10699358/… 这是一个 Log4j 2.0 的问题,所以 API 与 Log4j 1.2 有很大的不同,之前的答案中的很多方法都没有暴露出来。 【参考方案1】:您可以做的是,在运行应用程序时,将 logFilename
作为参数传递给 JVM:
java -DlogFilename=myAppName.log -jar /path/to/myApp.jar
【讨论】:
【参考方案2】:从 log4j2 版本 2.5 开始,这是实现此目的的最简单方法:
在你的log4j2.xml
:
<Appenders>
<File name="MyFile" filename="$sys:logFilename">
...
在你的主MyApp.java
文件中:
public class MyApp
Logger log;
static
System.setProperty("logFilename", ...);
log = LogManager.getLogger();
public static void main(String... args) ...
CATCH:您应该在加载 log4j2 之前设置 logFilename
系统属性。在这个例子中调用LogManager.getLogger
之前。
【讨论】:
这不行,它只会创建$sys/logFilename
文件
这在我的命令行独立应用程序中对我有用。您可能会遇到问题,因为您依赖的一些其他代码比您想象的更早地初始化了 log4j2。你能描述一下你尝试这个的环境吗?它是 Web 应用程序还是命令行工具?
+1 表示警告!这就是问题所在。我试图这样做,但总是得到第二个空文件$sys/logFilename
。【参考方案3】:
我知道这个话题很老,但答案并不适合我。这是一个允许您在运行时重新配置现有 Appender 的函数:
static void updateLogger(String file_name, String appender_name, String package_name)
LoggerContext context = (LoggerContext) LogManager.getContext(false);
Configuration configuration = context.getConfiguration();
Layout<? extends Serializable> old_layout = configuration.getAppender(appender_name).getLayout();
//delete old appender/logger
configuration.getAppender(appender_name).stop();
configuration.removeLogger(package_name);
//create new appender/logger
LoggerConfig loggerConfig = new LoggerConfig(package_name, Level.INFO, false);
FileAppender appender = FileAppender.createAppender(file_name, "false", "false", appender_name, "true", "true", "true",
"8192", old_layout, null, "false", "", configuration);
appender.start();
loggerConfig.addAppender(appender, Level.INFO, null);
configuration.addLogger(package_name, loggerConfig);
context.updateLoggers();
您可以指定文件名、appender 名称和要记录的包名称。
示例记录器:
<File name="fileWriter_api" fileName="$LOG_DIR/api.log" append="false">
<PatternLayout pattern="$PATTERN"/>
</File>
可以像这样重新配置调用:
updateLogger("log/api_new.log", "fileWriter_api", "my.package");
【讨论】:
这是一个很好的答案! 这适用于命名的附加程序和包,但会停止所有其他附加程序。您是否遇到过这个问题,是否知道如何解决它? 我会省略loggerConfig.addAppender(appender, Level.INFO, null);
行中的 leve.INFO 规范,因为即使您更改记录器的日志级别,它也无法通过此附加程序记录 DEBUG 或 TRACE 事件.
你为我节省了很多时间。谢谢。【参考方案4】:
h/t rgoers FileAppender 不支持文件名上的两个美元符号,因为在启动 appender 时打开了文件。您用两个美元符号表示的是您希望(可能)为每个事件使用不同的文件名。
使用单个 $(如$sys:logFilename
),系统将在系统属性中查找属性“logFilename”。
因此,log4j2.xml 应该有:
<appenders>
<File name="MyFile" fileName="$sys:logFilename">
<PatternLayout pattern="%-4r %d$datestamp [%t] %-5level %logger36 - %msg%n"/>
</File>
</appenders>
Java 应用程序应该设置系统属性:
System.setProperty("logFilename", filename);
和重新配置记录器:
org.apache.logging.log4j.core.LoggerContext ctx =
(org.apache.logging.log4j.core.LoggerContext) LogManager.getContext(false);
ctx.reconfigure();
这会产生所需的行为。
【讨论】:
我不确定这是否是因为 API 已更改,但这对我不起作用。为了让它发挥作用,我必须做的是$sys:logFilename
使用版本 2.0-beta9
和单个 $
这将创建两个文件,一个具有正确名称但内容为空,另一个具有所有日志输出的字面名称为 $sys:logFilename.log
。
LoggerContext.reconfigure
在 log4j2 版本 2.5 中被删除。所以这个方案不能用。
@AlexYursha 我目前正在使用org.apache.logging.log4j:log4j-core:2.6.1
,并且使用该方法没有问题(甚至没有收到弃用警告)。
你可以使用this solution而不依赖log4j2的实现细节。唯一的问题是您必须在记录任何内容之前定义系统属性。以上是关于Log4J2 - 在运行时分配文件附加程序文件名的主要内容,如果未能解决你的问题,请参考以下文章