How to configure RewriteAppender with multiple AppenderRefs in a properties file?

23 Views Asked by At

I am trying to use the RewriteAppender to make mods to the LogEvent and then pass it along to several other appenders. (My environment requires all configurations to use properties files.)

In looking at the code in PropertiesConfigurationBuilder methods processRemainingProperties() and createComponent, it is not clear how to configure this if it is even possible at all.

The documentation (https://logging.apache.org/log4j/2.x/manual/configuration.html#configuration-with-properties) has an example that includes:

logger.app.appenderRef.$1.ref = stdout
logger.app.appenderRef.$2.ref = file

My latest attempt to configure this array was this: (note the plural "appenderRefs" since that is the plugin builders parameter name)

# added for error "No type attribute for component appenderRefs"
appender.rewrite.appenderRefs.type = AppenderRef 
appender.rewrite.appenderRefs.stdout.type = AppenderRef
appender.rewrite.appenderRefs.stdout.ref = stdout
appender.rewrite.appenderRefs.file.type = AppenderRef
appender.rewrite.appenderRefs.file.ref = file

I was expecting the appenderRefs RewriteAppender property to be set to an array with two elements but I get the following ConfigurationException:

Arguments given for element RewriteAppender are invalid: field 'appenderRefs' has invalid value '[Lorg.apache.logging.log4j.core.config.AppenderRef;@740fb309'
1

There are 1 best solutions below

2
Piotr P. Karwasz On

As you already noticed, the general rule used to transform a set of properties into an XML tree transforms:

<parentPrefix>.<id1>.type = Component
<parentPrefix>.<id1>.foo = bar
<parentPrefix>.<id1>.<id2>.type = SubComponent
<parentPrefix>.<id1>.<id2>.bar = baz
<parentPrefix>.<id1>.<id3>.type = SubComponent

into the subtree:

<Component foo="bar">
  <SubComponent bar="baz"/>
  <SubComponent/>
</Component>

So assuming appender.rewrite is the prefix of the Rewrite appender, you can use:

appender.rewrite.stdout.type = AppenderRef
appender.rewrite.stdout.ref = stdout
appender.rewrite.file.type = AppenderRef
appender.rewrite.file.ref = file

Why does the example from the documentation work?

Beyond the general rule (expressed in the processRemainingProperties method), some sub-trees have special rules. For example the properties that start with logger. are parsed by createLogger, which accepts the syntax you found in the doc:

logger.app.appenderRef.$1.ref = stdout
logger.app.appenderRef.$2.ref = file

but does not accept:

logger.app.$1.type = AppenderRef
logger.app.$1.ref = stdout
logger.app.$2.type = AppenderRef
logger.app.$2.ref = file

Remark: the 3.x version of Log4j will feature a new log4j-config-properties with coherent mapping rules provided by jackson-dataformat-properties. Under these new rules you'll be able to write:

Appenders.Rewrite.AppenderRef[1].ref = stdout
Appenders.Rewrite.AppenderRef[2].ref = file