Apache Log4j 2 Users Guide

User Manual:

Open the PDF directly: View PDF PDF.
Page Count: 172

DownloadApache Log4j 2 Log4j-users-guide
Open PDF In BrowserView PDF
......................................................................................................................................

Apache Log4j 2
v. 2.0-rc1
User's Guide

......................................................................................................................................

The Apache Software Foundation

2014-02-09

Table of Contents

Table of Contents

i

.......................................................................................................................................
1. Table of Contents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . i
2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
3. Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
4. Log4j 1.x Migration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
5. API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
6. Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
7. Web Applications and JSPs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
8. Plugins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
9. Lookups . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
10. Appenders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
11. Layouts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
12. Filters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
13. Async Loggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
14. JMX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
15. Logging Separation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
16. Extending Log4j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
161

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

Table of Contents

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

ii

1 Introduction

1

1 Introduction

.......................................................................................................................................
1.1 Welcome to Log4j 2!
1.1.1 Introduction

Almost every large application includes its own logging or tracing API. In conformance with this
rule, the E.U. SEMPER project decided to write its own tracing API. This was in early 1996. After
countless enhancements, several incarnations and much work that API has evolved to become log4j,
a popular logging package for Java. The package is distributed under the Apache Software License,
a fully-fledged open source license certified by the open source initiative. The latest log4j version,
including full-source code, class files and documentation can be found at http://logging.apache.org/
log4j/2.0/index.html.
Inserting log statements into code is a low-tech method for debugging it. It may also be the only way
because debuggers are not always available or applicable. This is usually the case for multithreaded
applications and distributed applications at large.
Experience indicates that logging was an important component of the development cycle. It offers
several advantages. It provides precise context about a run of the application. Once inserted into the
code, the generation of logging output requires no human intervention. Moreover, log output can
be saved in persistent medium to be studied at a later time. In addition to its use in the development
cycle, a sufficiently rich logging package can also be viewed as an auditing tool.
As Brian W. Kernighan and Rob Pike put it in their truly excellent book "The Practice of
Programming":
As personal choice, we tend not to use debuggers beyond getting a stack trace or the value of a
variable or two. One reason is that it is easy to get lost in details of complicated data structures and
control flow; we find stepping through a program less productive than thinking harder and adding
output statements and self-checking code at critical places. Clicking over statements takes longer
than scanning the output of judiciously-placed displays. It takes less time to decide where to put print
statements than to single-step to the critical section of code, even assuming we know where that is.
More important, debugging statements stay with the program; debugging sessions are transient.
Logging does have its drawbacks. It can slow down an application. If too verbose, it can cause
scrolling blindness. To alleviate these concerns, log4j is designed to be reliable, fast and extensible.
Since logging is rarely the main focus of an application, the log4j API strives to be simple to
understand and to use.
1.1.2 Log4j 2

Log4j 1.x has been widely adopted and used in many applications. However, through the years
development on it has slowed down. It has become more difficult to maintain due to its need to
be compliant with very old versions of Java. Its alternative, SLF4J/Logback made many needed
improvements to the framework. So why bother with Log4j 2? Here are a few of the reasons.
1. Log4j 2 is designed to be usable as an audit logging framework. Both Log4j 1.x and Logback
will lose events while reconfiguring. Log4j 2 will not. in Logback exceptions in Appenders are
never visible to the application. In Log4j 2 Appenders can be configured to allow the exception
to percolate to the application
2. Log4j 2 contains next-generation lock-free Asynchronous Loggers based on the LMAX
Disruptor library. In multi-threaded scenarios Asynchronous Loggers have 10 times higher
throughput and orders of magnitude lower latency than Log4j 1.x and Logback.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

1 Introduction

2

3. Log4j 2 uses a Plugin system that makes it extremely easy to extend the framework by adding
new Appenders, Filters, Layouts, Lookups, and Pattern Converters without requiring any
changes to Log4j.
4. Due to the Plugin system configuration is simpler. Entries in the configuration do not require a
class name to be specified.
5. Support for Message objects. Messages allow support for interesting and complex constructs to
be passed through the logging system and be efficiently manipulated. Users are free to create
their own Message types and write custom Layouts, Filters and Lookups to manipulate them.
6. Log4j 1.x supports Filters on Appenders. Logback added TurboFilters to allow filtering of
events before they are processed by a Logger. Log4j 2 supports Filters that can be configured to
process events before they are handled by a Logger, as they are processed by a Logger or on an
Appender.
7. Many Logback Appenders do not accept a Layout and will only send data in a fixed format.
Most Log4j 2 Appenders accept a Layout, allowing the data to be transported in any format
desired.
8. Layouts in Log4j 1.x and Logback return a String. This resulted in the problems discussed at
Logback Encoders. Log4j 2 takes the simpler approach that Layouts always return a byte array.
This has the advantage that it means they can be used in virtually any Appender, not just the ones
that write to an OutputStream.
9. The Syslog Appender supports both TCP and UDP as well as support for the BSD syslog and the
RFC 5424 formats.
10.Log4j 2 takes advantage of Java 5 concurrency support and performs locking at the lowest level
possible. Log4j 1.x has known deadlock issues. Many of these are fixed in Logback but many
Logback classes still require synchronization at a fairly high level.
11.It is an Apache Software Foundation project following the community and support model used
by all ASF projects. If you want to contribute or gain the right to commit changes just follow the
path outlined at Contributing

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

2 Architecture

3

2 Architecture

.......................................................................................................................................
2.1 Architecture
2.1.1 Main Components

Log4j uses the classes shown in the diagram below.

Applications using the Log4j 2 API will request a Logger with a specific name from the LogManager.
The LogManager will locate the appropriate LoggerContext and then obtain the Logger from it. If the
Logger must be created it will be associated with the LoggerConfig that contains either a) the same
name as the Logger, b) the name of a parent package, or c) the root LoggerConfig. LoggerConfig
objects are created from Logger declarations in the configuration. The LoggerConfig is associated
with the Appenders that actually deliver the LogEvents.
2.1.1.1 Logger Hierarchy

The first and foremost advantage of any logging API over plain System.out.println resides in
its ability to disable certain log statements while allowing others to print unhindered. This capability
assumes that the logging space, that is, the space of all possible logging statements, is categorized
according to some developer-chosen criteria.
In Log4j 1.x the Logger Hierarchy was maintained through a relationship between Loggers. In Log4j
2 this relationship no longer exists. Instead, the hierarchy is maintained in the relationship between
LoggerConfig objects.
Loggers and LoggerConfigs are named entities. Logger names are case-sensitive and they follow the
hierarchical naming rule:
Named Hierarchy

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

2 Architecture

4

A LoggerConfig is said to be an ancestor of another LoggerConfig if its name followed
by a dot is a prefix of the descendant logger name. A LoggerConfig is said to be a parent
of a child LoggerConfig if there are no ancestors between itself and the descendant
LoggerConfig.
For example, the LoggerConfig named "com.foo" is a parent of the LoggerConfig named
"com.foo.Bar". Similarly, "java" is a parent of "java.util" and an ancestor of
"java.util.Vector". This naming scheme should be familiar to most developers.
The root LoggerConfig resides at the top of the LoggerConfig hierarchy. It is exceptional in
that it always exists and it is part of every hierarchy. A Logger that is directly linked to the root
LoggerConfig can be obtained as follows:
Logger logger = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);

Alternatively, and more simply:
Logger logger = LogManager.getRootLogger();

All other Loggers can be retrieved using the LogManager.getLogger static method by passing the
name of the desired Logger. Further information on the Logging API can be found at Log4j 2 API.
2.1.1.2 LoggerContext

The LoggerContext acts as the anchor point for the Logging system. However, it is possible to have
multiple active LoggerContexts in an application depending on the circumstances. More details on the
LoggerContext are in the Log Separation section.
2.1.1.3 Configuration

Every LoggerContext has an active Configuration. The Configuration contains all the Appenders,
context-wide Filters, LoggerConfigs and contains the reference to the StrSubstitutor. During
reconfiguration two Configuration objects will exist. Once all Loggers have been redirected to the
new Configuration, the old Configuration will be stopped and discarded.
2.1.1.4 Logger

As stated previously, Loggers are created by calling LogManager.getLogger. The Logger itself
performs no direct actions. It simply has a name and is associated with a LoggerConfig. It extends
AbstractLogger and implements the required methods. As the configuration is modified Loggers may
become associated with a different LoggerConfig, thus causing their behavior to be modified.
2.Retrieving Loggers

Calling the getLogger method with the same name will always return a reference to the exact same
Logger object.
For example, in
Logger x = Logger.getLogger("wombat");
Logger y = Logger.getLogger("wombat");

x and y refer to exactly the same Logger object.

Configuration of the log4j environment is typically done at application initialization. The preferred
way is by reading a configuration file. This is discussed in Configuration.
Log4j makes it easy to name Loggers by software component. This can be accomplished by
instantiating a Logger in each class, with the logger name equal to the fully qualified name of the
class. This is a useful and straightforward method of defining loggers. As the log output bears the
name of the generating Logger, this naming strategy makes it easy to identify the origin of a log

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

2 Architecture

5

message. However, this is only one possible, albeit common, strategy for naming loggers. Log4j does
not restrict the possible set of loggers. The developer is free to name the loggers as desired.
Nevertheless, naming loggers after the class where they are located seems to be the best strategy
known so far.
2.1.1.5 LoggerConfig

LoggerConfig objects are created when Loggers are declared in the logging configuration. The
LoggerConfig contains a set of Filters that must allow the LogEvent to pass before it will be passed to
any Appenders. It contains references to the set of Appenders that should be used to process the event.
2.Log Levels

LoggerConfigs will be assigned a Log Level. The set of possible levels includes TRACE, DEBUG,
INFO, WARN, ERROR, and FATAL. Note that in Log4j 2, the Level is an Enum and cannot be subclassed. Users who desire more granularity are encouraged to use Markers instead.
Log4j 1.x and Logback both have the concept of "Level Inheritance". In Log4j 2, Loggers and
LoggerConfigs are two different objects so this concept is implemented differently. Each Logger
references the appropriate LoggerConfig which in turn can reference its parent, thus achieving the
same effect.
Below are five tables with various assigned level values and the resulting levels that will be associated
with each Logger. Note that in all these cases if the root LoggerConfig is not configured a default
Level will be assigned to it.
Logger Name

Assigned LoggerConfig

Level

root

root

DEBUG

X

root

DEBUG

X.Y

root

DEBUG

X.Y.Z

root

DEBUG

Example 1
In example 1 above, only the root logger is configured and has a Log Level. All the other Loggers
reference the root LoggerConfig and use its Level.
Logger Name

Assigned LoggerConfig

Level

root

root

DEBUG

X

X

ERROR

X.Y

X.Y

INFO

X.Y.Z

X.Y.Z

WARN

Example 2
In example 2, all loggers have a configured LoggerConfig and obtain their Level from it.
Logger Name

Assigned LoggerConfig

Level

root

root

DEBUG

X

X

ERROR

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

2 Architecture

6

X.Y

X

ERROR

X.Y.Z

X.Y.Z

WARN

Example 3
In example 3, the loggers root, X and X.Y.Z each have a configured LoggerConfig with the same
name. The Logger X.Y does not have a configured LoggerConfig with a matching name so uses the
configuration of LoggerConfig X since that is the LoggerConfig whose name has the longest match to
the start of the Logger's name.
Logger Name

Assigned LoggerConfig

level

root

root

DEBUG

X

X

ERROR

X.Y

X

ERROR

X.Y.Z

X

ERROR

Example 4
In example 4, the loggers root and X each have a Configured LoggerConfig with the same name.
The loggers X.Y and X.Y.Z do not have configured LoggerConfigs and so get their Level from the
LoggerConfig assigned to them, X, since it is the LoggerConfig whose name has the longest match to
the start of the Logger's name.
Logger Name

Assigned LoggerConfig

level

root

root

DEBUG

X

X

ERROR

X.Y

X.Y

INFO

X.YZ

X

ERROR

Example 5
In example 5, the loggers root. X, and X.Y each have a Configured LoggerConfig with the same
name. The logger X.YZ does not have configured LoggerConfig and so gets its Level from the
LoggerConfig assigned to it, X, since it is the LoggerConfig whose name has the longest match to the
start of the Logger's name. It is not associated with LoggerConfig X.Y since tokens after periods must
match exactly.
The table below illustrates how Level filtering works. In the table, the vertical header shows the
Level of the LogEvent, while the horizontal header shows the Level associated with the appropriate
LoggerConfig. The intersection identifies whether the LogEvent would be allowed to pass for further
processing (Yes) or discarded (No).
Event
Level

