I want to use Rewrite appender in my log4j2.xml file so that before logging I can modify logs. I have not get much helps from google. As per log4j2 documents Rewrite is an interface has rewrite method and MapRewritePolicy is implementation class, when I run this I am able to see my web3.log file generating but not seeing any modification in log content. I seen MapRewritePolicy source code and created local implementation class as MapRewritePolicyImpl.java in my project and put some System.out to see code flow is coming into this class from log4j2.xml file. I have modified my log4j2.xml to use MapRewritePolicyImpl.java but code flow is not going into my MapRewritePolicyImpl.java class.
<Rewrite name="rewrite" >
<Appender-Ref ref="web3" />
<MapRewritePolicyImpl">
<KeyValuePair key="creditCard" value="new12345"/>
</MapRewritePolicyImpl>
</Rewrite>
<Configuration monitorInterval="5" status="debug" strict="true">
<Appenders>
<RollingFile name="web3" fileName="../logs/web3.log"
filePattern="${sys:catalina.home}/logs/$${date:yyyy-MM-dd}/web3-%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout
pattern="%d{dd/MM/yyyy HH:mm:ss,SSS} [%X{cartID}] [%X{sessionId}] [%p] [%t] [%c] (%F:%L) - %m%n" />
<Policies>
<TimeBasedTriggeringPolicy interval="1"
modulate="true" />
<SizeBasedTriggeringPolicy size="10 MB" />
</Policies>
</RollingFile>
<Rewrite name="rewrite" >
<Appender-Ref ref="web3" />
<MapRewritePolicy">
<KeyValuePair key="creditCard" value="new12345"/>
</MapRewritePolicy>
</Rewrite>
</Appenders>
<Loggers>
<Logger name="com.virginamerica" level="info" additivity="false">
<!-- <Appender-Ref ref="web3" /> -->
<Appender-Ref ref="rewrite"/>
</Logger>
</Loggers>
</Configuration>
Solution 1: Using RewriteAppender
Your example seems almost correct. As mentioned by @Remko Popma the Rewrite implementation you selected is not fit for your usecase.
If you use your own Rewriter implementation you can get it to work.
I found a very good example here: RewriteAppender Example
The example contains the log4j2.xml and the implementation of the RewriteAppender. In the RewriteAppender (here called
MarkerInjectorRewritePolicy
) you can modify the event to fit your needs. In the example the author injects some marker-data, you would not need that part..
Solution 2: Using LogEventFactory
Solution 1 has some drawbacks. Imagine you have a 100 loggers and 50 Appenders. Trying to implement solution 1 now you end up with another 50 RewriteAppender declarations plus adjustments to all loggers to use the redirect logger instead of the actual target Appender. This can be very tedious and error-prone.
A much easier solution is this:
Or set it by using the start parameter:
EDIT: BETTER: A more robust way to set this is by using a
log4j2.component.properties
:log4j2.component.properties
and put it in your classpath.Log4jLogEventFactory = my.package.MyLogEventFactory
This file is loaded automatically by log4j and used to configure multiple core settings. Using this file you do not have to pass start-parameters every time plus you don't run into the potential problem of class initialization ordering problems (like when using
System.setProperty()
).The LogEventFactory implementation is pretty simple:
The
LogEventFactory
is used to create theLogEvents
. So instead of intercepting and manipulating them later, we simply go to the source and do our work here.With this we get ALL events!
Good luck! Have fun!
MapRewritePolicy will evaluate LogEvents that contain a MapMessage and will add or update elements of the Map. This only works if your application calls
logger.info(new MapMessage(keyValueMap))
. I suspect that this is not what your application is currently doing.Usually, your messages will be either a SimpleMessage (if you called
logger.info("Just a string without parameters")
) or a ParameterizedMessage (if you calledlogger.info("Hi {}!", name)
). RewriteAppender will not be able to do anything with either SimpleMessage or ParameterizedMessages, so nothing is replaced...You may want to take a look at the documentation for PatternLayout: this has the capability to replace regular expressions in string messages with some replacement value, if you use the
replace{pattern}{regex}{substitution}
pattern.