I am trying to use the new RoutingAppender of Log4j2 to route the different logs based on the MDC (ThreadContext in Log4j2). What I want to do is the following:
- If MDC map has $contextId -> Append to $contextId appender (specific log)
- If MDC does not have $contextId -> Append to main appender (general log)
I want to achieve this using a wildcard pattern in the tag and then filter using the key parameter in the for contextId (${ctx:contextId}) and using the default (without key paramenter) for the main appender, however I don’t know which value is that wildcard.
Any help is appreciated, maybe I am approaching this from the wrong path. I have been reading about Filters but don’t seem to work as I want.
Thanks!
Advertisement
Answer
Thanks for the link Remko, I have found a temporary solution until that feature gets improved from the guys of Log4j2. The solution is using both RoutingAppender and Filters. This is how my log4j2 config looks like (I have properties defined but I am not showing them here):
<appenders> <appender name="applicationAppender" type="RollingFile" fileName="${logFileName}" filePattern="${logFileNamePattern}" bufferedIO="true" immediateFlush="true" append="true"> <layout type="PatternLayout" pattern="${logPattern}" /> <Policies> <TimeBasedTriggeringPolicy /> <SizeBasedTriggeringPolicy size="${logFileSize}" /> </Policies> <DefaultRolloverStrategy max="${logFileCount}" /> </appender> <Routing name="contextSpecificAppender"> <Routes pattern="$${ctx:contextId}"> <Route> <appender name="Rolling-${ctx:contextId}" type="RollingFile" fileName="logs/${ctx:contextId}.log" filePattern="${logFileNamePattern}" bufferedIO="true" immediateFlush="true" append="true"> <layout type="PatternLayout" pattern="${logPattern}" /> <Policies> <TimeBasedTriggeringPolicy /> <SizeBasedTriggeringPolicy size="${logFileSize}" /> </Policies> <DefaultRolloverStrategy max="${logFileCount}" /> </appender> </Route> </Routes> </Routing> </appenders> <loggers> <root level="info"> <appender-ref ref="contextSpecificAppender"> <ThreadContextMapFilter onMatch="DENY" onMismatch="ACCEPT"> <KeyValuePair key="contextId" value="" /> </ThreadContextMapFilter> </appender-ref> <appender-ref ref="applicationAppender"> <ThreadContextMapFilter onMatch="ACCEPT" onMismatch="DENY"> <KeyValuePair key="contextId" value="" /> </ThreadContextMapFilter> </appender-ref> </root> </loggers>
What I do it is calling ThreadContext.put(“contextId”, “”) or ThreadContext.put(“contextId”, “something”) depending on what appender I want to log. I hope the wildward feature gets implemented soon, but for the meantime, this solution is enough for me.
Thanks!