Configurator Log4j2

0 views
Skip to first unread message

Rosette Allaband

unread,
Aug 5, 2024, 4:33:30 AM8/5/24
to martivertheo
Theadvantage over configuring the location directly in the web.xml is thatyou can compute the path based on some additional information and access the log4j2.xml even if its outside of your classpath.

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.


This page focuses primarily on configuring Log4j through a configuration file. Information on programmatically configuring Log4j can be found at Extending Log4j 2 and Programmatic Log4j Configuration.


All available formats are functionally equivalent. For example, a configuration file in XML can be rewritten using the properties format (and the opposite) without any loss of functionality. However, the hierarchical nature of a Log4j configuration can be captured better in formats which naturally support nesting so XML, JSON, and YAML files, are usually easier to use.


In part because support for XML was added first, Log4j's configuration is reflected as a tree structure. In fact every configuration dialect, including the ConfigurationBuilder, generates a Node for every configuration element. A node is a fairly simple structure that contains a set of attributes, a set of child nodes and a PluginType. It is important to note that every Node must have a corresponding plugin, as the plugin is the component that actually performs the work represented by the node.


Every document type supported by Log4j has a ConfigurationFactory. The factory itself is a Log4j plugin that declares what file extensions it supports and what its priority is. Properties have the highest precedence with a value of 8, followed by yaml, json and xml. When autoconfiguration is performed Log4j will call each of these factories in order to determine which, if any, support the specified configuration file format. If one is found that factory will create the corresponding Configuration object and pass the reference to the configuration data to it.


Every configuration implementation, such as XMLConfiguration, YamlConfiguration, JsonConfiguration, etc. has the primary task of converting the configuration text into the Node tree, typically by parsing the text with whatever tool is available for that document type. It should be noted that while most of the supported document types are inherently tree structured, the Java properties syntax is not. Because of the need to convert the syntax into a Node tree the Java properties syntax used by Log4j required all properties follow a naming pattern that made the tree structure clear. As a consequence, the Java Properties format tends to be more verbose than using a different document type.


Once the Node tree is created control is delegated to AbstractConfiguration, which converts the Nodes into their respective Java objects using Log4j's Plugin system and provides all the common functionality.


In some situations it is desirable to have a single logging configuration that can be used in any deployment environment. For example, it may be necessary to have a different default logging level in production then in development. Another case might be where one type of appender is used when running natively but another is used when deployed to a docker container. One way to handle that is to use a tool such as Spring Cloud Config Server that can be environment aware and serve a different file for each environment. Another option is to include Arbiters in the configuration.


An Arbiter is a Log4j plugin that has the job of determining whether other configured elements should be included in the generated configuration. While all other "Core" plugins are designed to execute as part of Log4j's runtime logic Arbiters execute after the Node tree has been constructed but before the tree is converted to a configuration. An Arbiter is a Node itself which is always removed from the Node tree before it the tree is processed. All an arbiter really does is provide a method that returns a boolean result that determines whether the child nodes of the arbiter should remain in the configuration or be pruned.


Arbiters may occur anywhere an element is allowed in the configuration. So an Arbiter could encapsulate something as simple as a single property declaration or a whole set of Appenders or Loggers. Arbiters may also be nested although Arbiters that are the descendant of another arbiter will only be evaluated if the ancestor returned true. The child elements of an Arbiter must be valid elements for whatever element is the parent of the Arbiter.


Normally Arbiters act in isolation from other Arbiters. That is, the outcome of one Arbiter will not impact any other Arbiters. This can be cumbersome when you simply want to use one of a set of choices. A special plugin named "Select" can be used in this case. Each element under the Select is required to be an Arbiter. The first Arbiter that returns a true value will be the one used while others are ignored. If no Arbiter returns true a DefaultArbiter may be configured with the default configuration elements. The DefaultArbiter is an Arbiter that always returns true, so using it outside of a Select would result in its configured elements always being included just as if it hadn't been present.


Natively Log4j contains the SystemProperty Arbiter that can evaluate whether to include elements based on whether a SystemProperty is non-null or has a specific value, a ClassArbiter that makes its decision based on whether the specified class is present, and a ScriptArbiter that makes its decision based on the result of the script configured with it.


For Spring Boot users an Arbiter named SpringProfile has been provided. The specified profiles are evaluated by Spring's Environment.acceptsProfiles() method, so any expressions it supports may be used as the name attribute.


Log4j has the ability to automatically configure itself during initialization. When Log4j starts it will locate all the ConfigurationFactory plugins and arrange them in weighted order from highest to lowest. As delivered, Log4j contains four ConfigurationFactory implementations: one for JSON, one for YAML, one for properties, and one for XML.


When log4j2.configurationFile references a URL, Log4j will first determine if the URL reference a file using the file protocol. If it does Log4j will validate that the file URL is valid and continue processing as previously described. If it contains a protocol other than file then Log4j will inspect the value of the log4j2.Configuration.allowedProtocols system property. If the provided list contains the protocol specified then Log4j will use the URI to locate the specified configuration file. If not an exception will be thrown and an error message will be logged. If no value is provided for the system property it will default to "https, file, jar". Use of any protocol other than "file" can be prevented by setting the system property value to "_none". This value would be an invalid protocol so cannot conflict with any custom protocols that may be present.


Log4j supports access to remote URLs that require authentication. Log4j supports basic authentication out of the box. If the log4j2.Configuration.username and log4j2.Configuration.password are specified those values will be used to perform the authentication. If the password is encrypted a custom password decryptor may be supplied by specifying the fully qualified class name in the log4j2.Configuration.passwordDecryptor system property. A custom AuthenticationProvider may be used by setting the log4j2.Configuration.authenticationProvider system property to the fully qualified class name of the provider.


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:


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


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:


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.


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.

3a8082e126
Reply all
Reply to author
Forward
0 new messages