Appenders

Appenders are responsible for delivering log events to their destination. Every Appender must implement the Appender interface.

While not strictly required by the Log4j Core architecture, most appenders inherit from AbstractAppender and:

  • delegate the filtering of log events to an implementation of Filter. See Filters for more information.

  • delegate the formatting of log events to an implementation of Layout. See Layouts for more information.

  • only directly handle the writing of log event data to the target destination.

Appenders always have a name so that they can be referenced from a logger configuration.

Common concerns

Buffering

Appenders that use stream-like resources (such as files, TCP connections) have an internal ByteBuffer that can be used to format each log event, before sending it to the underlying resource. The buffer is used if:

The buffer is flushed to the underlying resource on three occasions:

These configuration attributes are shared by multiple appenders:

bufferSize

Type

int

Default value

log4j2.encoderByteBufferSize

This configuration attribute specifies the size of the ByteBuffer used by the appender.

bufferedIo

Type

boolean

Default value

true

If set to true, Log4j Core will use an internal ByteBuffer to store log events before sending them.

If the log4j2.enableDirectEncoders configuration property is set to true, the internal ByteBuffer will always be used.

immediateFlush

Type

boolean

Default value

true

If set to true, Log4j will flush Log4j Core and Java buffers at the end of each event:

  • the internal ByteBuffer of the appender will be flushed.

  • for appenders based on Java’s OutputStream a call to the OutputStream.flush() method will be performed.

This setting only guarantees that a byte representation of the log event is passed to the operating system. It does not ensure that the operating system writes the event to the underlying storage.

If you are using asynchronous loggers or appenders, you can set this attribute to false. Log4j Core will still flush the internal buffer whenever the log event queue becomes empty.

Exception handling

By default, Log4j Core uses Status Logger to report exceptions that occur in appenders. This behavior can be changed using the following configuration property:

ignoreExceptions

Type

boolean

Default value

true

If false logging exceptions will be forwarded to the caller. Otherwise, they will be logged using Status Logger.

If logging is important for your business, consider using a Failover Appender to redirect log events to a different appender in case of exceptions.

Runtime evaluation of attributes

The following configuration attributes are also evaluated at runtime, so can contain escaped $${...} property substitution expressions.

Table 1. List of attributes evaluated at runtime
Component Parameter Event type Evaluation context

HTTP Appender

Property/value

Log event

global

Kafka Appender

key

Log event

global

NoSQL Appender

KeyValuePair/value

Log event

global

PropertiesRewrite Policy

Property/value

Log event

global

Routes Container

pattern

Log event

log event

Rolling File Appenders

filePattern

Rollover

global

Optional Rollover Actions

basePath

Rollover

global

The Route component of the Routing Appender is special: its children are evaluated at runtime, but they are not evaluated at configuration time. Inside the Route component you should not use escaped $${...} property substitution expressions, but only unescaped ${...} property substitution expressions.

See runtime property substitution for more details.

Collection

Log4j bundles several predefined appenders to assist in several common deployment use cases. They are documented in separate pages based on their target resource:

Console Appender

As one might expect, the Console Appender writes its output to either the standard output or standard error output. The appender supports four different ways to access the output streams:

direct

This mode gives the best performance. It can be enabled by setting the direct attribute to true.

default

By default, the Console appender uses the values of System.out or System.err present at configuration time. Any changes to those streams at runtime will be ignored.

follow

This mode always uses the current value of the System.out and System.err streams. It can be enabled by setting the follow attribute to true.

This setting might be useful in multi-application environments. Some application servers modify System.out and System.err to always point to the currently running application.

JANSI

If the application is running on Windows and the JANSI library is available, the Console appender will use JANSI to emulate ANSI sequence support. This mode can be disabled by setting the log4j2.skipJansi configuration attribute to true.

Additional runtime dependencies are required to use JANSI:

  • Maven

  • Gradle

<dependency>
  <groupId>org.fusesource.jansi</groupId>
  <artifactId>jansi</artifactId>
  <version>1.18</version>
</dependency>
runtimeOnly 'org.fusesource.jansi:jansi:1.18'
Table 2. Console Appender configuration attributes
Attribute Type Default value Description

Required

name

String

The name of the appender.

Optional

