[ 
https://issues.apache.org/jira/browse/LOG4J2-3469?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17518627#comment-17518627
 ] 

Ralph Goers commented on LOG4J2-3469:
-------------------------------------

Once a configuration has started you cannot modify the filename the Appender 
writes to. 

Our position is that programmatic configuration is to be avoided as it makes 
applications too tied to the internals of Log4j, which is why so many 
applications have yet to upgrade from Log4j 1.x.  Instead, we have added things 
like Arbiters to allow you to choose which components you want to use 
dynamically during initialization.  In general, we suggest that if we haven't 
provided something that will allow you to do what you need in the configuration 
file that a Jira issue be opened requesting a feature to do it.  

I should note that I believe all 3 of your bullets could be solved by using 
[Arbiters|https://logging.apache.org/log4j/2.x/manual/configuration.html#Arbiters].

However, we do understand that no matter how hard we try to explain that it is 
a bad idea that people still want to do it. To that end I will try to respond 
to some of your options.

Modifying the Node tree - So long as you know what you are doing this is very 
safe. In a sense that is exactly what Arbiters do - they evaluate some 
condition and then either include the nodes or they don't.

Yes, you can override preConfigure(). But again, you are doing the same thing 
an Arbiter would do.

> Create new builder from existing Appender
> -----------------------------------------
>
>                 Key: LOG4J2-3469
>                 URL: https://issues.apache.org/jira/browse/LOG4J2-3469
>             Project: Log4j 2
>          Issue Type: New Feature
>          Components: Configuration, Configurators, Core
>    Affects Versions: 2.17.2
>            Reporter: Jody Garnett
>            Priority: Minor
>         Attachments: DEFAULT_LOGGING.xml
>
>
>  
> The documentation covers both [Initialize Log4j by Combining Configuration 
> File with Programmatic 
> Configuration|https://logging.apache.org/log4j/2.x/manual/customconfig.html#Hybrid]
>  and [Programmatically Modifying the Current Configuration after 
> Initialization|https://logging.apache.org/log4j/2.x/manual/customconfig.html#Programmatically_Modifying_the_Current_Configuration_after_Initialization].
>  
> However both these techniques are limited as to what they can accomplish:
>  * MyXMLConfiguration.doConfigure() is shown adding an appender, via 
> addLogger method
>  * A custom configuration super.setup() method is shown using 
> config.addLogger() and then ctx.updateLoggers().
> My challenge is to programatically update the configuration to:
>  * Override logfile output location, either directly modifying appender, or 
> modifying config property used by appender.
>  * Optionally Filter out any RollingFileAppender or FileAppender appenders
>  * Optionally suppress (filter out) any Console loggers if asked
> I am seeking an api used to pre-process configuration objects if one is 
> available.
> In the past when using a fluent / builder API there is an option to 
> jump-start a builder with the configuration of an existing object. This 
> approach would allow a builder to be loaded with an existing appender; 
> revised, and a new appender generated as a replacement.
> {code:java}
> @Override protected void doConfigure() {
>     super.doConfigure();
>     getProperties().put("GEOSERVER_LOG_LOCATION","geoserver.log");
>     Appender appender = getAppenders("geoserverlogfile");
>     if( appender instanceof RollingFileAppender){
>          RollingFileAppender fileAppender =(RollingFileAppender) appender;
>          RollingFileAppender replacement = 
> RollingFileAppender.newBuilder(fileAppender)
>             .withFileName("${GEOSERVER_LOG_LOCATION}.log")
>             .withFilePattern("${GEOSERVER_LOG_LOCATION}-%i.log")
>             .build();
>         
>          getAppenders().remove("geoserverlogfile");
>          addAppender(replacement);
>     }
> }{code}
> The alternative is verbose and may miss copying new parameters added over 
> time.
> Alternatives considered:
> *MyXMLConfiguration.setup()* prior to super.setup(): Unclear how easy/safe it 
> is to to modify _rootNode_ structure directly? Is this what is intended by 
> the documentation.
> {code:java}
> public void setup() {
>     for( Node child : rootNode.getChildren()){
>         if ("Properties".equals(child.getName())){
>             for( Node property : child.getChildren() ){
>                 if( property.getAttributes().containsKey("name") &&
>                         
> property.getAttributes().get("name").equals("GEOSERVER_LOG_LOCATION")) {
>                     // override value with current GEOSERVER_LOG_LOCATION
>                     property.setValue("foo.log");
>                 }
>             }
>         }
>     }
>     super.setup();
> }{code}
> *MyXMLConfiguration.doConfigure()* before super.doConfigure(): should be able 
> to modify _rootNode_ and make any changes required. Unclear how easy/safe it 
> is to to modify node structure directly?
> *MyXMLConfiguration.doConfigure()*  after super.doConfigure(): is too late as 
> shown above.
>  - Can add loggers and appenders
>  - Modifications to config.getProperties() are not reflected in appender 
> configuration 
>  - Modifications to existing appenders cannot be accomplished
> {*}MyXMLConfiguration.{*}{*}preConfigure(Node){*} allows xml to be rewritten 
> just-in-time:
> {code:java}
> @Overrideprotected void preConfigure(Node node) {
>     if( !node.isRoot() && node.getName().equals("Property")){
>         if( node.getAttributes().containsKey("name") &&
>                 
> node.getAttributes().get("name").equals("GEOSERVER_LOG_LOCATION")) {
>             // override value with current GEOSERVER_LOG_LOCATION
>             node.setValue("foo.log");
>         }
>     }
>     super.preConfigure(node);
> } {code}
> For reference see attached {*}DEFAULT_LOGGING.xml{*}.



--
This message was sent by Atlassian Jira
(v8.20.1#820001)

Reply via email to