PluginsIntroductionLog4j 1.x allowed for extension by requiring class attributes on most of the configuration declarations. In the case of some elements, notably the PatternLayout, the only way to add new pattern converters was to extend the PatternLayout class and add them via code. One of goals of Log4j 2 is to make extending it extremely easy through the use of plugins. In Log4j 2 a plugin is declared by adding a Plugin annotation to the class declaration. During initialization the Configuration will invoke the PluginManager to locate all the Log4j plugins that are located in the declared packages. As the configuration is processed the appropriate plugins will be automatically configured and initialized. Log4j 2 utilizes a few different categories of plugins which are described in the following sections. CoreCore plugins are those that are directly represented by an element in a configuration file, such as an Appender, Logger or Filter. Custom plugins that conform to the rules laid out in the next paragraph may simply be referenced in the configuration, provided they are appropriate configured to be loaded by the PluginManager. Every Core plugin must declare a static method that is marked with a PluginFactory annotation. To allow the Configuration to pass the correct parameters to the method, every parameter to the method must be annotated as one of the following attribute types. Each attribute or element annotation must include the name that must be present in the configuration in order to match the configuration item to its respective parameter. Attribute Types
ConvertersConverters are used by PatternLayout to render the elements identified by the conversion pattern. Every converter must specify its type as "Converter" on the Plugin attribute, have a static newInstance method that accepts an array of Strings as its only parameter and returns an instance of the Converter, and must have a ConverterKeys annotation present that contains the array of converter patterns that will cause the Converter to be selected. Converters that are meant to handle LogEvents must extend the LogEventPatternConverter class and must implement a format method that accepts a LogEvent and a StringBuilder as arguments. The Converter should append the result of its operation to the StringBuilder. A second type of Converter is the FileConverter - which must have "FileConverter" specified in the type attribute of the Plugin annotation. While similar to a LogEventPatternConverter, instead of a single format method these Converters will have two variations; one that takes an Object and one that takes an array of Objects instead of the LogEvent. Both append to the provided StringBuilder in the same fashion as a LogEventPatternConverter. These Converters are typically used by the RollingFileAppender to construct the name of the file to log to. KeyProvidersSome components within Log4j may provide the ability to perform data encryption. These components require a secret key to perform the encryption. Applications may provide the key by creating a class that implements the SecretKeyProvider interface.LookupsLookups are perhaps the simplest plugins of all. They must declare their type as "Lookup" on the plugin annotation and must implement the StrLookup interface. They will have two methods; a lookup method that accepts a String key and returns a String value and a second lookup method that accepts both a LogEvent and a String key and returns a String. Lookups may be referenced by specifying ${name:key} where name is the name specified in the Plugin annotation and key is the name of the item to locate. Plugin PreloadingScanning for annotated classes dynamically takes a bit of time during application initialization. Log4j avoids this by scanning its classes during the build. In the Maven build, the PluginManager is invoked as shown below and then the resulting Map is stored in a file in the jar being constructed. Log4j will locate all the files created this way and and preload them, which shortens startup time considerably. Adding the following plugin definition to your project's pom.xml will cause the plugin manager to be called during the build. It will store the resulting file in the correct location under the directory specified in the first argument after scanning all the components located under the package specified in the second argument.<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>1.2.1</version> <executions> <execution> <phase>process-classes</phase> <goals> <goal>java</goal> </goals> </execution> </executions> <configuration> <mainClass>org.apache.logging.log4j.core.config.plugins.PluginManager</mainClass> <arguments> <argument>${project.build.outputDirectory}</argument> <argument>org.myorg.myproject.log4j</argument> </arguments> </Configuration> </plugin> |