Originally reported by JAXenter. Release announced June 30, 2019 by the Apache Logging team.
Background: From Log4j to Log4j 2
Log4j has been a foundational logging library in the Java ecosystem for many years. In 2014, the project underwent a major architectural overhaul and relaunched as Log4j 2. The rewrite delivered significant improvements over the 1.x line, including:
- Substantially faster throughput via the LMAX Disruptor library for asynchronous logging
- A cleaner, more flexible configuration syntax (XML, JSON, YAML, and Properties formats)
- Fixes to architectural problems present in Log4j 1.x
- A plugin-based architecture enabling easy extensibility
Log4j 2 is not backward-compatible with Log4j 1.x. The Apache team provides a bridge adapter for legacy applications, but a clean migration to the 2.x API is recommended for new projects.
The latest milestone in the Log4j 2 journey is version 2.12.0, which adds several useful features and resolves a significant number of bugs.
New Features in Log4j 2.12.0
Docker Lookup and HTTP(S) Reconfiguration (LOG4J2-913)
The headline addition in 2.12.0 is support for reconfiguration via HTTP(S), Docker, and Spring Cloud Configuration. This means Log4j can now look up configuration values dynamically from these sources at runtime — a significant quality-of-life improvement for teams running containerised Java services. In Docker environments, the new Docker Lookup allows log configuration to reference Docker metadata (such as container labels or environment variables) directly in log patterns and routing rules.
Zero-Padded Rolling File Counter (LOG4J2-2403)
The RollingFileAppender now supports zero-padded counters in file name patterns. This ensures rolled log files sort correctly in file system listings — for example, app.log.001 instead of app.log.1. Contributed by community member hupfdule.
Marker-Absence Filter (LOG4J2-2427)
A new filter can be configured to match log events that carry no marker. This complements the existing MarkerFilter, enabling finer-grained routing of unmarked events to specific appenders. Contributed by Rimaljit Kaur.
Programmatic Reconfiguration API (LOG4J2-2406)
New reconfiguration methods have been added to the Configurator class, making it easier to programmatically reload or update the Log4j configuration at runtime without restarting the JVM.
TCP Appender Multi-Address Support (LOG4J2-2586)
The TCP Appender now correctly handles host names that resolve to multiple IP addresses (round-robin DNS or multi-homed hosts), improving resilience when shipping logs to a log aggregation cluster.
Custom End-of-Line in JsonLayout (LOG4J2-2337)
JsonLayout now accepts a configurable end-of-line character sequence, giving operators control over how JSON log lines are delimited — useful when downstream log shippers expect specific line endings. Contributed by Arvind Sahare and Patrice Ferrot.
Configurable GZIP Compression Level on Rollover (LOG4J2-2598)
GZIP compression applied during log file rollover now supports configurable compression levels (1–9), allowing teams to tune the trade-off between CPU usage and compressed file size. Contributed by Carter Kozak.
Case-Insensitive AsyncQueueFullPolicy Values (LOG4J2-2611)
The AsyncQueueFullPolicy configuration now accepts the shorthand values Default and Discard in a case-insensitive manner, reducing the potential for silent misconfiguration caused by capitalisation differences.
MapMessage Helper Method (LOG4J2-2634)
A new org.apache.logging.log4j.message.MapMessage.toKey(String) method simplifies the creation of subclasses, a common pattern when structured logging is used with custom message types.
Bug Fixes and Resolved Issues
Log4j 2.12.0 resolves a substantial list of defects. The most operationally significant are highlighted below.
Stability and Crash Fixes
- LOG4J2-2592 — Fixed a
StackOverflowExceptioninSocketAppenderwhen the remote server was unreachable. This was a significant reliability issue for applications shipping logs over TCP. - LOG4J2-2598 — Fixed a
StackOverflowErrorinAbstractExternalFileCleaner. - LOG4J2-2618 — Fixed a possible
ClassCastExceptioninScriptManagerduring initialisation. - LOG4J2-2616 — Restored a constructor in
ThrowablePatternConverterthat was inadvertently removed in version 2.8.2, restoring binary compatibility for downstream libraries.
NullPointerException Fixes
- LOG4J2-2559 — NPE in
JdbcAppender.createAppender(). - LOG4J2-2612 — NPE in
JdbcDatabaseManager.writeInternal().
Async Logging Performance Fix (LOG4J2-2606)
A critical fix for asynchronous logging: when the async queue was full, Log4j would previously enter a busy-wait loop, causing very high CPU utilisation and dramatically reduced throughput. This has been corrected so that a full queue is handled gracefully without spinning.
RoutingAppender Race Condition (LOG4J2-2629)
A race condition in RoutingAppender could allow log events to be silently dropped when a purge policy attempted to remove an idle appender at exactly the same moment a new event arrived for that appender. This has been fixed.
Additional Notable Fixes
- LOG4J2-2622 —
StructuredDataIdwas ignoring themaxLengthattribute. - LOG4J2-2636 —
RFC5424Layoutwas not correctly setting the default Structured Element ID for the MDC. - LOG4J2-1143 — Lookups were silently ignored when the plugin key was not all-lowercase. Contributed by Pascal Heinrich.
- LOG4J2-1852 — Plugin discovery inside a JAR over a URL connection now works correctly. Contributed by Tanner Altares.
- LOG4J2-2561 — Fixed JEP 223 version detection for JDK 9 and later. Contributed by Ulrich Enslin.
- LOG4J2-1103 —
FailoverAppenderwas failing with a configuration parsing error when the<Failovers>element was present. Contributed by Seán Dunne. - LOG4J2-2597 — A clearer exception message is now thrown when both
log4j-slf4j-implandlog4j-to-slf4jare on the classpath simultaneously (a common misconfiguration). - LOG4J2-2631 —
RoutingAppenderpurge policies no longer incorrectly stop appenders that are defined in the logger configuration but only referenced (not owned) by theRoutingAppender. - LOG4J2-2564 —
MapPatternConverteris now correctly created from the%K,%map, and%MAPpatterns. - LOG4J2-2602 — File modification time is now updated correctly when a size-based triggering policy is used without a time-based policy.
- LOG4J2-2610 — File creation time is now explicitly set on newly created log files.
- LOG4J2-2547 — An error message in
RollingRandomAccessFileAppenderwas referencing the wrong class name.
Upgrade Notes and Requirements
Before upgrading to Log4j 2.12.0, keep the following in mind:
- Java 7 or higher is required to build and run Log4j 2.12.0.
- Log4j 2.x is not compatible with Log4j 1.x. Do not mix the two on the classpath.
- Do not place both
log4j-slf4j-impl(routes SLF4J calls into Log4j 2) andlog4j-to-slf4j(routes Log4j 2 calls into SLF4J) on the classpath at the same time. This creates a logging loop and will now throw a more descriptive exception. - If you use
RoutingAppender, review the behaviour change in LOG4J2-2631:RoutingAppender.getAppenders()no longer includes entries for appenders that the router references but did not create.
The full changelog and release artifacts are available on the official Apache Log4j website.