[ https://issues.apache.org/jira/browse/LOG4J2-2240?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17466460#comment-17466460 ]
Lado Kumsiashvili commented on LOG4J2-2240: ------------------------------------------- What ist the status of this ticket? > Is there a mechanism to reconfigure log4j2 in a predictable fashion? > -------------------------------------------------------------------- > > Key: LOG4J2-2240 > URL: https://issues.apache.org/jira/browse/LOG4J2-2240 > Project: Log4j 2 > Issue Type: Improvement > Components: Core > Affects Versions: 2.10.0 > Reporter: Edward Pershwitz > Assignee: Ralph Goers > Priority: Critical > > Hello, I'm re-posting from Stack Overflow following Remko Popma's > recommendation. This is simultaneously a question and a request for > improvement. If there is a trick I haven't discovered yet it can be used as a > workaround, however, the absence of a public API to the Configurator that > would support reconfiguration and allow (even if optionally) handling of > abnormal events appears to be a serious deficiency that could hopefully be > addressed in the near future. Thanks! > > ------------------------------------------------------------------------------------------------------------------------ > I'm looking for ways to configure/reconfigure log4j after it may, or may not > have been initialized. This should work running standalone or in a web > container. > The configuration may be represented by a configuration file at a particular > arbitrary URI. The knowledge of the URI comes from the application, not log4j > framework. The configuration may also be done programmatically (less > problematic but problematic still). > The public API is unfortunately sorely lacking so developers are forced to > write brittle code using implementation classes from log4j core. From weeks > of studying documentation and stepping through log4j code I see two ways to > accomplish reconfiguration: > Stopping the current context and re-initializing using > log4j.core.config.Configurator, > similar to the following: > {code:java} > ((LoggerContext) LogManager.getContext(false)).stop(); > Configurator.initialize(buildDefaultConfiguration()); //programmatically > building a configuration{code} > or > {code:java} > ((LoggerContext) LogManager.getContext(false)).stop(); > Configurator.initialize(null, ConfigurationSource.fromUri(loggingUri)); > //passing the configuration source constructed from a known URI{code} > The first line in both examples will stop the current context if it has > already been created and started (when running in a web container for > example). If log4j has not been initialized (when running as a standalone app > for example) it will initialize log4j with the default configuration and > start the context first (as a side effect of calling getContext()), and then > stop it. > If the current context is not stopped first the call to > Configurator.initialize() will have no effect. log4j will ignore your attempt > to re-initialize, will not give you any indication of it, and just simply > return the current context. This behavior is not mentioned in the > "Reconfigure Log4j Using ConfigurationBuilder with the Configurator" section > of the Manual. It simply says: "However, should any logging be attempted > before Configurator.initialize() is called then the default configuration > will be used for those log events." The default configuration will also be > used for all subsequent log events in the provided examples because calling > Configurator.initialize() will have no effect, unless the current context is > stopped first. > Setting a new configuration location on the existing context thus forcing > reconfiguration, > similar to the following: > {code:java} > ((LoggerContext) > LogManager.getContext(false)).setConfigLocation(loggingUri);{code} > This works in a similar fashion: if log4j hasn't been initialized the call to > getContext() will trigger initialization and creation of the default context > that will then be reconfigured; and if it has been initialized then the > current context, whatever it may have been, will get reconfigured. The > configuration source will be created from the URI by the log4j framework. > The difference is that in the first way the context is replaced and all > loggers in the old (stopped) context will be dead. If any code on the stack > holds references to these dead loggers and tries to log to them it will be a > no-op. In the second way the context is kept but the configuration is > replaced and existing loggers are updated with the new configuration. > Both methods use core code and are therefore brittle, but both work for the > sunny day scenario (using log4j-core 2.10.0 anyway). However, neither one > appears to afford the user any control over handling any exceptional events, > or even inform the user that something went wrong. Log4j will "eat up" any > exceptions, and make its own executive decision how to handle them. > If a problem occurs after Configurator.initialize() is called log4j will > create a default configuration that effectively cuts all logging off other > than errors to the console and happily return the new context back not giving > the calling code any clue that logging has effectively been stopped. > If a problem occurs after LoggerContext.setConfigLocation() is called log4j > will do essentially the same thing except the current context will be kept. > One would think that particularly in the case of a reconfiguration failure > the most typical handling would be to revert back to the old configuration. > There doesn't appear to be a way to accomplish this because log4j will simply > stop logging (other than errors to the console) and give the calling code no > indication of the failure. > Here's a typical scenario: several applications extend a common framework. > The framework configures the same logging for all extending applications (to > facilitate reuse and simplify post-processing of the logs). Some application > has a unique logging need and attempts to reconfigure log4j from its own > metadata (config file at a known URI). The XML parser throws an exception > parsing this file. The exception gets handled internally by log4j, logging is > quietly stopped, and no one knows. Well, there is an error log sent to the > StatusLogger with the exception, but the calling code doesn't know. > So with this lengthy preamble, the question is: is there a mechanism I > haven't discovered yet to modify log4j configuration in a predictable fashion > and be able to handle abnormal events should they arise? That is, other than > something drastic like (for the example above) extending the XML > configuration class and replacing code that handles exceptions, thus running > a risk of creating undesirable side effects in the current log4j > implementation, not talking about an even greater risk of breaking in the > future if the implementation changes. > Any help would be greatly appreciated! -- This message was sent by Atlassian Jira (v8.20.1#820001)