bufferSize

int

8192

The size of the ByteBuffer internally used by the appender.

See Buffering for more details.

direct

boolean

false

If set to true, log events will be written directly to either FileDescriptor.out or FileDescriptor.err.

This setting bypasses the buffering of System.out and System.err and might provide a performance comparable to a file appender.

If other logging backends or the application itself uses System.out/System.err, setting this to true might cause interleaved output.

This setting is incompatible with the follow attribute and JANSI support.

follow

boolean

false

If set to true, the appender will honor reassignments of System.out (resp. System.err) via System.setOut (resp. System.setErr).

Otherwise, the value of System.out (resp. System.err) at configuration time will be used.

This setting is incompatible with the direct attribute and JANSI support.

ignoreExceptions

boolean

true

If false, logging exception will be forwarded to the caller of the logging statement. Otherwise, they will be ignored.

Logging exceptions are always also logged to Status Logger

immediateFlush

boolean

true

If set to true, the appender will flush its internal buffer and the buffer of the System.out/System.err stream after each log event.

See Buffering for more details.

target

Target

SYSTEM_OUT

It specifies which standard output stream to use:

SYSTEM_OUT

It uses the standard output.

SYSTEM_ERR

It uses the standard error output.

Table 3. Common nested elements

Type

Multiplicity

Description

Filter

zero or one

Allows filtering log events just before they are formatted and sent.

See also appender filtering stage.

Layout

zero or one

Formats log events.

See Layouts for more information.

Configuration examples

A typical configuration in a development environment might look like:

  • XML

  • JSON

  • YAML

  • Properties

Snippet from an example log4j2.xml
<Console name="CONSOLE">
  <PatternLayout pattern="%d [%t] %p %c - %m%n"/>
</Console>
Snippet from an example log4j2.json
"Console": {
  "name": "CONSOLE",
  "PatternLayout": {
    "pattern": "%d [%t] %p %c - %m%n"
  }
}
Snippet from an example log4j2.yaml
Console:
  name: "CONSOLE"
  PatternLayout:
    pattern: "%d [%t] %p %c - %m%n"
Snippet from an example log4j2.properties
appender.0.type = Console
appender.0.name = CONSOLE

appender.0.layout.type = PatternLayout
appender.0.layout.pattern = %d [%t] %p %c - %m%n

A typical configuration for a production environment might look like

  • XML

  • JSON

  • YAML

  • Properties

Snippet from an example log4j2.xml
<Console name="CONSOLE"
         direct="true"> (1)
  <JsonTemplateLayout/> (2)
</Console>
Snippet from an example log4j2.json
"Console": {
  "name": "CONSOLE",
  "direct": true, (1)
  "JsonTemplateLayout": {} (2)
}
Snippet from an example log4j2.yaml
Console:
  name: "CONSOLE"
  direct: true (1)
  JsonTemplateLayout: {} (2)
Snippet from an example log4j2.properties
appender.0.type = Console
appender.0.name = CONSOLE
(1)
appender.0.direct = true

(2)
appender.0.layout.type = JsonTemplateLayout
1 Improve performance by setting direct to true.
2 Use a structured layout. Additional dependencies are required, see JSON Template Layout.

File appenders

File appenders write logs to the filesystem. They can be further split into:

Single file appenders

See File appenders for details.

Rolling file appenders

See Rolling file appenders for details.

Database appenders

The appenders write log events directly to a database.

Cassandra appender

Sends log events to Apache Cassandra

JDBC appender

Sends log events to a JDBC driver

JPA appender

Uses Jakarta Persistence API to deliver log events to a database

NoSQL appender

Store log events to a document-oriented database

See Database appenders for details.

Network appenders

These appenders use simple network protocols to transmit log events to a remote host. The supported network protocols are:

UDP
TCP

These are handled by the Socket Appender.

HTTP

This is handled by the HTTP Appender.

SMTP

This is handled by the SMTP Appender.

See Network Appenders for details.

Message queue appenders

Message queue appenders forward log events to a message broker. The following systems are supported:

Flume appender

Forwards log events to an Apache Flume server.

JMS appender

Forwards log events to a Jakarta Message 2.0 broker.

Kafka appender

Forwards log events to an Apache Kafka server.

