[ https://issues.apache.org/jira/browse/LOG4J2-3469?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Jody Garnett updated LOG4J2-3469: --------------------------------- Description: 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{*}. was: 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(); final LoggerContext context = (LoggerContext) LogManager.getContext(false); final Configuration config = context.getConfiguration(); config.getProperties().put("GEOSERVER_LOG_LOCATION","geoserver.log"); ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder(); Appender appender = config.getAppenders("geoserverlogfile"); if( appender instanceof RollingFileAppender){ RollingFileAppender fileAppender =(RollingFileAppender) appender; AppenderComponentBuilder appenderBuilder = builder. newAppender("geoserverlogfile", fileAppender) .addAttribute("fileName", "${GEOSERVER_LOG_LOCATION}.log"); config.getAppenders().remove("geoserverlogfile"); addAppender((Appender) appenderBuilder.build()); } }{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{*}. > Create new AppenderComponentBuilder 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)