Creating a Custom Log4j2 Appender – 创建一个自定义的Log4j2 Appender

最后修改: 2018年 8月 2日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.绪论

In this tutorial, we’ll learn about creating a custom Log4j2 appender. If you’re looking for the introduction to Log4j2, please take a look at this article.

在本教程中,我们将学习如何创建一个自定义的Log4j2应用器。如果你正在寻找Log4j2的介绍,请看看这篇文章

Log4j2 ships with a lot of built-in appenders which can be used for various purposes such as logging to a file, to a database, to a socket or to a NoSQL database.

Log4j2带有许多内置的应用程序,可用于各种目的,如记录到文件、数据库、套接字或NoSQL数据库中。

However, there could be a need for a custom appender depending on the application demands.

然而,根据应用需求,可能需要一个定制的应用程序。

Log4j2 is an upgraded version of Log4j and has significant improvements over Log4j. Hence, we’ll be using the Log4j2 framework to demonstrate the creation of a custom appender.

Log4j2是Log4j的升级版,与Log4j相比有很大的改进。因此,我们将使用Log4j2框架来演示创建一个自定义的appender。

2. Maven Setup

2.Maven设置

We will need the log4j-core dependency in our pom.xml to start with:

我们需要在我们的pom.xml中加入log4j-core依赖关系,以便开始使用。

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.11.0</version>
</dependency>

The latest version log4j-core can be found here.

最新版本log4j-core可以在这里找到。

3. Custom Appender

3.自定义应用者

There are two ways by which we can implement our custom appender. First is by implementing the Appender interface and the second is by extending the AbstractAppender class. The second method provides a simple way to implement our own custom appender and that is what we will use.

我们可以通过两种方法来实现我们的自定义Appender。第一种是通过实现Appender接口,第二种是通过扩展AbstractAppender类。第二种方法提供了一种简单的方法来实现我们自己的自定义Appender,这就是我们将使用的方法。

For this example, we’re going to create a MapAppender. We’ll capture the log events and store them in a ConcurrentHashMap with the timestamp for the key.

对于这个例子,我们将创建一个MapAppender。我们将捕获日志事件并将其存储在一个ConcurrentHashMap中,并以时间戳为关键。

Here’s how we create the MapAppender:

下面是我们如何创建MapAppender:

@Plugin(
  name = "MapAppender", 
  category = Core.CATEGORY_NAME, 
  elementType = Appender.ELEMENT_TYPE)
public class MapAppender extends AbstractAppender {

    private ConcurrentMap<String, LogEvent> eventMap = new ConcurrentHashMap<>();

    protected MapAppender(String name, Filter filter) {
        super(name, filter, null);
    }

    @PluginFactory
    public static MapAppender createAppender(
      @PluginAttribute("name") String name, 
      @PluginElement("Filter") Filter filter) {
        return new MapAppender(name, filter);
    }

    @Override
    public void append(LogEvent event) {
        eventMap.put(Instant.now().toString(), event);
    }
}

We’ve annotated the class with the @Plugin annotation which indicates that our appender is a plugin.

我们用 @Plugin 注解了这个类,这表明我们的appender是一个插件。

The name of the plugin signifies the name we would provide in the configuration to use this appender. The category specifies that category under which we place the plugin. The elementType is appender.

插件的name表示我们将在配置中提供的名称,以使用这个appender。category指定了我们放置该插件的类别。elementType是appender。

We also need a factory method that will create the appender. Our createAppender method serves this purpose and is annotated with the @PluginFactory annotation.

我们还需要一个工厂方法来创建appender。我们的createAppender方法就可以达到这个目的,并被注解为@PluginFactory注解。

Here, we initialize our appender by calling the protected constructor and we pass the layout as null as we are not going to provide any layout in the config file and we expect the framework to resolve default layout.

在这里,我们通过调用受保护的构造函数来初始化我们的appender,并且我们将layout传递为null,因为我们不打算在配置文件中提供任何布局,我们希望框架能够解决默认布局。

Next, we’ve overridden the append method which has the actual logic of handling the LogEvent. In our case, the append method puts the LogEvent into our eventMap. 

接下来,我们重载了append方法,它具有处理LogEvent的实际逻辑。在我们的例子中,append方法将LogEvent放入我们的eventMap。

4. Configuration

4.配置

Now that we have our MapAppender in place, we need a lo4j2.xml configuration file to use this appender for our logging.

现在我们有了MapAppender,我们需要一个lo4j2.xml配置文件来使用这个appender进行记录。

Here’s how we define the configuration section in our log4j2.xml file:

下面是我们如何在log4j2.xml文件中定义配置部分。

<Configuration xmlns:xi="http://www.w3.org/2001/XInclude" packages="com.baeldung" status="WARN">

Note that the packages attribute should reference the package that contains your custom appender.

注意,packages属性应该引用包含你的自定义appender的包。

Next, in our appender’s section, we define the appender. Here is how we add our custom appender to the list of appenders in the configuration:

接下来,在我们的appender部分,我们定义appender。下面是我们如何将我们的自定义appender添加到配置中的appender列表中。

<MapAppender name="MapAppender" />

The last part is to actually use the appender in our Loggers section. For our implementation, we use MapAppender as a root logger and define it in the root section.

最后一部分是在我们的Loggers部分实际使用appender。对于我们的实现,我们使用MapAppender作为根记录器并在根部分定义它。

Here’s how it’s done:

这里是如何做到的。

<Root level="DEBUG">
    <AppenderRef ref="MapAppender" />
</Root>

5. Error Handling

5.错误处理

To handle errors while logging the event we can use the error method inherited from AbstractAppender.

为了在记录事件时处理错误,我们可以使用从AbstractAppender.继承的error方法。

For example, if we don’t want to log events which have a log level less than that of WARN.

例如,如果我们不希望记录那些日志级别低于WARN.的事件。

We can use the error method of AbstractAppender to log an error message. Here’s how it’s done in our class:

我们可以使用AbstractAppendererror方法来记录一个错误信息。下面是在我们的类中是如何做的。

public void append(LogEvent event) {
    if (event.getLevel().isLessSpecificThan(Level.WARN)) {
        error("Unable to log less than WARN level.");
        return;
    }
    eventMap.put(Instant.now().toString(), event);
}

Observe how our append method has changed now. We check the event’s level for being greater than WARN and we return early if it is anything less than WARN.

观察一下我们的append方法现在是如何变化的。我们检查event的级别是否大于WARN,如果小于WARN,我们就提前返回。

6. Conclusion

6.结语

In this article, we’ve seen how to implement a custom appender for Log4j2.

在这篇文章中,我们已经看到了如何为Log4j2实现一个自定义的appender。

While there are many in-built ways of logging our data by using Log4j2’s provided appenders, we also have tools in this framework that enable us to create our own appender as per our application needs.

虽然有很多内置的方法可以通过使用Log4j2提供的appender来记录我们的数据,但我们在这个框架中也有一些工具,使我们能够根据我们的应用需求来创建自己的appender。

As usual, the example can be found over on Github.

像往常一样,这个例子可以在Github上找到over