Extending

Log4j provides numerous extension points to adapt it for custom needs. Several of such extension points are covered in the page of the associated component:

This section guides you on the rest of the Log4j extension points.

Extension mechanisms

Log4j allows extensions primarily using following mechanisms:

Plugins

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

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

Bindings

The Log4j plugin system was enhanced in 3.0 to support arbitrary bindings for dependency injection. Many shared components in Log4j could be configured via system properties or similar to include a fully qualified class name to use. Using custom bindings, however, these custom classes can be configured as code. Default bindings are configured in CoreDefaultBundle. Custom bindings can be installed by defining a ConfigurableInstanceFactoryPostProcessor service class which invokes ConfigurableInstanceFactory::registerBundle to register the bundle class containing the bindings. This approach is more portable than the legacy approach of using system properties to define the classes as it removes ambiguity of ClassLoader ownership and other details of modules and similar runtimes.

ServiceLoaders

ServiceLoader is a simple service-provider loading facility baked into the Java platform itself. Log4j uses ServiceLoaders for extending places where

Refer to the ServiceLoader documentation for details.

System properties

Log4j uses system properties to determine the fully-qualified class name (FQCN) to load for extending a certain functionality. For instance, extending MessageFactory2 works using system properties.

Loading a class using only its FQCN can result in unexpected behaviour when there are multiple class loaders.

Extension points

In this section we will guide you on certain Log4j extension points that are not covered elsewhere.

Provider

Provider is the anchor contract binding Log4j API to an implementation. For instance, it has been implemented by Log4j Core, Log4j-to-JUL bridge, and Log4j-to-SLF4J bridge modules.

Under the hood, LogManager locates a Provider implementation using the ServiceLoader mechanism, and delegates invocations to it. Hence, you can extend it by providing a org.apache.logging.log4j.spi.Provider implementation in the form of a ServiceLoader.

Having multiple Providers in the classpath is strongly discouraged. A specific provider can be bound using a custom bundle class if Log4j Core is also available. Alternatively, you can use the log4j2.provider property to explicitly select one.

LoggerContextFactory

LoggerContextFactory is the factory class used by Log4j API implementations to create LoggerContexts. If you are using Log4j Core, you can use ContextSelectors to influence the way its LoggerContextFactory implementation works. If you are creating a new Log4j API implementation, you should provide a custom Provider to introduce your custom LoggerContextFactory implementation.

ContextSelector

Log4jContextFactory, the Log4j Core implementation of LoggerContextFactory, delegates the actual work to a ContextSelector. This should be configured as a ContextSelector binding in a custom binding. Alternatively, it can be configured using the log4j.loggerContext.selector property.

ConfigurationFactory

ConfigurationFactory is the factory class used by Log4j Core to create Configuration instances given a LoggerContext and a ConfigurationSource.

You can provide a custom ConfigurationFactory in the form of a plugin. For example, see XmlConfigurationFactory.java and XmlConfiguration.java of Log4j Core.

A specific configuration factory can be bound in a custom bundle class which can take priority over the default configuration factories. You can also use the log4j.configuration.factory property to explicitly set a ConfigurationFactory to be used before any other factory implementation.

LoggerConfig

LoggerConfig denotes the Logger configurations in a Configuration. A custom LoggerConfig needs to satisfy the following conditions:

  • It needs to extend from LoggerConfig class

  • It needs to be declared as a plugin

  • It needs to include a @Configurable annotation on the class

For example, see RootLogger definition in LoggerConfig.java.

LogEventFactory

Log4j Core uses LogEventFactory to create LogEvents. You can replace the default LogEventFactory implementation with a custom one of yours by defining a custom binding for LogEventFactory or by using the log4j.logEvent.factory property.

Asynchronous loggers discard LogEventFactory and any configuration related with it.

MessageFactory2

Log4j Core uses MessageFactory2 to create Messages. You can replace the default MessageFactory2 implementation with a custom one of yours by using the log4j.message.factory property.

Message factory implementations are expected to interpret formatting patterns containing placeholders denoted with {}. For instance, the default message factory chooses between a SimpleMessage and a ParameterizedMessage depending on the presence of placeholders in the formatting pattern.

If you want to change the placeholder style (e.g., switching from {} to %s), you should not replace the default message factory. Because this will break the existing Log4j API calls using the standard placeholder style. Instead, you can use LogManager methods accepting a message factory to create Loggers with your custom message factory implementations.