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:
-
Log4j API
-
Log4j Core
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
-
The service needs to be implementation agnostic. As a result, the Log4j plugin system cannot be used, since it is provided by the logging implementation, i.e., Log4j Core. For instance, this is why extending Thread Context, which is a Log4j API component, works using
ServiceLoaders. -
The service needs to be loaded before the Log4j plugin system. For instance, this is why extending
Providerworks usingServiceLoaders.
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
LoggerConfigclass -
It needs to be declared as a plugin
-
It needs to include a
@Configurableannotation 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 |
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 If you want to change the placeholder style (e.g., switching from |