LoggerConfig
Level
TRACE

DEBUG

INFO

WARN

ERROR

FATAL

OFF

ALL

YES

YES

YES

YES

YES

YES

NO

TRACE

YES

NO

NO

NO

NO

NO

NO

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

2 Architecture

7

DEBUG

YES

YES

NO

NO

NO

NO

NO

INFO

YES

YES

YES

NO

NO

NO

NO

WARN

YES

YES

YES

YES

NO

NO

NO

ERROR

YES

YES

YES

YES

YES

NO

NO

FATAL

YES

YES

YES

YES

YES

YES

NO

OFF

NO

NO

NO

NO

NO

NO

NO

2.1.1.6 Filter

In addition to the automatic log Level filtering that takes place as described in the previous section,
Log4j provides Filters that can be applied before control is passed to any LoggerConfig, after
control is passed to a LoggerConfig but before calling any Appenders, after control is passed to a
LoggerConfig but before calling a specific Appender, and on each Appender. In a manner very similar
to firewall filters, each Filter can return one of three results, Accept, Deny or Neutral. A response
of Accept means that no other Filters should be called and the event should progress. A response of
Deny means the event should be immediately ignored and control should be returned to the caller. A
response of Neutral indicates the event should be passed to other Filters. If there are no other Filters
the event will be processed.
Although an event may be accepted by a Filter the event still might not be logged. This can happen
when the event is accepted by the pre-LoggerConfig Filter but is then denied by a LoggerConfig filter
or is denied by all Appenders.
2.1.1.7 Appender

The ability to selectively enable or disable logging requests based on their logger is only part of the
picture. Log4j allows logging requests to print to multiple destinations. In log4j speak, an output
destination is called an Appender. Currently, appenders exist for the console, files, remote socket
servers, Apache Flume, JMS, and remote UNIX Syslog daemons. More than one Appender can be
attached to a Logger.
An Appender can be added to a Logger by calling the addLoggerAppender method of the current
Configuration. If a LoggerConfig matching the name of the Logger does not exist, one will be created,
the Appender will be attached to it and then all Loggers will be notified to update their LoggerConfig
references.
Each enabled logging request for a given logger will be forwarded to all the appenders in
that Logger's LoggerConfig as well as the Appenders of the LoggerConfig's parents. In other
words, Appenders are inherited additively from the LoggerConfig hierarchy. For example, if a
console appender is added to the root logger, then all enabled logging requests will at least print
on the console. If in addition a file appender is added to a LoggerConfig, say C, then enabled
logging requests for C and C's children will print in a file and on the console. It is possible to
override this default behavior so that Appender accumulation is no longer additive by setting
additivity="false" on the Logger declaration in the configuration file.
The rules governing appender additivity are summarized below.
Appender Additivity
The output of a log statement of Logger L will go to all the Appenders in the LoggerConfig
associated with L and the ancestors of that LoggerConfig. This is the meaning of the term
"appender additivity".

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

2 Architecture

8

However, if an ancestor of the LoggerConfig associated with Logger L, say P, has the
additivity flag set to false, then L's output will be directed to all the appenders in L's
LoggerConfig and it's ancestors up to and including P but not the Appenders in any of the
ancestors of P.
Loggers have their additivity flag set to true by default.
The table below shows an example:
Logger
Name

Added
Appenders

Additivity
Flag

Output Targets

Comment

root

A1

not applicable

A1

The root logger
has no parent so
additivity does not
apply to it.

x

A-x1, A-x2

true

A1, A-x1, A-x2

Appenders of "x"
and root.

x.y

none

true

A1, A-x1, A-x2

Appenders of "x"
and root. It would
not be typical to
configure a Logger
with no Appenders.

x.y.z

A-xyz1

true

A1, A-x1, A-x2, Axyz1

Appenders in
"x.y.z", "x" and root.

security

A-sec

false

A-sec

No appender
accumulation since
the additivity flag is
set to false.

security.access

none

true

A-sec

Only appenders of
"security" because
the additivity flag in
"security" is set to
false.

2.1.1.8 Layout

More often than not, users wish to customize not only the output destination but also the output
format. This is accomplished by associating a Layout with an Appender. The Layout is responsible
for formatting the LogEvent according to the user's wishes, whereas an appender takes care of sending
the formatted output to its destination. The PatternLayout, part of the standard log4j distribution, lets
the user specify the output format according to conversion patterns similar to the C language printf
function.
For example, the PatternLayout with the conversion pattern "%r [%t] %-5p %c - %m%n" will output
something akin to:
176 [main] INFO

org.foo.Bar - Located nearest gas station.

The first field is the number of milliseconds elapsed since the start of the program. The second field
is the thread making the log request. The third field is the level of the log statement. The fourth field
is the name of the logger associated with the log request. The text after the '-' is the message of the
statement.
Just as importantly, log4j will render the content of the log message according to user specified
criteria. For example, if you frequently need to log Oranges, an object type used in your current

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

2 Architecture

9

project, then you can create an OrangeMessage that accepts an Orange instance and pass that to Log4j
so that the Orange object can be formatted into an appropriate byte array when required.
2.1.1.9 StrSubstitutor and StrLookup

The StrSubstitutor class and StrLookup interface were borrowed from Apache Commons Lang
and then modified to support evaluating LogEvents. In addition the Interpolator class was borrowed
from Apache Commons Configuration to allow the StrSubstitutor to evaluate variables that from
multiple StrLookups. It too was modified to support evaluating LogEvents. Together these provide
a mechanism to allow the configuration to reference variables coming from System Properties, the
configuration file, the ThreadContext Map, StructuredData in the LogEvent. The variables can either
be resolved when the configuration is processed or as each event is processed, if the component is
capable of handling it. See Lookups for more information.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

3 Log4j 1.x Migration

10

3 Log4j 1.x Migration

.......................................................................................................................................
3.1 Migrating from Log4j 1.x

3.1.1 Using the Log4j 1.x bridge

Perhaps the simplest way to convert to using Log4j 2 is to replace the log4j 1.x jar file with Log4j
2's log4j-1.2-api.jar. However, to use this successfully applications must meet the following
requirements:
1. They must not access methods and classes internal to the Log4j 1.x implementation such as
Appenders, LoggerRepository or Category's callAppenders method.
2. They must not programmatically configure Log4j.
3. They must not configure by calling the classes DomConfigurator or
PropertiesConfigurator.
3.1.2 Converting to the Log4j 2 API

For the most part, converting from the Log4j 1.x API to Log4j 2.0 should be fairly simple. Many of
the log statements will require no modification. However, where necessary the following changes
must be made.
1. Calls to Logger.getLogger() must be modified to LogManager.getLogger().
2. Calls to Logger.getRootLogger() or LogManager.getRootLogger() must be replaced
with LogManager.getRootLogger().
3. Calls to LogManager.getLogger that accept a LoggerFactory must remove the
LoggerFactory and use one of Log4j 2's other extension mechanisms.
4. Calls to logger.setLevel() or similar methods are not supported in the API. Applications
should remove these. Equivalent functionality is provided in the Log4j 2 implementation classes
but may leave the application susceptible to changes in Log4j 2 internals.
5. Where appropriate, applications should convert to use parameterized messages instead of String
concatenation.
3.1.3 Configuring Log4j 2

Although the Log4j 2 configuration syntax is different than that of Log4j 1.x, most, if not all, of
the same functionality is available. Below are the example configurations for Log4j 1.x and their
counterparts in Log4j 2.
3.1.3.1 Sample 1 - Simple configuration using a Console Appender

Log4j 1.x XML configuration

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

3 Log4j 1.x Migration


















Log4j 2 XML configuration















3.1.3.2 Sample 2 - Simple configuration using a File Appender

Log4j 1.x XML configuration

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

11

3 Log4j 1.x Migration

12


























Log4j 2 XML configuration




















3.1.3.3 Sample 3 - SocketAppender

Log4j 1.x XML configuration. This example from Log4j 1.x is misleading. The SocketAppender does
not actually use a Layout. Configuring one will have no effect.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

3 Log4j 1.x Migration



























Log4j 2 XML configuration




















3.1.3.4 Sample 4 - AsyncAppender

Log4j 1.x XML configuration using the AsyncAppender.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

13

3 Log4j 1.x Migration



















Log4j 2 XML configuration.

















3.1.3.5 Sample 5 - AsyncAppender with Console and File

Log4j 1.x XML configuration using the AsyncAppender.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

14

3 Log4j 1.x Migration

15

























Log4j 2 XML configuration. Note that the Async Appender should be configured after the appenders
it references. This will allow it to shutdown properly.





















©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

4 API

16

4 API

.......................................................................................................................................
4.1 Log4j 2 API

4.1.1 Overview

The Log4j 2 API provides the interface that applications should code to and provides the adapter
components required for implementers to create a logging implementation. Although Log4j 2 is
broken up between an API and an implementation, the primary purpose of doing so was not to allow
multiple implementations, although that is certainly possible, but to clearly define what classes and
methods are safe to use in "normal" application code.
4.1.1.1 Hello World!

No introduction would be complete without the customary Hello, World example. Here is ours. First,
a Logger with the name "HelloWorld" is obtained from the LogManager. Next, the logger is used
to write the "Hello, World!" message, however the message will be written only if the Logger is
configured to allow informational messages.
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class HelloWorld {
private static Logger logger = LogManager.getLogger("HelloWorld");
public static void main(String[] args) {
logger.info("Hello, World!");
}
}

The output from the call to logger.info() will vary significantly depending on the configuration used.
See the Configuration section for more details.
4.1.1.2 Substituting Parameters

Frequently the purpose of logging is to provide information about what is happening in the system,
which requires including information about the objects being manipulated. In Log4j 1.x this could be
accomplished by doing:
if (logger.isDebugEnabled()) {
logger.debug("Logging in user " + user.getName() + " with birthday " + user.getBirthdayCalendar());
}

Doing this repeatedly has the effect of making the code feel like it is more about logging than the
actual task at hand. In addition, it results in the logging level being checked twice; once on the call to
isDebugEnabled and once on the debug method. A better alternative would be:
logger.debug("Logging in user {} with birthday {}", user.getName(), user.getBirthdayCalendar());

With the code above the logging level will only be checked once and the String construction will only
occur when debug logging is enabled.
4.1.1.3 Formatting Parameters

Substituting parameters leaves formatting up to you if toString() is not what you want. To
facilitate formatting, you can use the same format strings as Java's Formatter. For example:

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

4 API

17

public static Logger logger = LogManager.getFormatterLogger("Foo");