ZeroMQ/JeroMQ appender

Forwards log events to a ZeroMQ broker.

See Message queue appenders for details.

Servlet Appender

The Servlet appender allows users to forward all logging calls to the ServletContext.log() methods.

The ServletContext.log(String, Throwable) method predates modern logging APIs. By using Servlet appender, you typically will not be able to differentiate log events by log level or logger name.

The Servlet Appender has no configuration attributes.

You can use it by declaring an appender of type Servlet in your configuration file:

  • XML

  • JSON

  • YAML

  • Properties

<Servlet name="SERVLET">
  <PatternLayout pattern="%m%n" alwaysWriteExceptions="false"/> (1)
</Servlet>
"Servlet": {
  "name": "SERVLET",
  "PatternLayout": {
    "pattern": "%m%n",
    "alwaysWriteExceptions": false (1)
  }
}
Servlet:
  name: "SERVLET"
  PatternLayout:
    pattern: "%m%n"
    alwaysWriteExceptions: false (1)
appender.0.type = Servlet
appender.0.name = SERVLET
appender.0.layout.type = PatternLayout
appender.0.layout.pattern = %m%n
(1)
appender.0.layout.alwaysWriteExceptions = false
1 Encodes events using Pattern Layout and forwards the call to ServletContext.log(). Setting alwaysWriteExceptions to false prevents the stacktrace from appearing as both part of the message argument and as throwable argument: this usually results in the stacktrace being printed to the log file twice.

Additional runtime dependencies are required for using the servlet appender:

  • Maven

  • Gradle

We assume you use log4j-bom for dependency management.

<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-jakarta-web</artifactId>
  <scope>runtime</scope>
</dependency>

We assume you use log4j-bom for dependency management.

runtimeOnly 'org.apache.logging.log4j:log4j-jakarta-web'
Click here if you are you using Jakarta EE 8 or any version of Java EE?

Jakarta EE 8 and all Java EE applications servers use the legacy javax package prefix instead of jakarta. If you are using those application servers, you should replace the dependencies above with:

  • Maven

  • Gradle

We assume you use log4j-bom for dependency management.

<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-web</artifactId>
  <scope>runtime</scope>
</dependency>

We assume you use log4j-bom for dependency management.

runtimeOnly 'org.apache.logging.log4j:log4j-web'

See Integrating with Jakarta EE for more information.

Delegating appenders

Delegating appenders are intended to decorate other appenders:

Asynchronous appender

Perform all I/O on a dedicated thread

Failover appender

Provide a backup appender in case an appender fails

Rewrite appender

Modify log events prior to delivering them to the target

Routing appender

Dynamically choose a different appender for each log event

See Delegating Appenders for details.

Extending

Appenders are plugins implementing the Appender interface. This section will guide you on how to create custom ones.

Implementing a reliable and efficient appender is a challenging task! We strongly advise you to

  1. Use existing appenders and/or managers whenever appropriate

  2. Share your use case and ask for feedback in a user support channel

Plugin preliminaries

Log4j plugin system is the de facto extension mechanism embraced by various Log4j components. Plugins provide extension points to components, that can be used to implement new features, without modifying the original component. It is analogous to a dependency injection framework, but curated for Log4j-specific needs.

In a nutshell, you annotate your classes with @Plugin and their (static) factory methods with @PluginFactory. Last, you inform the Log4j plugin system to discover these custom classes. This is done using running the PluginProcessor annotation processor while building your project. Refer to Plugins for details.

Extending appenders

Appenders are plugins implementing the Appender interface. We recommend users to extend from AbstractAppender, which provides implementation convenience. While annotating your appender with @Plugin, you need to make sure that

  • It has a unique name attribute across all available Appender plugins

  • The category attribute is set to Node.CATEGORY

Most appender implementation use managers, which model an abstraction owning the resources, such as an OutputStream or a socket. When a reconfiguration occurs, a new appender will be created. However, if nothing significant in the previous manager has changed, the new appender will simply reference it instead of creating a new one. This ensures that events are not lost while a reconfiguration is taking place without requiring that logging pause while the reconfiguration takes place. You are strongly advised to study the manager concept in the predefined appenders, and either use an existing manager, or create your own.

You can check out the following files for examples: