如何自定义log4j2 RollingFileAppender? [英] How to customize log4j2 RollingFileAppender?

查看:2112
本文介绍了如何自定义log4j2 RollingFileAppender?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们使用log4j 1.2.x登录我们的产品,并希望在不久的将来迁移到log4j 2.x.我们实现的功能之一是在生成的每个新的翻转日志文件上记录系统信息和其他重要参数。我们在log4j 1.2.x中实现的方式是我们扩展了 RollingFileAppender 类的log4j并覆盖了 rollOver()方法,下面是实现的部分片段

We use log4j 1.2.x for logging in our product and are looking to migrate to log4j 2.x in near future. One of the functionality we have implemented is to log the system information and other important parameters on every new roll-over logfile that gets generated. The way we implemented in log4j 1.2.x is that we have extended RollingFileAppender class of log4j and have overridden the rollOver() method, below is the part snippet of the implementation

@Override
public 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

Now as we want to migrate to log4j2 we are looking at a new solution to achieve same functionality. But as I see the source code for log4j2 it is very different from older source code. The RollingFileAppender class does not contain rollover() method as it has been moved to RollingManagerhelper and it has been set to private as-well.

开发一个完整的新包并从log4j2扩展/实现一些抽象/辅助类是我们可能的解决方案之一,但这需要大量编码/复制我们不修改 RollingFileAppender 而不是我们只需要小扩展。有一个简单的解决方案吗?

Developing a complete new package and extending/implementing some abstract/helper classes from log4j2 is one of the possible solution for us but that would require a lot of coding/copying as we do not modify what RollingFileAppender does rather we only need small extension to it. Is there a simple solution to it?

更新

我根据答案中的建议创建了自定义查找以下是我创建它的方式;

I created a custom lookup according to the suggestion in answers and below is how I created it;

@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";

}}

但这并不像上面提到的那样有效;这总是打印这是标题中的第一次调用。我还尝试将breakoint放在第一个 if 条件下,我注意到它只被调用一次。所以我担心的是,当log4j2从xml config初始化其属性时,customLookup类仅在启动时初始化。我不知道我怎么能实现这个自定义查找类。

But this did not work as mentioned; this always prints this was first call in the header. I also tried putting breakoint on the first if condition and what I noticed was that it only gets called once. So what I fear is that the customLookup class only gets initialized on the startup when log4j2 is initialising its properties from xml config. I don't know how else I could implemented this custom lookup class.

更新2

在上面的实现之后,我尝试了不同的方式,如下所示;

After the above implementation I tried it in bit different way which is as below;

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配置文件初始化时创建头,然后使用内存中的头。被重写的 lookup()方法的 return 值无法动态更改,因为它只在初始化期间被调用。任何更多的帮助将受到高度赞赏。

But this does the same thing as-well. log4j2 creates the headers at while initialising from its xml config file and then uses the headers from memory. The return value of overridden lookup() method can not be changed dynamically as it only gets called during initialisation. Any more help would be highly appreciated.

推荐答案

使用内置查找的另一种方法是创建自定义查找。这可以使用log4j2插件在几行代码中完成。然后,您的自定义查找会提供您希望在每次翻转时在文件标题中显示的确切值。

An alternative to using the built-in lookups is to create a custom lookup. This can be accomplished in a few lines of code with a log4j2 plugin. Your custom lookup then provides the exact value you want to show in the file header at each roll over.

插件代码如下所示:

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);
    }
}

然后,在您的配置中,您可以使用标题模式布局在每次翻转时输出:

Then, in your configuration you can use the header of the pattern layout to output this at every rollover:

<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手册中有关于构建/部署自定义插件。简要总结:

The log4j2 manual has details on building/deploying custom plugins. Brief summary:

最简单的方法是使用Maven构建jar;这将导致log4j2注释处理器在jar中生成二进制索引文件,因此log4j2可以快速找到您的插件。

The easiest way is to build your jar with Maven; this will cause the log4j2 annotation processor to produce a binary index file in the jar so your plugin can be found quickly by log4j2.

另一种方法是指定包名称你的log4j2.xml配置中的插件类的属性:

The alternative is to specify the package name of your plugin class in your log4j2.xml configuration's packages attribute:

<Configuration status="warn" packages="com.mycompany">
  ...






更新:注意在您的查找实现中,您可以根据需要获得创意。例如:


UPDATE: Note that in your lookup implementation you can get as creative as necessary. For example:

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?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