logger.debug("Logging in user %s with birthday %s", user.getName(), user.getBirthdayCalendar());
logger.debug("Logging in user %1$s with birthday %2$tm %2$te,%2$tY", user.getName(), user.getBirthdayCalendar
logger.debug("Integer.MAX_VALUE = %,d", Integer.MAX_VALUE);
logger.debug("Long.MAX_VALUE = %,d", Long.MAX_VALUE);

To use a formatter Logger, you must call one of the LogManager getFormatterLogger method. The
output for this example shows that Calendar toString() is verbose compared to custom formatting:

2012-12-12 11:56:19,633 [main] DEBUG: User John Smith with birthday java.util.GregorianCalendar[time=?,areFie
2012-12-12 11:56:19,643 [main] DEBUG: User John Smith with birthday 05 23, 1995
2012-12-12 11:56:19,643 [main] DEBUG: Integer.MAX_VALUE = 2,147,483,647
2012-12-12 11:56:19,643 [main] DEBUG: Long.MAX_VALUE = 9,223,372,036,854,775,807

4.1.1.4 Logger names

Most logging implementations use a hierarchical scheme for matching logger names with logging
configuration. In this scheme the logger name hierarchy is represented by '.' characters in the
logger name, in a fashion very similar to the hierarchy used for Java package names. For example,
org.apache.logging.appender and org.apache.logging.filter both have org.apache.logging as their
parent. In most cases, applications name their loggers by passing the current class's name to
LogManager.getLogger. Because this usage is so common, Log4j 2 provides that as the default when
the logger name parameter is either omitted or is null. For example, in both examples below the
Logger will have a name of "org.apache.test.MyTest".
package org.apache.test;
public class MyTest {
private static Logger logger = LogManager.getLogger(MyTest.class.getName());
}
package org.apache.test;
public class MyTest {
private static Logger logger = LogManager.getLogger();
}

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

5 Configuration

18

5 Configuration

.......................................................................................................................................
5.1 Configuration
Inserting log requests into the application code requires a fair amount of planning and effort.
Observation shows that approximately 4 percent of code is dedicated to logging. Consequently, even
moderately sized applications will have thousands of logging statements embedded within their code.
Given their number, it becomes imperative to manage these log statements without the need to modify
them manually.
Configuration of Log4j 2 can be accomplished in 1 of 4 ways:
1. Through a configuration file written in XML or JSON.
2. Programmatically, by creating a ConfigurationFactory and Configuration implementation.
3. Programmatically, by calling the APIs exposed in the Configuration interface to add components
to the default configuration.
4. Programmatically, by calling methods on the internal Logger class.
This page focuses primarily on configuring Log4j through a configuration file. Information on
programmatically configuring Log4j can be found at Extending Log4j 2.
Note that unlike Log4j 1.x, the public Log4j 2 API does not expose methods to add, modify or remove
appenders and filters or manipulate the configuration in any way.

5.1.1 Automatic Configuration

Log4j has the ability to automatically configure itself during initialization. When Log4j starts it will
locate all the ConfigurationFactory plugins and arrange then in weighted order from highest to lowest.
As delivered, Log4j contains two ConfigurationFactory implementations, one for JSON and one for
XML.
1. Log4j will inspect the "log4j.configurationFile" system property and, if set, will attempt to load
the configuration using the ConfigurationFactory that matches the file extension.
2. If no system property is set the JSON ConfigurationFactory will look for log4j2-test.json or
log4j2-test.jsn in the classpath.
3. If no such file is found the XML ConfigurationFactory will look for log4j2-test.xml in the
classpath.
4. If a test file cannot be located the JSON ConfigurationFactory will look for log4j2.json or
log4j2.jsn on the classpath.
5. If a JSON file cannot be located the XML ConfigurationFactory will try to locate log4j2.xml on
the classpath.
6. If no configuration file could be located the DefaultConfiguration will be used. This will
cause logging output to go to the console.
An example application named MyApp that uses log4j can be used to illustrate how this is done.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

5 Configuration

19

import com.foo.Bar;
// Import log4j classes.
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
public class MyApp {
// Define a static logger variable so that it references the
// Logger instance named "MyApp".
static final Logger logger = LogManager.getLogger(MyApp.class.getName());
public static void main(String[] args) {
// Set up a simple configuration that logs on the console.
logger.trace("Entering application.");
Bar bar = new Bar();
if (!bar.doIt()) {
logger.error("Didn't do it.");
}
logger.trace("Exiting application.");
}

}

MyApp begins by importing log4j related classes. It then defines a static logger variable with the name
MyApp which happens to be the fully qualified name of the class.
MyApp uses the Bar class defined in the package com.foo.
package com.foo;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
public class Bar {
static final Logger logger = LogManager.getLogger(Bar.class.getName());
public boolean doIt() {
logger.entry();
logger.error("Did it again!");
return logger.exit(false);
}
}

Log4j will provide a default configuration if it cannot locate a configuration file. The default
configuration, provided in the DefaultConfiguration class, will set up:
• A ConsoleAppender attached to the root logger.
• A PatternLayout set to the pattern "%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg
%n" attached to the ConsoleAppender
Note that by default Log4j assigns the root logger to Level.ERROR.
The output of MyApp would be similar to:

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

5 Configuration

20

17:13:01.540 [main] ERROR com.foo.Bar - Did it again!
17:13:01.540 [main] ERROR MyApp - Didn't do it.

As was described previously, Log4j will first attempt to configure itself from configuration files. A
configuration equivalent to the default would look like:














Once the file above is placed into the classpath as log4j2.xml you will get results identical to those
listed above. Changing the root level to trace will result in results similar to:
17:13:01.540
17:13:01.540
17:13:01.540
17:13:01.540
17:13:01.540
17:13:01.540

[main]
[main]
[main]
[main]
[main]
[main]

TRACE
TRACE
ERROR
TRACE
ERROR
TRACE

MyApp - Entering application.
com.foo.Bar - entry
com.foo.Bar - Did it again!
com.foo.Bar - exit with (false)
MyApp - Didn't do it.
MyApp - Exiting application.

Note that status logging is disabled when the default configuration is used.
Perhaps it is desired to eliminate all the TRACE output from everything except com.foo.Bar.
Simply changing the log level would not accomplish the task. Instead, the solution is to add a new
logger definition to the configuration:





With this configuration all log events from com.foo.Bar will be recorded while only error events
will be recorded from all other components.

5.1.2 Additivity

In the previous example all the events from com.foo.Bar were still written to the Console. This is
because the logger for com.foo.Bar did not have any appenders configured while its parent did. In
fact, the following configuration

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

5 Configuration

21


















would result in
17:13:01.540
17:13:01.540
17:13:01.540
17:13:01.540
17:13:01.540
17:13:01.540

[main]
[main]
[main]
[main]
[main]
[main]

TRACE
TRACE
ERROR
TRACE
TRACE
ERROR

com.foo.Bar - entry
com.foo.Bar - entry
com.foo.Bar - Did it again!
com.foo.Bar - exit (false)
com.foo.Bar - exit (false)
MyApp - Didn't do it.

Notice that the trace messages from com.foo.Bar appear twice. This is because the appender
associated with logger com.foo.Bar is first used, which writes the first instance to the Console.
Next, the parent of com.foo.Bar, which in this case is the root logger, is referenced. The event is
then passed to its appender, which is also writes to the Console, resulting in the second instance. This
is known as additivity. While additivity can be quite a convenient feature (as in the first previous
example where no appender reference needed to be configured), in many cases this behavior is
considered undesirable and so it is possible to disable it by setting the additivity attribute on the logger
to false:

















Once an event reaches a logger with its additivity set to false the event will not be passed to any of its
parent loggers, regardless of their additivity setting.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

5 Configuration

22

5.1.3 Automatic Reconfiguration

When configured from a File, Log4j has the ability to automatically detect changes to the
configuration file and reconfigure itself. If the monitorInterval attribute is specified on the
configuration element and is set to a non-zero value then the file will be checked the next time a
log event is evaluated and/or logged and the monitorInterval has elapsed since the last check. The
example below shows how to configure the attribute so that the configuration file will be checked for
changes only after at least 30 seconds have elapsed. The minimum interval is 5 seconds.


...


5.1.4 Chainsaw can automatically process your log files (Advertising appender configurations)

Log4j provides the ability to 'advertise' appender configuration details for all file-based appenders
as well as socket-based appenders. For example, for file-based appenders, the file location and the
pattern layout in the file are included in the advertisement. Chainsaw and other external systems can
discover these advertisements and use that information to intelligently process the log file.
The mechanism by which an advertisement is exposed, as well as the advertisement format, is specific
to each Advertiser implementation. An external system which would like to work with a specific
Advertiser implementation must understand how to locate the advertised configuration as well as the
format of the advertisement. For example, a 'database' Advertiser may store configuration details in
a database table. An external system can read that database table in order to discover the file location
and the file format.
Log4j provides one Advertiser implementation, a 'multicastdns' Advertiser, which advertises appender
configuration details via IP multicast using the http://jmdns.sourceforge.net library.
Chainsaw automatically discovers log4j's multicastdns-generated advertisements and displays
those discovered advertisements in Chainsaw's Zeroconf tab (if the jmdns library is in Chainsaw's
classpath). To begin parsing and tailing a log file provided in an advertisement, just double-click the
advertisement entry in Chainsaw's the Zeroconf tab. Currently, Chainsaw only supports FileAppender
advertisements.
To advertise an appender configuration:
•
•
•
•

Add the JmDns library from http://jmdns.sourceforge.net to the application classpath
Set the 'advertiser' attribute of the configuration element to 'multicastdns'
Set the 'advertise' attribute on the appender element to 'true'
If advertising a FileAppender-based configuration, set the 'advertiseURI' attribute on the
appender element to an appropriate URI

FileAppender-based configurations require an additional 'advertiseURI' attribute to be specified on
the appender. The 'advertiseURI' attribute provides Chainsaw with information on how the file can be
accessed. For example, the file may be remotely accessible to Chainsaw via ssh/sftp by specifying a
Commons VFS ( http://commons.apache.org/proper/commons-vfs/) sftp:// URI, an http:// URI may
be used if the file is accessible through a web server, or a file:// URI can be specified if accessing the
file from a locally-running instance of Chainsaw.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

5 Configuration

23

Here is an example advertisement-enabled appender configuration which can be used by a locallyrunning Chainsaw to automatically tail the log file (notice the file:// advertiseURI):
Please note, you must add the JmDns library from http://jmdns.sourceforge.net to your
application classpath in order to advertise with the 'multicastdns' advertiser.


...






5.1.5 Configuration Syntax

As the previous examples have shown as well as those to follow, Log4j allows you to easily redefine
logging behavior without needing to modify your application. It is possible to disable logging for
certain parts of the application, log only when specific criteria are met such as the action being
performed for a specific user, route output to Flume or a log reporting system, etc. Being able to do
this requires understanding the syntax of the configuration files.

5.1.5.1 Configuration with XML

The configuration element in the XML file accepts several attributes:
Attribute Name

Description

advertiser

(Optional) The Advertiser plugin name which will
be used to advertise individual FileAppender or
SocketAppender configurations. The only Advertiser
plugin provided is 'multicastdns".

dest

Either "err", which will send output to stderr, or a file
path or URL.

monitorInterval

The minimum amount of time, in seconds, that must
elapse before the file configuration is checked for
changes.

name

The name of the configuration.

packages

A comma separated list of package names to
search for plugins. Plugins are only loaded once per
classloader so changing this value may not have any
effect upon reconfiguration.

schema

Identifies the location for the classloader to located the
XML Schema to use to validate the configuration. Only
valid when strict is set to true. If not set no schema
validation will take place.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

5 Configuration

24

shutdownHook

Specifies whether or not Log4j should automatically
shutdown when the JVM shuts down. The shutdown
hook is enabled by default but may be disabled by
setting this attribute to "disable"

status

The level of internal Log4j events that should be
logged to the console.

strict

Enables the use of the strict XML format. Not
supported in JSON configurations.

verbose

Enables diagnostic information while loading plugins.

Log4j can be configured using two XML flavors; concise and strict. The concise format makes
configuration very easy as the element names match the components they represent however it cannot
be validated with an XML schema. For example, the ConsoleAppender is configured by declaring an
XML element named Console under its parent appenders element. However, element and attribute
names are are not case sensitive. In addition, attributes can either be specified as an XML attribute or
as an XML element that has no attributes and has a text value. So


and

%m%n


are equivalent.
The file below represents the structure of an XML configuration, but note that the elements in italics
below represent the concise element names that would appear in their place.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

5 Configuration

;


value


<
filter ... />

<
appender ... >
<
filter ... />

...



<
filter ... />

...






See the many examples on this page for sample appender, filter and logger declarations.
5.Strict XML

In addition to the concise XML format above, Log4j allows configurations to be specified in a
more "normal" XML manner that can be validated using an XML Schema. This is accomplished by
replacing the friendly element names above with their object type as shown below. For example,
instead of the ConsoleAppender being configuerd using an element named Console it is instead
configured as an appender element with a type attribute containing "Console".

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

25

5 Configuration

;


value







...





...






Below is a sample configuration using the strict format.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

26

5 Configuration

27




target/test.log



















%d %p %C{1.} [%t] %m%n





















©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

5 Configuration

28

5.1.5.2 Configuration with JSON

In addition to XML, Log4j can be configured using JSON. The JSON format is very similar to the
concise XML format. Each key represents the name of a plugin and the key/value pairs associated
with it are its attributes. Where a key contains more than a simple value it itself will be a subordinate
plugin. In the example below, ThresholdFilter, Console, and PatternLayout are all plugins while the
Console plugin will be assigned a value of STDOUT for its name attribute and the ThresholdFilter
will be assigned a level of debug.
{ "configuration": { "status": "error", "name": "RoutingTest",
"packages": "org.apache.logging.log4j.test",
"properties": {
"property": { "name": "filename",
"value" : "target/rolling1/rollingtest-$${sd:type}.log" }
},
"ThresholdFilter": { "level": "debug" },
"appenders": {
"Console": { "name": "STDOUT",
"PatternLayout": { "pattern": "%m%n" }
},
"List": { "name": "List",
"ThresholdFilter": { "level": "debug" }
},
"Routing": { "name": "Routing",
"Routes": { "pattern": "$${sd:type}",
"Route": [
{
"RollingFile": {
"name": "Rolling-${sd:type}", "fileName": "${filename}",
"filePattern": "target/rolling1/test1-${sd:type}.%i.log.gz",
"PatternLayout": {"pattern": "%d %p %c{1.} [%t] %m%n"},
"SizeBasedTriggeringPolicy": { "size": "500" }
}
},
{ "AppenderRef": "STDOUT", "key": "Audit"},
{ "AppenderRef": "List", "key": "Service"}
]
}
}
},
"loggers": {
"logger": { "name": "EventLogger", "level": "info", "additivity": "false",
"AppenderRef": { "ref": "Routing" }},
"root": { "level": "error", "AppenderRef": { "ref": "STDOUT" }}
}
}
}

Note that in the RoutingAppender the Route element has been declared as an array. This is valid
because each array element will be a Route component. This won't work for elements such as
appenders and filters, where each element has a different name in the concise format. Appenders and
filters can be defined as array elements if each appender or filter declares an attribute named "type"
that contains the type of the appender. The following example illustrates this as well as how to declare
multiple loggers as an array.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

5 Configuration

29

{ "configuration": { "status": "debug", "name": "RoutingTest",
"packages": "org.apache.logging.log4j.test",
"properties": {
"property": { "name": "filename",
"value" : "target/rolling1/rollingtest-$${sd:type}.log" }
},
"ThresholdFilter": { "level": "debug" },
"appenders": {
"appender": [
{ "type": "Console", "name": "STDOUT", "PatternLayout": { "pattern": "%m%n" }},
{ "type": "List", "name": "List", "ThresholdFilter": { "level": "debug" }},
{ "type": "Routing", "name": "Routing",
"Routes": { "pattern": "$${sd:type}",
"Route": [
{
"RollingFile": {
"name": "Rolling-${sd:type}", "fileName": "${filename}",
"filePattern": "target/rolling1/test1-${sd:type}.%i.log.gz",
"PatternLayout": {"pattern": "%d %p %c{1.} [%t] %m%n"},
"SizeBasedTriggeringPolicy": { "size": "500" }
}
},
{ "AppenderRef": "STDOUT", "key": "Audit"},
{ "AppenderRef": "List", "key": "Service"}
]
}
}
]
},
"loggers": {
"logger": [
{ "name": "EventLogger", "level": "info", "additivity": "false",
"AppenderRef": { "ref": "Routing" }},
{ "name": "com.foo.bar", "level": "error", "additivity": "false",
"AppenderRef": { "ref": "Console" }}
],
"root": { "level": "error", "AppenderRef": { "ref": "STDOUT" }}
}
}
}

The JSON support uses the Jackson Data Processor to parse the JSON files. These dependencies must
be added to a project that wants to use JSON for configuration:

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

5 Configuration

30


com.fasterxml.jackson.core
jackson-core
2.2.2


com.fasterxml.jackson.core
jackson-databind
2.2.2


com.fasterxml.jackson.core
jackson-annotations
2.2.2


5.1.5.3 Configuring loggers

An understanding of how loggers work in Log4j is critical before trying to configure them. Please
reference the Log4j architecture if more information is required. Trying to configure Log4j without
understanding those concepts will lead to frustration.
A LoggerConfig is configured using the logger element. The logger element must have a name
attribute specified, will usually have a level attribute specified and may also have an additivity
attribute specified. The level may be configured with one of TRACE, DEBUG, INFO, WARN,
ERROR, ALL or OFF. If no level is specified it will default to ERROR. The additivity attribute may
be assigned a value of true or false. If the attribute is omitted the default value of false will be used.
A LoggerConfig (including the root LoggerConfig) can be configured with properties that will be
added to the properties copied from the ThreadContextMap. These properties can be referenced from
Appenders, Filters, Layouts, etc just as if they were part of the ThreadContext Map. The properties
can contain variables that will be resolved either when the configuration is parsed or dynamically
when each event is logged. See Property Substitution for more information on using variables.
The LoggerConfig may also be configured with one or more AppenderRef elements. Each appender
referenced will become associated with the specified LoggerConfig. If multiple appenders are
configured on the LoggerConfig each of them be called when processing logging events.
Every configuration must have a root logger. If one is not configured the default root LoggerConfig,
which has a level of ERROR and has a Console appender attached, will be used. The main differences
between the root logger and other loggers are
1. The root logger does not have a name attribute.
2. The root logger does not support the additivity attribute since it has no parent.

5.1.5.4 Configuring Appenders

An appender is configured either using the specific appender plugin's name or with an appender
element and the type attibute containing the appender plugin's name. In addition each appender must
have a name attribute specified with a value that is unique within the set of appenders. The name will
be used by loggers to reference the appender as described in the previous section.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

5 Configuration

31

Most appenders also support a layout to be configured (which again may be specified either using the
specific Layout plugin's name as the element or with "layout" as the element name along with a type
attribute that contains the layout plugin's name. The various appenders will contain other attributes or
elements that are required for them to function properly.

5.1.5.5 Configuring Filters

Log4j allows a filter to be specified in any of 4 places:
1. At the same level as the appenders, loggers and properties elements. These filters can accept or
reject events before they have been passed to a LoggerConfig.
2. In a logger element. These filters can accept or reject events for specific loggers.
3. In an appender element. These filters can prevent or cause events to be processed by the
appender.
4. In an appender reference element. These filters are used to determine if a Logger should route the
event to an appender.
Although only a single filter element can be configured, that element may be the filters element
which represents the CompositeFilter. The filters element allows any number of filter elements
to be configured within it. The following example shows how multiple filters can be configured on the
ConsoleAppender.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

5 Configuration

32




target/test.log
















%d %p %C{1.} [%t] %m%n













${sys:user.name}













©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

5 Configuration

33

5.1.6 Property Substitution

Log4j 2 supports the ability to specify tokens in the configuration as references to properties defined
elsewhere. Some of these properties will be resolved when the configuration file is interpreted while
others may be passed to components where they will be evaluated at runtime. To accomplish this,
Log4j uses variations of Apache Commons Lang's StrSubstitutor and StrLookup classes. In a manner
similar to Ant or Maven, this allows variables declared as ${name} to be resolved using properties
declared in the configuration itself. For example, the following example shows the filename for the
rolling file appender being declared as a property.



target/rolling1/rollingtest-$${sd:type}.log














%d %p %c{1.} [%t] %m%n



















©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

5 Configuration

34

While this is useful, there are many more places properties can originate from. To accommodate this,
Log4j also supports the syntax ${prefix:name} where the prefix identifies tells Log4j that variable
name should be evaluated in a specific context. The contexts that are built in to Logj4 are:
Prefix

Context

bundle

Resource bundle. The format is

${bundle:BundleName:BundleKey}.
The bundle name follows package
naming conventions, for example:

${bundle:com.domain.Messages:MyKey}.
ctx

Thread Context Map (MDC)

date

Inserts the current date and/or time using the specified
format

env

System environment variables

map

A value from a MapMessage

sd

A value from a StructuredDataMessage. The key "id"
will return the name of the StructuredDataId without
the enterprise number. The key "type" will return the
message type. Other keys will retrieve individual
elements from the Map.

sys

System properties

A default property map can be declared in the configuration file. If the value cannot be located in
the specified lookup the value in the default property map will be used. The default map is prepopulated with a value for "hostName" that is the current system's host name or IP address and the
"contextName" with is the value of the current logging context.
An interesting feature of StrLookup processing is that when a variable reference is declared with
multiple leading '$' characters each time the variable is resolved the leading '$' is simply removed. In
the previous example the "Routes" element is capable of resolving the variable at runtime. To allow
this the prefix value is specified as a variable with two leading '$' characters. When the configuration
file is first processed the first variable is simply removed. Thus, when the Routes element is evaluated
at runtime it is the variable declaration "${sd:type}" which causes the event to be inspected for a
StructuredDataMessage and if one is present the value of its type attribute to be used as the routing
key. Not all elements support resolving variables at runtime. Components that do will specifically call
that out in their documentation.
If no value is found for the key in the Lookup associated with the prefix then the value associated
with the key in the properties declaration in the configuration file will be used. If no value is found the
variable declaration will be returned as the value. Default values may be declared in the configuration
by doing:



Audit

...


As a footnote, it is worth pointing out that the variables in the RollingFile appender declaration will
also not be evaluated when the configuration is processed. This is simply because the resolution

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

5 Configuration

35

of the whole RollingFile element is deferred until a match occurs. See RoutingAppender for more
information.

5.1.7 Status Messages

Just as it is desirable to be able to diagnose problems in applications, it is frequently necessary to
be able to diagnose problems in the logging configuration or in the configured components. Since
logging has not been configured, "normal" logging cannot be used during initialization. In addition,
normal logging within appenders could create infinite recursion which Log4j will detect and cause the
recursive events to be ignored. To accomodate this need, the Log4j 2 API includes a StatusLogger.
Components declare an instance of the StatusLogger similar to:
protected final static Logger logger = StatusLogger.getLogger();

Since StatusLogger implements the Log4j 2 API's Logger interface, all the normal Logger methods
may be used.
When configuring Log4j it is sometimes necessary to view the generated status events. This can be
accomplished by adding the status attribute to the configuration element or a default value can be
provided by setting the "Log4jDefaultStatusLevel" system property. The following configuration has
the status attribute set to debug.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

5 Configuration

;


target/rolling1/rollingtest-$${sd:type}.log














%d %p %c{1.} [%t] %m%n



















During startup this configuration produces:

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

36

5 Configuration

37

2011-11-23 17:08:00,769 DEBUG Generated plugins in 0.003374000 seconds
2011-11-23 17:08:00,789 DEBUG Calling createProperty on class org.apache.logging.log4j.core.
config.Property for element property with params(name="filename",
value="target/rolling1/rollingtest-${sd:type}.log")
2011-11-23 17:08:00,792 DEBUG Calling configureSubstitutor on class org.apache.logging.log4j.
core.config.plugins.PropertiesPlugin for element properties with
params(properties={filename=target/rolling1/rollingtest-${sd:type}.log})
2011-11-23 17:08:00,794 DEBUG Generated plugins in 0.001362000 seconds
2011-11-23 17:08:00,797 DEBUG Calling createFilter on class org.apache.logging.log4j.core.
filter.ThresholdFilter for element ThresholdFilter with params(level="debug",
onMatch="null", onMismatch="null")
2011-11-23 17:08:00,800 DEBUG Calling createLayout on class org.apache.logging.log4j.core.
layout.PatternLayout for element PatternLayout with params(pattern="%m%n",
Configuration(RoutingTest), null, charset="null")
2011-11-23 17:08:00,802 DEBUG Generated plugins in 0.001349000 seconds
2011-11-23 17:08:00,804 DEBUG Calling createAppender on class org.apache.logging.log4j.core.
appender.ConsoleAppender for element Console with params(PatternLayout(%m%n), null,
target="null", name="STDOUT", ignoreExceptions="null")
2011-11-23 17:08:00,804 DEBUG Calling createFilter on class org.apache.logging.log4j.core.
filter.ThresholdFilter for element ThresholdFilter with params(level="debug",
onMatch="null", onMismatch="null")
2011-11-23 17:08:00,806 DEBUG Calling createAppender on class org.apache.logging.log4j.test.
appender.ListAppender for element List with params(name="List", entryPerNewLine="null",
raw="null", null, ThresholdFilter(DEBUG))
2011-11-23 17:08:00,813 DEBUG Calling createRoute on class org.apache.logging.log4j.core.appender.
routing.Route for element Route with params(AppenderRef="null", key="null", Node=Route)
2011-11-23 17:08:00,823 DEBUG Calling createRoute on class org.apache.logging.log4j.core.appender.
routing.Route for element Route with params(AppenderRef="STDOUT", key="Audit", Node=Route)
2011-11-23 17:08:00,824 DEBUG Calling createRoute on class org.apache.logging.log4j.core.appender.
routing.Route for element Route with params(AppenderRef="List", key="Service", Node=Route)
2011-11-23 17:08:00,825 DEBUG Calling createRoutes on class org.apache.logging.log4j.core.appender.
routing.Routes for element Routes with params(pattern="${sd:type}",
routes={Route(type=dynamic default), Route(type=static Reference=STDOUT key='Audit'),
Route(type=static Reference=List key='Service')})
2011-11-23 17:08:00,827 DEBUG Calling createAppender on class org.apache.logging.log4j.core.appender.
routing.RoutingAppender for element Routing with params(name="Routing",
ignoreExceptions="null", Routes({Route(type=dynamic default),Route(type=static
Reference=STDOUT key='Audit'),
Route(type=static Reference=List key='Service')}), Configuration(RoutingTest), null, null)
2011-11-23 17:08:00,827 DEBUG Calling createAppenders on class org.apache.logging.log4j.core.config.
plugins.AppendersPlugin for element appenders with params(appenders={STDOUT, List, Routing})
2011-11-23 17:08:00,828 DEBUG Calling createAppenderRef on class org.apache.logging.log4j.core.
config.plugins.AppenderRefPlugin for element AppenderRef with params(ref="Routing")
2011-11-23 17:08:00,829 DEBUG Calling createLogger on class org.apache.logging.log4j.core.config.
LoggerConfig for element logger with params(additivity="false", level="info", name="EventLogger",
AppenderRef={Routing}, null)
2011-11-23 17:08:00,830 DEBUG Calling createAppenderRef on class org.apache.logging.log4j.core.
config.plugins.AppenderRefPlugin for element AppenderRef with params(ref="STDOUT")

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

5 Configuration

38

2011-11-23 17:08:00,831 DEBUG Calling createLogger on class org.apache.logging.log4j.core.config.
LoggerConfig$RootLogger for element root with params(additivity="null", level="error",
AppenderRef={STDOUT}, null)
2011-11-23 17:08:00,833 DEBUG Calling createLoggers on class org.apache.logging.log4j.core.
config.plugins.LoggersPlugin for element loggers with params(loggers={EventLogger, root})
2011-11-23 17:08:00,834 DEBUG Reconfiguration completed
2011-11-23 17:08:00,846 DEBUG Calling createLayout on class org.apache.logging.log4j.core.
layout.PatternLayout for element PatternLayout with params(pattern="%d %p %c{1.} [%t] %m%n",
Configuration(RoutingTest), null, charset="null")
2011-11-23 17:08:00,849 DEBUG Calling createPolicy on class org.apache.logging.log4j.core.
appender.rolling.SizeBasedTriggeringPolicy for element SizeBasedTriggeringPolicy with
params(size="500")
2011-11-23 17:08:00,851 DEBUG Calling createAppender on class org.apache.logging.log4j.core.
appender.RollingFileAppender for element RollingFile with
params(fileName="target/rolling1/rollingtest-Unknown.log",
filePattern="target/rolling1/test1-Unknown.%i.log.gz", append="null", name="Rolling-Unknown",
bufferedIO="null", immediateFlush="null",
SizeBasedTriggeringPolicy(SizeBasedTriggeringPolicy(size=500)), null,
PatternLayout(%d %p %c{1.} [%t] %m%n), null, ignoreExceptions="null")
2011-11-23 17:08:00,858 DEBUG Generated plugins in 0.002014000 seconds
2011-11-23 17:08:00,889 DEBUG Reconfiguration started for context sun.misc.
Launcher$AppClassLoader@37b90b39
2011-11-23 17:08:00,890 DEBUG Generated plugins in 0.001355000 seconds
2011-11-23 17:08:00,959 DEBUG Generated plugins in 0.001239000 seconds
2011-11-23 17:08:00,961 DEBUG Generated plugins in 0.001197000 seconds
2011-11-23 17:08:00,965 WARN No Loggers were configured, using default
2011-11-23 17:08:00,976 DEBUG Reconfiguration completed

If the status attribute is set to error than only error messages will be written to the console. This makes
troubleshooting configuration errors possible. As an example, if the configuration above is changed to
have the status set to error and the logger declaration is:




the following error message will be produced.
2011-11-24 23:21:25,517 ERROR Unable to locate appender Routng for logger EventLogger

Applications may wish to direct the status output to some other destination. This can be accomplished
by setting the dest attribute to either "err" to send the output to stderr or to a file location or URL. This
can also be done by insuring the configured status is set to OFF and then configuring the application
programmatically such as:
StatusConsoleListener listener = new StatusConsoleListener(Level.ERROR);
((StatusLogger) logger).registerListener(listener);

5.1.8 Testing in Maven

Maven can run unit and functional tests during the build cycle. By default, any files placed in src/
test/resources are automatically copied to target/test-classes and are included in the classpath

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

5 Configuration

39

during execution of any tests. As such, placing a log4j2-test.xml into this directory will cause it to be
used instead of a log4j2.xml or log4j2.json that might be present. Thus a different log configuration
can be used during testing than what is used in production.
A second approach, which is extensively used by Log4j 2, is to set the log4j.configurationFile
property in the method annotated with @BeforeClass in the junit test class. This will allow an
arbitrarily named file to be used during the test.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

6 Web Applications and JSPs

40

6 Web Applications and JSPs

.......................................................................................................................................
6.1 Using Log4j 2 in Web Applications
You must take particular care when using Log4j or any other logging framework within a Java EE
web application. It's important for logging resources to be properly cleaned up (database connections
closed, files closed, etc.) when the container shuts down or the web application is undeployed.
Because of the nature of class loaders within web applications, Log4j resources cannot be cleaned up
through normal means. Log4j must be "started" when the web application deploys and "shut down"
when the web application undeploys. How this works varies depending on whether your application is
a Servlet 3.0 or newer or Servlet 2.5 web application.

6.1.1 Servlet 3.0 and Newer Web Applications

A Servlet 3.0 or newer web application is any  whose version attribute has a value
of "3.0" or higher. Of course, the application must also be running in a compatible web container.
Some examples are: Tomcat 7.0 and higher, GlassFish 3.0 and higher, JBoss 7.0 and higher, Oracle
WebLogic 12c and higher, and IBM WebSphere 8.0 and higher.
The Short Story
Log4j 2 "just works" in Servlet 3.0 and newer web applications. It is capable of automatically starting
when the application deploys and shutting down when the application undeploys.
Important Note! For performance reasons, containers often ignore certain JARs known not to
contain TLDs or ServletContainerInitializers and do not scan them for web-fragments and
initializers. Importantly, Tomcat 7 <7.0.43 ignores all JAR files named log4j*.jar, which prevents this
feature from working. This has been fixed in Tomcat 7.0.43, Tomcat 8, and later. In Tomcat 7 <7.0.43
you will need to change catalina.properties and remove "log4j*.jar" from the jarsToSkip
property. You may need to do something similar on other containers if they skip scanning Log4j JAR
files.
The Long Story
The Log4j 2 Core JAR file is a web-fragment configured to order before any other web
fragments in your application. It contains a ServletContainerInitializer (
Log4jServletContainerInitializer) that the container automatically discovers and initializes. This adds
the Log4jServletContextListener and Log4jServletFilter to the ServletContext. These classes
properly initialize and deinitialize the Log4j configuration.
For some users, automatically starting Log4j is problematic or undesirable. You can easily disable
this feature using the isLog4jAutoInitializationDisabled context parameter. Simply add it
to your deployment descriptor with the value "true" to disable auto-initialization. You must define the
context parameter in web.xml. If you set in programmatically, it will be too late for Log4j to detect
the setting.

isLog4jAutoInitializationDisabled
true


Once you disable auto-initialization, you must initialize Log4j as you would a Servlet 2.5 web
application. You must do so in a way that this initialization happens before any other application code
(such as Spring Framework startup code) executes.
You can customize the behavior of the listener and filter using the log4jContextName,
log4jConfiguration, and/or isLog4jContextSelectorNamed context parameters. Read

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

6 Web Applications and JSPs

41

more about this in the Context Parameters section below. You must not manually configure the
Log4jServletContextListener or Log4jServletFilter in your deployment descriptor (
web.xml) or in another initializer or listener in a Servlet 3.0 or newer application unless you disable
auto-initialization with isLog4jAutoInitializationDisabled. Doing so will result in startup
errors and unspecified erroneous behavior.

6.1.2 Servlet 2.5 Web Applications

A Servlet 2.5 web application is any  whose version attribute has a value of "2.5." The
version attribute is the only thing that matters; even if the web application is running in a Servlet
3.0 or newer container, it is a Servlet 2.5 web application if the version attribute is "2.5." Note that
Log4j 2 does not support Servlet 2.4 and older web applications.
If you are using Log4j in a Servlet 2.5 web application, or if you have disabled auto-initialization
with the isLog4jAutoInitializationDisabled context parameter, you must configure
the Log4jServletContextListener and Log4jServletFilter in the deployment descriptor or
programmatically. The filter should match all requests of any type. The listener should be the very
first listener defined in your application, and the filter should be the very first filter defined and
mapped in your application. This is easily accomplished using the following web.xml code:

org.apache.logging.log4j.core.web.Log4jServletContextListener



log4jServletFilter
org.apache.logging.log4j.core.web.Log4jServletFilter


log4jServletFilter
/*
REQUEST
FORWARD
INCLUDE
ERROR
ASYNC





%d %p %c{1.} [%t] %m %ex%n










When AsyncLoggerContextSelector is used to make all loggers asynchronous, make sure to use
normal  and  elements in the configuration. The AsyncLoggerContextSelector will
ensure that all loggers are asynchronous, using a mechanism that is different from what happens when
you configure  or . The latter elements are intended for mixing async
with sync loggers. If you use both mechanisms together you will end up with two background threads,
where your application passes the log message to thread A, which passes the message to thread B,
which then finally logs the message to disk. This works, but there will be an unnecessary step in the
middle.
There are a few system properties you can use to control aspects of the asynchronous logging
subsystem. Some of these can be used to tune logging performance.
System Property

Default Value

Description

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

12 Async Loggers

AsyncLogger.ExceptionHandler

141

null

Fully qualified name of a
class that implements the

com.lmax.disruptor.ExceptionHandler
interface. The class needs to have
a public zero-argument constructor.
If specified, this class will be
notified when an exception occurs
while logging the messages.
AsyncLogger.RingBufferSize

256 * 1024

Size (number of slots) in
the RingBuffer used by the
asynchronous logging subsystem.
Make this value large enough
to deal with bursts of activity.
The minimum size is 128. The
RingBuffer will be pre-allocated
at first use and will never grow or
shrink during the life of the system.

AsyncLogger.WaitStrategy

Sleep

Valid values: Block, Sleep, Yield.
Block is a strategy that uses
a lock and condition variable
for the I/O thread waiting for
log events. Block can be used
when throughput and low-latency
are not as important as CPU
resource. Recommended for
resource constrained/virtualised
environments.
Sleep is a strategy that initially
spins, then uses a Thread.yield(),
and eventually parks for the
minimum number of nanos the OS
and JVM will allow while the I/O
thread is waiting for log events.
Sleep is a good compromise
between performance and CPU
resource. This strategy has very
low impact on the application
thread, in exchange for some
additional latency for actually
getting the message logged.
Yield is a strategy that uses a
Thread.yield() for waiting for log
events after an initially spinning.
Yield is a good compromise
between performance and CPU
resource, but may use more CPU
than Sleep in order to get the
message logged to disk sooner.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

12 Async Loggers

142

AsyncLogger.ThreadNameStrategy

CACHED

Valid values: CACHED,
UNCACHED.
By default, AsyncLogger caches
the thread name in a threadlocal
variable to improve performance.
Specify the UNCACHED option
if your application modifies the
thread name at runtime (with

Thread.currentThread().setName())
and you want to see the new thread
name reflected in the log.
log4j.Clock

SystemClock

Implementation of the

org.apache.logging.log4j.core.helpers
interface that is used for
timestamping the log events when
all loggers are asynchronous.
By default,

System.currentTimeMillis
is called on every log event.
CachedClock is an optimization
where time stamps are generated
from a clock that updates its
internal time in a background
thread once every millisecond, or
every 1024 log events, whichever
comes first. This reduces logging
latency a little, at the cost of
some precision in the logged time
stamps. Unless you are logging
many events, you may see "jumps"
of 10-16 milliseconds between log
time stamps.
You can also specify a fully
qualified class name of a custom
class that implements the Clock
interface.

System Properties to configure all asynchronous loggers

12.1.3 Mixing Synchronous and Asynchronous Loggers

Requires disruptor-3.0.0.jar or higher on the classpath. There is no need to set system property
"Log4jContextSelector" to any value.
Synchronous and asynchronous loggers can be combined in configuration. This gives you more
flexibility at the cost of a slight loss in performance (compared to making all loggers asynchronous).
Use the  or  configuration elements to specify the loggers that need to
be asynchronous. The same configuration file can also contain  and  elements for
the synchronous loggers.
By default, location is not passed to the I/O thread by asynchronous loggers. If one of your layouts or
custom filters needs location information, you need to set "includeLocation=true" in the configuration
of all relevant loggers, including the root logger.
A configuration that mixes asynchronous loggers might look like:

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

12 Async Loggers

143








%d %p %class{1.} [%t] %location %m %ex%n














There are a few system properties you can use to control aspects of the asynchronous logging
subsystem. Some of these can be used to tune logging performance.
System Property

Default Value

AsyncLoggerConfig.ExceptionHandlernull

Description
Fully qualified name of a
class that implements the

com.lmax.disruptor.ExceptionHandler
interface. The class needs to have
a public zero-argument constructor.
If specified, this class will be
notified when an exception occurs
while logging the messages.
AsyncLoggerConfig.RingBufferSize

256 * 1024

Size (number of slots) in
the RingBuffer used by the
asynchronous logging subsystem.
Make this value large enough
to deal with bursts of activity.
The minimum size is 128. The
RingBuffer will be pre-allocated
at first use and will never grow or
shrink during the life of the system.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

12 Async Loggers

AsyncLoggerConfig.WaitStrategy

144

Sleep

Valid values: Block, Sleep, Yield.
Block is a strategy that uses
a lock and condition variable
for the I/O thread waiting for
log events. Block can be used
when throughput and low-latency
are not as important as CPU
resource. Recommended for
resource constrained/virtualised
environments.
Sleep is a strategy that initially
spins, then uses a Thread.yield(),
and eventually parks for the
minimum number of nanos the OS
and JVM will allow while the I/O
thread is waiting for log events.
Sleep is a good compromise
between performance and CPU
resource. This strategy has very
low impact on the application
thread, in exchange for some
additional latency for actually
getting the message logged.
Yield is a strategy that uses a
Thread.yield() for waiting for log
events after an initially spinning.
Yield is a good compromise
between performance and CPU
resource, but may use more CPU
than Sleep in order to get the
message logged to disk sooner.

System Properties to configure mixed asynchronous and normal loggers

12.1.4 Location, location, location...

If one of the layouts is configured with a location-related attribute like HTML locationInfo, or one of
the patterns %C or $class, %F or %file, %l or %location, %L or %line, %M or %method, Log4j
will take a snapshot of the stack, and walk the stack trace to find the location information.
This is an expensive operation: 1.3 - 5 times slower for synchronous loggers. Synchronous loggers
wait as long as possible before they take this stack snapshot. If no location is required, the snapshot
will never be taken.
However, asynchronous loggers need to make this decision before passing the log message to another
thread; the location information will be lost after that point. The performance impact of taking a stack
trace snapshot is even higher for asynchronous loggers: logging with location is 4 - 20 times slower
than without location. For this reason, asynchronous loggers and asynchronous appenders do not
include location information by default.
You can override the default behaviour in your logger or asynchronous appender configuration by
specifying includeLocation="true".

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

12 Async Loggers

145

12.1.5 Asynchronous Logging Performance

The performance results below were all derived from running the PerfTest, MTPerfTest and
PerfTestDriver classes which can be found in the Log4j 2 unit test source directory. All tests were
done using the default settings (SystemClock and SleepingWaitStrategy). The methodology used was
the same for all tests:
• First, warm up the JVM by logging 200,000 log messages of 500 characters.
• Repeat the warm-up 10 times, then wait 10 seconds for the I/O thread to catch up and buffers to
drain.
• Latency test: at less than saturation, measure how long a call to Logger.log takes. Pause for 10
microseconds * threadCount between measurements. Repeat this 5 million times, and measure
average latency, latency of 99% of observations and 99.99% of observations.
• Throughput test: measure how long it takes to execute 256 * 1024 / threadCount calls to
Logger.log and express the result in messages per second.
• Repeat the test 5 times and average the results.
The results below were obtained with log4j-2.0-beta5, disruptor-3.0.0.beta3, log4j-1.2.17 and
logback-1.0.10.
12.1.5.1 Logging Throughput

The graph below compares the throughput of synchronous loggers, asynchronous appenders and
asynchronous loggers. This is the total throughput of all threads together. In the test with 64 threads,
asynchronous loggers are 12 times faster than asynchronous appenders, and 68 times faster than
synchronous loggers.
Asynchronous loggers' throughput increases with the number of threads, whereas both synchronous
loggers and asynchronous appenders have more or less constant throughput regardless of the number
of threads that are doing the logging.

12.1.5.2 Asynchronous Throughput Comparison with Other Logging Packages

We also compared throughput of asynchronous loggers to the synchronous loggers and asynchronous
appenders available in other logging packages, specifically log4j-1.2.17 and logback-1.0.10, with
similar results. For asynchronous appenders, total logging throughput of all threads together remains

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

12 Async Loggers

146

roughly constant when adding more threads. Asynchronous loggers make more effective use of the
multiple cores available on the machine in multi-threaded scenarios.

On Solaris 10 (64bit) with JDK1.7.0_06, 4-core Xeon X5570 dual CPU @2.93Ghz with
hyperthreading switched on (16 virtual cores):

Logger

1 thread

2 threads

4 threads

8 threads

16
threads

32
threads

64
threads

Log4j 2:
Loggers all
asynchronous

2,652,412

909,119

776,993

516,365

239,246

253,791

288,997

Log4j 2:
Loggers
mixed sync/
async

2,454,358

839,394

854,578

597,913

261,003

216,863

218,937

Log4j 2:
Async
Appender

1,713,429

603,019

331,506

149,408

86,107

45,529

23,980

Log4j1:
Async
Appender

2,239,664

494,470

221,402

109,314

60,580

31,706

14,072

Logback:
Async
Appender

2,206,907

624,082

307,500

160,096

85,701

43,422

21,303

Log4j 2:
Synchronous

273,536

136,523

67,609

34,404

15,373

7,903

4,253

Log4j1:
Synchronous

326,894

105,591

57,036

30,511

13,900

7,094

3,509

Logback:
Synchronous

178,063

65,000

34,372

16,903

8,334

3,985

1,967

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

12 Async Loggers

147

Throughput per thread in messages/second
On Windows 7 (64bit) with JDK1.7.0_11, 2-core Intel i5-3317u CPU @1.70Ghz with hyperthreading
switched on (4 virtual cores):
Logger

1 thread

Log4j 2:
Loggers all
asynchronous

2 threads

4 threads

8 threads

16 threads

32 threads

1,715,344

928,951

1,045,265

1,509,109

1,708,989

773,565

571,099

1,204,774

1,632,204

1,368,041

462,093

908,529

Log4j 2:
Async
Appender

1,236,548

1,006,287

511,571

302,230

160,094

60,152

Log4j1: Async
Appender

1,373,195

911,657

636,899

406,405

202,777

162,964

Logback:
Async
Appender

1,979,515

783,722

582,935

289,905

172,463

133,435

Log4j 2:
Synchronous

281,250

225,731

129,015

66,590

34,401

17,347

Log4j1:
Synchronous

147,824

72,383

32,865

18,025

8,937

4,440

Logback:
Synchronous

149,811

66,301

32,341

16,962

8,431

3,610

Log4j 2:
Loggers
mixed sync/
async

Throughput per thread in messages/second
12.1.5.3 Throughput of Logging With Location (includeLocation="true")

On Solaris 10 (64bit) with JDK1.7.0_06, 4-core Xeon X5570 dual CPU @2.93Ghz with
hyperthreading switched off (8 virtual cores):
Logger (Log4j 2)

1 thread

2 threads

4 threads

8 threads

Loggers all
asynchronous

75,862

88,775

80,240

68,077

Loggers mixed sync/
async

61,993

66,164

55,735

52,843

Async Appender

47,033

52,426

50,882

36,905

Synchronous

31,054

33,175

29,791

23,628

Throughput in log messages/second per thread
As expected, logging location information has a large performance impact. Asynchronous loggers
are 4 - 20 times slower, while synchronous loggers are 1.3 - 5 times slower. However, if you do need
location information, asynchronous logging will still be faster than synchronous logging.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

12 Async Loggers

148

12.1.5.4 Latency

Latency tests are done by logging at less than saturation, measuring how long a call to Logger.log
takes to return. After each call to Logger.log, the test waits for 10 microseconds * threadCount before
continuing. Each thread logs 5 million messages.
All the latency measurements below are results of tests run on Solaris 10 (64bit) with JDK1.7.0_06, 4core Xeon X5570 dual CPU @2.93Ghz with hyperthreading switched on (16 virtual cores).

Note that this is log-scale, not linear. The above graph compares the latency distributions of an
asynchronous logger and a Log4j 1.2.17 Async Appender. This shows the latency of one thread
during a test where 64 threads are logging in parallel. The test was run once for the async logger and
once for the async appender.

Average
latency

99%
99.99%
observations observations
less than
less than

1 thread

64 threads

1 thread

64 threads

1 thread

64 threads

Log4j 2:
Loggers all
async

677

4,135

1,638

4,096

8,192

16,128

Log4j 2:
Loggers
mixed sync/
async

648

4,873

1,228

4,096

8,192

16,384

2,423

2,117,722

4,096

67,108,864

16,384

268,435,456

Log4j 2:
Async
Appender

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

12 Async Loggers

149

Log4j1: Async
Appender

1,562

1,781,404

4,096

109,051,904

16,384

268,435,456

Logback:
Async
Appender

2,123

2,079,020

3,276

67,108,864

14,745

268,435,456

Latency of a call to Logger.log() in nanoseconds
The latency comparison graph below is also log-scale, and shows the average latency of asynchronous
loggers and ArrayBlockingQueue-based asynchronous appenders in scenarios with more and more
threads running in parallel. Up to 8 threads asynchronous appenders have comparable average
latency, two or three times that of asynchronous loggers. With more threads, the average latency of
asynchronous appenders is orders of magnitude larger than asynchronous loggers.

Applications interested in low latency often care not only about average latency, but also about worstcase latency. The graph below shows that asynchronous loggers also do better when comparing
the maximum latency of 99.99% of observations with other logging methods. When increasing the
number of threads the vast majority of latency measurements for asynchronous loggers stay in the
10-20 microseconds range where Asynchronous Appenders start experiencing many latency spikes in
the 100 millisecond range, a difference of four orders of magnitude.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

12 Async Loggers

150

12.1.5.5 FileAppender vs. RandomAccessFileAppender

The appender comparison below was done with synchronous loggers.
On Windows 7 (64bit) with JDK1.7.0_11, 2-core Intel i5-3317u CPU @1.70Ghz with hyperthreading
switched on (4 virtual cores):
Appender

1 thread

2 threads

4 threads

8 threads

RandomAccessFileAppender

250,438

169,939

109,074

58,845

FileAppender

186,695

118,587

57,012

28,846

RollingRandomAccessFileAppender278,369

213,176

125,300

63,103

RollingFileAppender

114,690

55,147

28,153

182,518

Throughput per thread in messages/second
On Solaris 10 (64bit) with JDK1.7.0_06, 4-core dual Xeon X5570 CPU @2.93GHz with
hyperthreading switched off (8 virtual cores):
Appender

1 thread

2 threads

4 threads

8 threads

RandomAccessFileAppender

240,760

128,713

66,555

30,544

FileAppender

172,517

106,587

55,885

25,675

RollingRandomAccessFileAppender228,491

135,355

69,277

32,484

97,737

55,766

25,097

RollingFileAppender

186,422

Throughput per thread in messages/second

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

12 Async Loggers

151

12.1.6 Under The Hood

Asynchronous Loggers are implemented using the LMAX Disruptor inter-thread messaging library.
From the LMAX web site:
... using queues to pass data between stages of the system was introducing latency, so we focused
on optimising this area. The Disruptor is the result of our research and testing. We found that cache
misses at the CPU-level, and locks requiring kernel arbitration are both extremely costly, so we
created a framework which has "mechanical sympathy" for the hardware it's running on, and that's
lock-free.
LMAX Disruptor internal performance comparisons with
java.util.concurrent.ArrayBlockingQueue can be found here.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

13 JMX

152

13 JMX

.......................................................................................................................................
13.1 JMX
Log4j 2 has built-in support for JMX. The StatusLogger, ContextSelector, and all LoggerContexts,
LoggerConfigs and Appenders are instrumented with MBeans and can be remotely monitored and
controlled.
Also included is a simple client GUI that can be used to monitor the StatusLogger output, as well as
to remotely reconfigure Log4j with a different configuration file, or to edit the current configuration
directly.

13.2 Enabling JMX
JMX support is enabled by default. When Log4j initializes, the StatusLogger, ContextSelector,
and all LoggerContexts, LoggerConfigs and Appenders are instrumented with MBeans. To
disable JMX completely, and prevent these MBeans from being created, specify system property
log4j2.disable.jmx=true when you start the Java VM.

13.2.1 Local Monitoring and Management

To perform local monitoring you don't need to specify any system properties. The JConsole tool
that is included in the Java JDK can be used to monitor your application. Start JConsole by typing
$JAVA_HOME/bin/jconsole in a command shell. For more details, see Oracle's documentation on
how to use JConsole.

13.2.2 Remote Monitoring and Management

To enable monitoring and management from remote systems, set the following system property when
starting the Java VM.
com.sun.management.jmxremote.port=portNum

In the property above, portNum is the port number through which you want to enable JMX RMI
connections.
For more details, see Oracle's documentation on Remote Monitoring and Management.

13.3 Log4j Instrumented Components
The best way to find out which methods and attributes of the various Log4j components are accessible
via JMX is to look at the Javadoc or by exploring directly in JConsole.
The screenshot below shows the Log4j MBeans in JConsole.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

13 JMX

153

13.4 Client GUI
Log4j includes a basic client GUI that can be used to monitor the StatusLogger output and to remotely
modify the Log4j configuration. The client GUI can be run as a stand-alone application or as a
JConsole plug-in.
13.4.1 Running the Client GUI as a JConsole Plug-in

To run the Log4j JMX Client GUI as a JConsole Plug-in, start JConsole with the following command:
$JAVA_HOME/bin/jconsole -pluginpath /path/to/log4j-core-2.0.jar:/path/to/
log4j-jmx-gui-2.0.jar

or on Windows:
%JAVA_HOME%\bin\jconsole -pluginpath \path\to\log4j-core-2.0.jar;\path\to
\log4j-jmx-gui-2.0.jar

If you execute the above command and connect to your application, you will see an extra "Log4j 2"
tab in the JConsole window. This tab contains the client GUI, with the StatusLogger selected. The
screenshot below shows the StatusLogger panel in JConsole.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

13 JMX

13.4.2 Remotely Editing the Log4j Configuration

The client GUI also contains a simple editor that can be used to remotely change the Log4j
configuration.
The screenshot below shows the configuration edit panel in JConsole.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

154

13 JMX

155

The configuration edit panel provides two ways to modify the Log4j configuration: specifying a
different configuration location URI, or modifying the configuration XML directly in the editor panel.
If you specify a different configuration location URI and click the "Reconfigure from Location"
button, the specified file or resource must exist and be readable by the application, or an error will
occur and the configuration will not change. If an error occurred while processing the contents of
the specified resource, Log4j will keep its original configuration, but the editor panel will show the
contents of the file you specified.
The text area showing the contents of the configuration file is editable, and you can directly modify
the configuration in this editor panel. Clicking the "Reconfigure with XML below" button will send
the configuration text to the remote application where it will be used to reconfigure Log4j on the fly.
This will not overwrite any configuration file. Reconfiguring with text from the editor happens in
memory only and the text is not permanently stored anywhere.

13.4.3 Running the Client GUI as a Stand-alone Application

To run the Log4j JMX Client GUI as a stand-alone application, run the following command:

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

13 JMX

156

$JAVA_HOME/bin/java -cp /path/to/log4j-core-2.0.jar:/path/to/log4j-jmxgui-2.0.jar org.apache.logging.log4j.jmx.gui.ClientGUI 

or on Windows:
%JAVA_HOME%\bin\java -cp \path\to\log4j-core-2.0.jar;\path\to\log4j-jmxgui-2.0.jar org.apache.logging.log4j.jmx.gui.ClientGUI 

Where options are one of the following:
• :
• service:jmx:rmi:///jndi/rmi://:/jmxrmi
• service:jmx:rmi://:/jndi/rmi://:/jmxrmi
The port number must be the same as the portNum specified when you started the application you
want to monitor.
For example, if you started your application with these options:
com.sun.management.jmxremote.port=33445
com.sun.management.jmxremote.authenticate=false
com.sun.management.jmxremote.ssl=false

(Note that this disables all security so this is not recommended for production environments.
Oracle's documentation on Remote Monitoring and Management provides details on how to
configure JMX more securely with password authentication and SSL.)
Then you can run the client with this command:
$JAVA_HOME/bin/java -cp /path/to/log4j-core-2.0.jar:/path/to/log4j-jmxgui-2.0.jar org.apache.logging.log4j.jmx.gui.ClientGUI localhost:33445

or on Windows:
%JAVA_HOME%\bin\java -cp \path\to\log4j-core-2.0.jar;\path\to\log4j-jmxgui-2.0.jar org.apache.logging.log4j.jmx.gui.ClientGUI localhost:33445

The screenshot below shows the StatusLogger panel of the client GUI when running as a stand-alone
application.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

13 JMX

157

The screenshot below shows the configuration editor panel of the client GUI when running as a standalone application.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

13 JMX

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

158

14 Logging Separation

159

14 Logging Separation

.......................................................................................................................................
14.1 Logging Separation
There are many well known use cases where applications may share an environment with other
applications and each has a need to have its own, separate logging environment. This purpose of this
section is to discuss some of these cases and ways to accomplish this.

14.1.1 Use Cases

This section describes some of the use cases where Log4j could be used and what its desired behavior
might be.
14.1.1.1 Standalone Application

Standalone applications are usually relatively simple. They typically have one bundled executable that
requires only a single logging configuration.
14.1.1.2 Web Applications

A typical web application will be packaged as a WAR file and will include all of its dependencies in
WEB-INF/lib and will have its configuration file located in the class path or in a location configured
in the web.xml. Be sure to follow the instructions to initialize Log4j 2 in a web application.
14.1.1.3 Java EE Applications

A Java EE application will consist of one or more WAR files and possible some EJBs, typically all
packaged in an EAR file. Usually, it is desirable to have a single configuration that applies to all the
components in the EAR. The logging classes will generally be placed in a location shared across all
the components and the configuration needs to also be shareable. Be sure to follow the instructions to
initialize Log4j 2 in a web application.
14.1.1.4 "Shared" Web Applications and REST Service Containers

In this scenario there are multiple WAR files deployed into a single container. Each of the
applications should use the same logging configuration and share the same logging implementation
across each of the web applications. When writing to files and streams each of the applications should
share them to avoid the issues that can occur when multiple components try to write to the same
file(s) through different File objects, channels, etc.

14.1.2 Approaches
14.1.2.1 The Simple Approach

The simplest approach for separating logging within applications is to package each application
with its own copy of Log4j and to use the BasicContextSelector. While this works for standalone
applications and may work for web applications and possibly Java EE applications, it does not work
at all in the last case. However, when this approach does work it should be used as it is ultimately the
simplest and most straightforward way of implementing logging.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

14 Logging Separation

160

14.1.2.2 Using Context Selectors

There are a few patterns for achieving the desired state of logging separation using ContextSelectors:
1. Place the logging jars in the container's classpath and set the system property
"Log4jContextSelector" to "org.apache.logging.log4j.core.selector.BasicContextSelector". This
will create a single LoggerContext using a single configuration that will be shared across all
applications.
2. Place the logging jars in the container's classpath and use the default
ClassLoaderContextSelector. Follow the instructions to initialize Log4j 2 in a web application.
Each application can be configured to share the same configuration used at the container or can
be individually configured. If status logging is set to debug in the configuration there will be
output from when logging is initialized in the container and then again in each web application.
3. Follow the instructions to initialize Log4j 2 in a web application and set the system property
"Log4jContextSelector" to "org.apache.logging.log4j.core.selector.JNDIContextSelector." This
will cause the container to use JNDI to locate each web application's LoggerContext. Be
sure to set the isLog4jContextSelectorNamed context parameter to true and also set the
log4jContextName and log4jConfiguration context parameters.
The exact method for setting system properties depends on the container. For Tomcat, edit
$CATALINA_HOME/conf/catalina.properties. Consult the documentation for other web containers.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

15 Extending Log4j

161

15 Extending Log4j

.......................................................................................................................................
15.1 Extending Log4j
Log4j 2 provides numerous ways that it can be manipulated and extended. This section includes an
overview of the various ways that are directly supported by the Log4j 2 implementation.
15.1.1 LoggerContextFactory

The LoggerContextFactory binds the Log4j API to its implementation. The Log4j LogManager
locates a LoggerContextFactory by locating all instances of META-INF/log4j-provider.xml, a file that
conforms to the java.util.Properties DTD, and then inspecting each to verify that it specifies a value
for the "Log4jAPIVersion" property that conforms to the version required by the LogManager. If
more than one valid implementation is located the value for "FactoryPriority" will be used to identify
the factory with the highest priority. Finally, the value of the "LoggerContextFactory" property will be
used to locate the LoggerContextFactory. In Log4j 2 this is provided by Log4jContextFactory.
Applications may change the LoggerContextFactory that will be used by
1. Implementing a new LoggerContextFactory and creating a log4j-provider.xml to reference it
making sure that it has the highest priority.
2. Create a new log4j-provider.xml and configure it with the desired LoggerContextFactory making
sure that it has the highest priority.
3. Setting the system property "log4j2.loggerContextFactory" to the name of the
LoggerContextFactory class to use.
4. Setting the property "log4j2.loggerContextFactory" in a properties file named
"log4j2.LogManager.properties" to the name of the LoggerContextFactory class to use. The
properties file must be on the classpath.
15.1.2 ContextSelector

ContextSelectors are called by the Log4j LoggerContext factory. They perform the actual
work of locating or creating a LoggerContext, which is the anchor for Loggers and their
configuration. ContextSelectors are free to implement any mechanism they desire to manage
LoggerContexts. The default Log4jContextFactory checks for the presence of a System Property
named "Log4jContextSelector". If found, the property is expected to contain the name of the Class
that implements the ContextSelector to be used.
Log4j provides three ContextSelectors:
BasicContextSelector
Uses either a LoggerContext that has been stored in a ThreadLocal or a common
LoggerContext.
ClassLoaderContextSelector
Associates LoggerContexts with the ClassLoader that created the caller of the getLogger
call.
JNDIContextSelector
Locates the LoggerContext by querying JNDI.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

15 Extending Log4j

162

15.1.3 ConfigurationFactory

Modifying the way in which logging can be configured is usually one of the areas with the most
interest. The primary method for doing that is by implementing or extending a ConfigurationFactory.
Log4j provides two ways of adding new ConfigurationFactories. The first is by defining the system
property named "log4j.configurationFactory" to the name of the class that should be searched first for
a configuration. The second method is by defining the ConfigurationFactory as a Plugin.
All the ConfigurationFactories are then processed in order. Each factory is called on its
getSupportedTypes method to determine the file extensions it supports. If a configuration file is
located with one of the specified file extensions then control is passed to that ConfigurationFactory to
load the configuration and create the Configuration object.
Most Configuration extend the BaseConfiguration class. This class expects that the subclass will
process the configuration file and create a hierarchy of Node objects. Each Node is fairly simple
in that it consists of the name of the node, the name/value pairs associated with the node, The
PluginType of the node and a List of all of its child Nodes. BaseConfiguration will then be passed the
Node tree and instantiate the configuration objects from that.
@Plugin(name = "XMLConfigurationFactory", category = "ConfigurationFactory")
@Order(5)
public class XMLConfigurationFactory extends ConfigurationFactory {
/**
* Valid file extensions for XML files.
*/
public static final String[] SUFFIXES = new String[] {".xml", "*"};
/**
* Return the Configuration.
* @param source The InputSource.
* @return The Configuration.
*/
public Configuration getConfiguration(InputSource source) {
return new XMLConfiguration(source, configFile);
}
/**
* Returns the file suffixes for XML files.
* @return An array of File extensions.
*/
public String[] getSupportedTypes() {
return SUFFIXES;
}
}

15.1.4 LoggerConfig

LoggerConfig objects are where Loggers created by applications tie into the configuration. The
Log4j implementation requires that all LoggerConfigs be based on the LoggerConfig class, so
applications wishing to make changes must do so by extending the LoggerConfig class. To declare
the new LoggerConfig, declare it as a Plugin of type "Core" and providing the name that applications
should specify as the element name in the configuration. The LoggerConfig should also define a
PluginFactory that will create an instance of the LoggerConfig.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

15 Extending Log4j

163

The following example shows how the root LoggerConfig simply extends a generic LoggerConfig.
@Plugin(name = "root", category = "Core", printObject = true)
public static class RootLogger extends LoggerConfig {
@PluginFactory
public static LoggerConfig createLogger(@PluginAttr("additivity") String additivity,
@PluginAttr("level") String loggerLevel,
@PluginElement("AppenderRef") AppenderRef[] refs,
@PluginElement("Filters") Filter filter) {
List appenderRefs = Arrays.asList(refs);
Level level;
try {
level = loggerLevel == null ? Level.ERROR : Level.valueOf(loggerLevel.toUpperCase());
} catch (Exception ex) {
LOGGER.error("Invalid Log level specified: {}. Defaulting to Error", loggerLevel);
level = Level.ERROR;
}
boolean additive = additivity == null ? true : Boolean.parseBoolean(additivity);
return new LoggerConfig(LogManager.ROOT_LOGGER_NAME, appenderRefs, filter, level, additive);
}
}

15.1.5 LogEventFactory

A LogEventFactory is used to generate LogEvents. Applications may replace the standard
LogEventFactory by setting the value of the system property Log4jLogEventFactory to the name of
the custom LogEventFactory class.
15.1.6 Lookups

Lookups are the means in which parameter substitution is performed. During Configuration
initialization an "Interpolator" is created that locates all the Lookups and registers them for use when
a variable needs to be resolved. The interpolator matches the "prefix" portion of the variable name to a
registered Lookup and passes control to it to resolve the variable.
A Lookup must be declared using a Plugin annotation with a type of "Lookup". The name specified
on the Plugin annotation will be used to match the prefix. Unlike other Plugins, Lookups do not use
a PluginFactory. Instead, they are required to provide a constructor that accepts no arguments. The
example below shows a Lookup that will return the value of a System Property.
The provided Lookups are documented here: Lookups

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

15 Extending Log4j

164

@Plugin(name = "sys", category = "Lookup")
public class SystemPropertiesLookup implements StrLookup {
/**
* Lookup the value for the key.
* @param key the key to be looked up, may be null
* @return The value for the key.
*/
public String lookup(String key) {
return System.getProperty(key);
}
/**
* Lookup the value for the key using the data in the LogEvent.
* @param event The current LogEvent.
* @param key the key to be looked up, may be null
* @return The value associated with the key.
*/
public String lookup(LogEvent event, String key) {
return System.getProperty(key);
}
}

15.1.7 Filters

As might be expected, Filters are the used to reject or accept log events as they pass through the
logging system. A Filter is declared using a Plugin annotation of type "Core" and an elementType of
"filter". The name attribute on the Plugin annotation is used to specify the name of the element users
should use to enable the Filter. Specifying the printObject attribute with a value of "true" indicates
that a call to toString will format the arguments to the filter as the configuration is being processed.
The Filter must also specify a PluginFactory method that will be called to create the Filter.
The example below shows a Filter used to reject LogEvents based upon their logging level. Notice the
typical pattern where all the filter methods resolve to a single filter method.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

15 Extending Log4j

165

@Plugin(name = "ThresholdFilter", category = "Core", elementType = "filter", printObject = true)
public final class ThresholdFilter extends AbstractFilter {
private final Level level;
private ThresholdFilter(Level level, Result onMatch, Result onMismatch) {
super(onMatch, onMismatch);
this.level = level;
}
public Result filter(Logger logger, Level level, Marker marker, String msg, Object[] params) {
return filter(level);
}
public Result filter(Logger logger, Level level, Marker marker, Object msg, Throwable t) {
return filter(level);
}
public Result filter(Logger logger, Level level, Marker marker, Message msg, Throwable t) {
return filter(level);
}
@Override
public Result filter(LogEvent event) {
return filter(event.getLevel());
}
private Result filter(Level level) {
return level.isAtLeastAsSpecificAs(this.level) ? onMatch : onMismatch;
}
@Override
public String toString() {
return level.toString();
}
/**
* Create a ThresholdFilter.
* @param loggerLevel The log Level.
* @param match The action to take on a match.
* @param mismatch The action to take on a mismatch.
* @return The created ThresholdFilter.
*/
@PluginFactory
public static ThresholdFilter createFilter(@PluginAttr("level") String loggerLevel,
@PluginAttr("onMatch") String match,
@PluginAttr("onMismatch") String mismatch) {
Level level = loggerLevel == null ? Level.ERROR : Level.toLevel(loggerLevel.toUpperCase());
Result onMatch = match == null ? Result.NEUTRAL : Result.valueOf(match.toUpperCase());
Result onMismatch = mismatch == null ? Result.DENY : Result.valueOf(mismatch.toUpperCase());
return new ThresholdFilter(level, onMatch, onMismatch);
}
}

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

15 Extending Log4j

166

15.1.8 Appenders

Appenders are passed an event, (usually) invoke a Layout to format the event, and then "publish"
the event in whatever manner is desired. Appenders are declared as Plugins with a type of "Core"
and an elementType of "appender". The name attribute on the Plugin annotation specifies the name
of the element users must provide in their configuration to use the Appender. Appender's should
specify printObject as "true" if the toString method renders the values of the attributes passed to the
Appender.
Appenders must also declare a PluginFactory method that will create the appender. The example
below shows an Appender named "Stub" that can be used as an initial template.
Most Appenders use Managers. A manager actually "owns" the resources, such as an OutputStream
or 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 insures that events are not lost while a reconfiguration is taking place
without requiring that logging pause while the reconfiguration takes place.
@Plugin(name = "Stub", category = "Core", elementType = "appender", printObject = true)
public final class StubAppender extends OutputStreamAppender {
private StubAppender(String name, Layout layout, Filter filter, StubManager manager,
boolean ignoreExceptions) {
}
@PluginFactory
public static StubAppender createAppender(@PluginAttr("name") String name,
@PluginAttr("ignoreExceptions") String ignore,
@PluginElement("Layout") Layout layout,
@PluginElement("Filters") Filter filter) {
boolean ignoreExceptions = Boolean.parseBoolean(ignore);
if (name == null) {
LOGGER.error("No name provided for StubAppender");
return null;
}
StubManager manager = StubManager.getStubManager(name);
if (manager == null) {
return null;
}
if (layout == null) {
layout = PatternLayout.createLayout(null, null, null, null);
}
return new StubAppender(name, layout, filter, manager, ignoreExceptions);
}
}

15.1.9 Layouts

Layouts perform the formatting of events into the printable text that is written by Appenders to some
destination. All Layouts must implement the Layout interface. Layouts that format the event into a
String should extend AbstractStringLayout, which will take care of converting the String into the
required byte array.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

15 Extending Log4j

167

Every Layout must declare itself as a plugin using the Plugin annotation. The type must be "Core",
and the elementType must be "Layout". printObject should be set to true if the plugin's toString
method will provide a representation of the object and its parameters. The name of the plugin must
match the value users should use to specify it as an element in their Appender configuration. The
plugin also must provide a static method annotated as a PluginFactory and with each of the methods
parameters annotated with PluginAttr or PluginElement as appropriate.
@Plugin(name = "SampleLayout", category = "Core", elementType = "layout", printObject = true)
public class SampleLayout extends AbstractStringLayout {
protected SampleLayout(boolean locationInfo, boolean properties, boolean complete,
Charset charset) {
}
@PluginFactory
public static SampleLayout createLayout(@PluginAttr("locationInfo") String locationInfo,
@PluginAttr("properties") String properties,
@PluginAttr("complete") String complete,
@PluginAttr("charset") String charset) {
Charset c = Charset.isSupported("UTF-8") ?
Charset.forName("UTF-8") : Charset.defaultCharset();
if (charset != null) {
if (Charset.isSupported(charset)) {
c = Charset.forName(charset);
} else {
LOGGER.error("Charset " + charset + " is not supported for layout, using " +
c.displayName());
}
}
boolean info = locationInfo == null ? false : Boolean.valueOf(locationInfo);
boolean props = properties == null ? false : Boolean.valueOf(properties);
boolean comp = complete == null ? false : Boolean.valueOf(complete);
return new SampleLayout(info, props, comp, c);
}
}

15.1.10 PatternConverters

PatternConverters are used by the PatternLayout to format the log event into a printable String. Each
Converter is responsible for a single kind of manipulation, however Converters are free to format the
event in complex ways. For example, there are several converters that manipulate Throwables and
format them in various ways.
A PatternConverter must first declare itself as a Plugin using the standard Plugin annotation but must
specify value of "Converter" on the type attribute. Furthermore, the Converter must also specify the
ConverterKeys attribute to define the tokens that can be specified in the pattern (preceded by a '%'
character) to identify the Converter.
Unlike most other Plugins, Converters do not use a PluginFactory. Instead, each Converter is required
to provide a static newInstance method that accepts an array of Strings as the only parameter. The
String array are the values that are specified within the curly braces that can follow the converter key.
The following shows the skeleton of a Converter plugin.

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

15 Extending Log4j

@Plugin(name = "query", category = "Converter")
@ConverterKeys({"q", "query"})
public final class QueryConverter extends LogEventPatternConverter {
public QueryConverter(String[] options) {
}
public static QueryConverter newInstance(final String[] options) {
return new QueryConverter(options);
}
}

15.1.11 Custom Plugins

©2014, The Apache Software Foundation • ALL RIGHTS RESERVED.

168



Source Exif Data:
File Type                       : PDF
File Type Extension             : pdf
MIME Type                       : application/pdf
Linearized                      : No
Page Count                      : 172
Profile CMM Type                : Linotronic
Profile Version                 : 2.1.0
Profile Class                   : Display Device Profile
Color Space Data                : RGB
Profile Connection Space        : XYZ
Profile Date Time               : 1998:02:09 06:49:00
Profile File Signature          : acsp
Primary Platform                : Microsoft Corporation
CMM Flags                       : Not Embedded, Independent
Device Manufacturer             : Hewlett-Packard
Device Model                    : sRGB
Device Attributes               : Reflective, Glossy, Positive, Color
Rendering Intent                : Perceptual
Connection Space Illuminant     : 0.9642 1 0.82491
Profile Creator                 : Hewlett-Packard
Profile ID                      : 0
Profile Copyright               : Copyright (c) 1998 Hewlett-Packard Company
Profile Description             : sRGB IEC61966-2.1
Media White Point               : 0.95045 1 1.08905
Media Black Point               : 0 0 0
Red Matrix Column               : 0.43607 0.22249 0.01392
Green Matrix Column             : 0.38515 0.71687 0.09708
Blue Matrix Column              : 0.14307 0.06061 0.7141
Device Mfg Desc                 : IEC http://www.iec.ch
Device Model Desc               : IEC 61966-2.1 Default RGB colour space - sRGB
Viewing Cond Desc               : Reference Viewing Condition in IEC61966-2.1
Viewing Cond Illuminant         : 19.6445 20.3718 16.8089
Viewing Cond Surround           : 3.92889 4.07439 3.36179
Viewing Cond Illuminant Type    : D50
Luminance                       : 76.03647 80 87.12462
Measurement Observer            : CIE 1931
Measurement Backing             : 0 0 0
Measurement Geometry            : Unknown
Measurement Flare               : 0.999%
Measurement Illuminant          : D65
Technology                      : Cathode Ray Tube Display
Red Tone Reproduction Curve     : (Binary data 2060 bytes, use -b option to extract)
Green Tone Reproduction Curve   : (Binary data 2060 bytes, use -b option to extract)
Blue Tone Reproduction Curve    : (Binary data 2060 bytes, use -b option to extract)
Title                           : Apache Log4j 2
Creator                         : The Apache Logging Project
Date                            : 2014:02:09 13:23:59-06:00
PDF Version                     : 1.4
Producer                        : Maven PDF Plugin v. 1.2, 'fo' implementation.
Create Date                     : 2014:02:09 13:23:59-06:00
Creator Tool                    : Nicholas
Page Mode                       : UseOutlines
Author                          : The Apache Logging Project
EXIF Metadata provided by EXIF.tools

Navigation menu