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:
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
log4j2.enableDirectEncoders
configuration property is enabled, -
or the
bufferedIo
configuration attribute is enabled.
The buffer is flushed to the underlying resource on three occasions:
-
if the buffer is full.
-
at the end of each log event batch, if asynchronous loggers or appenders are used.
-
at the end of each log event, if the
immediateFlush
configuration attribute istrue
.
These configuration attributes are shared by multiple appenders:
bufferSize
Type |
|
---|---|
Default value |
This configuration attribute specifies the size of the ByteBuffer
used by the appender.
bufferedIo
Type |
|
---|---|
Default value |
|
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 |
|
---|---|
Default value |
|
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 theOutputStream.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 |
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 |
|
---|---|
Default value |
|
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
|
Runtime evaluation of attributes
The following configuration attributes are also evaluated at runtime, so can contain escaped $${...}
property substitution expressions.
Component | Parameter | Event type | Evaluation context |
---|---|---|---|
Log event |
|||
Log event |
|||
Log event |
|||
Log event |
|||
Log event |
|||
Rollover |
|||
Rollover |
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 totrue
. default
-
By default, the Console appender uses the values of
System.out
orSystem.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
andSystem.err
streams. It can be enabled by setting thefollow
attribute totrue
.This setting might be useful in multi-application environments. Some application servers modify
System.out
andSystem.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 totrue
.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'
-
Attribute | Type | Default value | Description | ||
---|---|---|---|---|---|
Required |
|||||
|
The name of the appender. |
||||
Optional |
|||||
|
The size of the
See Buffering for more details. |
||||
|
|
If set to This setting bypasses the buffering of
This setting is incompatible with the
|
|||
|
|
If set to Otherwise, the value of This setting is incompatible with the
|
|||
|
|
If Logging exceptions are always also logged to Status Logger |
|||
|
|
If set to See Buffering for more details. |
|||
It specifies which standard output stream to use:
|
|
Multiplicity |
Description |
zero or one |
Allows filtering log events just before they are formatted and sent. See also appender filtering stage. |
|
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
log4j2.xml
<Console name="CONSOLE">
<PatternLayout pattern="%d [%t] %p %c - %m%n"/>
</Console>
log4j2.json
"Console": {
"name": "CONSOLE",
"PatternLayout": {
"pattern": "%d [%t] %p %c - %m%n"
}
}
log4j2.yaml
Console:
name: "CONSOLE"
PatternLayout:
pattern: "%d [%t] %p %c - %m%n"
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
log4j2.xml
<Console name="CONSOLE"
direct="true"> (1)
<JsonTemplateLayout/> (2)
</Console>
log4j2.json
"Console": {
"name": "CONSOLE",
"direct": true, (1)
"JsonTemplateLayout": {} (2)
}
log4j2.yaml
Console:
name: "CONSOLE"
direct: true (1)
JsonTemplateLayout: {} (2)
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 |
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
|
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 availableAppender
plugins -
The
category
attribute is set toNode.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:
-
HttpAppender.java
– HttpAppender sends log events over HTTP usingHttpURLConnectionManager
-
ConsoleAppender.java
– Console Appender writes log events to eitherSystem.out
orSystem.err
usingOutputStreamManager