如何自定义log4j2 RollingFileAppender?
我们使用log4j
1.2.x登录我们的产品,并希望在不久的将来迁移到log4j2.x。我们已实现的功能之一是将系统信息和其他重要参数记录在生成的每个新翻转日志文件上。在log4j
1.2.x中实现的方式是扩展RollingFileAppender
了log4j类并覆盖了该rollOver()
方法,下面是实现的部分代码段
@Overridepublic void rollOver() {
super.rollOver(); //We are not modifying it's default functionality but as soon as rollOver happens we apply our logic
//
// Logic to log required system properties and important parameters.
//
}
现在,当我们要迁移到log4j2时,我们正在寻找一种实现相同功能的新解决方案。但是,正如我看到的log4j2的源代码与旧的源代码有很大不同。RollingFileAppender
该类不包含rollover()
方法,因为该方法已移至该方法,RollingManagerhelper
并且已设置为private
as。
开发一个完整的新程序包并从log4j2扩展/实现一些抽象/帮助程序类对我们来说是一种可能的解决方案,但这将需要大量的编码/复制,因为我们不对其进行修改RollingFileAppender
,而只需要对其进行少量扩展即可。有没有简单的解决方案?
我根据答案中的建议创建了一个自定义查找,以下是如何创建它的;
@Plugin(name = "property", category = StrLookup.CATEGORY)public class CustomLookup extends AbstractLookup {
private static AtomicLong aLong = new AtomicLong(0);
@Override
public String lookup(LogEvent event, String key) {
if (aLong.getAndIncrement() == 0) {
return "this was first call";
}
if (key.equalsIgnoreCase("customKey")) {
return getCustomHeader();
} else {
return "non existing key";
}
}
private static String getCustomHeader() {
// Implementation of custom header
return "custom header string";
}}
但是,这没有像前面提到的那样起作用。这总是打印this was first
call在标题中。我还尝试将breakoint置于第一个if
条件,我注意到它只被调用一次。因此,我担心的是,仅当log4j2从xml配置中初始化其属性时,才会在启动时初始化customLookup类。我不知道我还能如何实现这个自定义查找类。
上面的实现后,我尝试了一些不同的方法,如下所示;
private static AtomicLong aLong = new AtomicLong(0);@Override
public String lookup(LogEvent event, String key) {
return getCustomHeader(key);
}
private static String getCustomHeader(final String key) {
if (aLong.getAndIncrement() == 0) {
return "this was first call";
}
if (key.equalsIgnoreCase("customKey")) {
// Implementation for customKey
return "This is custom header";
} else {
return "non existing key";
}
}
但这也做同样的事情。log4j2在从其xml配置文件初始化时在创建标头,然后使用内存中的标头。return
覆盖lookup()
方法的值不能动态更改,因为它仅在初始化期间被调用。任何更多的帮助将不胜感激。
回答:
使用内置查找的一种替代方法是创建自定义查找。使用log4j2插件只需几行代码即可完成。然后,您的自定义查询将提供您希望在每次翻转时在文件头中显示的确切值。
插件代码如下所示:
package com.mycompany;import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.lookup.AbstractLookup;
import org.apache.logging.log4j.core.lookup.StrLookup;
/**
* Looks up keys from a class SomeClass which has access to all
* information you want to provide in the log file header at rollover.
*/
@Plugin(name = "setu", category = StrLookup.CATEGORY)
public class SetuLookup extends AbstractLookup {
/**
* Looks up the value of the specified key by invoking a
* static method on SomeClass.
*
* @param event The current LogEvent (ignored by this StrLookup).
* @param key the key to be looked up, may be null
* @return The value of the specified key.
*/
@Override
public String lookup(final LogEvent event, final String key) {
return com.mycompany.SomeClass.getValue(key);
}
}
然后,在您的配置中,您可以使用模式布局的标题在每次翻转时将其输出:
<RollingFile name="RollingFile" fileName="logs/app.log" filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}.log.gz">
<!-- use custom lookups to access arbitrary internal system info -->
<PatternLayout header="${setu:key1} ${setu:key2}">
<Pattern>%d %m%n</Pattern>
</PatternLayout>
<Policies>
<TimeBasedTriggeringPolicy />
</Policies>
</RollingFile>
log4j2手册详细介绍了如何构建/部署自定义插件。简要摘要:
最简单的方法是使用Maven构建jar。这将导致log4j2注释处理器在jar中生成一个二进制索引文件,因此log4j2可以快速找到您的插件。
替代方法是在log4j2.xml配置的packages
属性中指定插件类的软件包名称:
<Configuration status="warn" packages="com.mycompany"> ...
更新:请注意,在您的查找实现中,您可以根据需要获得创意。例如:
package com.mycompany;public class SomeClass {
private static AtomicLong count = new AtomicLong(0);
public static String getValue(final String key) {
if (count.getAndIncrement() == 0) { // is this the first call?
return ""; // don't output a value at system startup
}
if ("FULL".equals(key)) {
// returns info to shown on rollover, nicely formatted
return fullyFormattedHeader();
}
return singleValue(key);
}
....
}
以上是 如何自定义log4j2 RollingFileAppender? 的全部内容, 来源链接: utcz.com/qa/427305.html