There is a Spring application where I need to route different servlet requests into two different log files. I created a filter in Spring's filter chain and tried to setup a working log4j2 configuration.
Filter:
@Component
public class LogFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
if (request.getServletPath().contains("healthcheck")) {
try (CloseableThreadContext.Instance context = CloseableThreadContext.put("health", "true")) {
chain.doFilter(request, response);
}
} else {
try (CloseableThreadContext.Instance context = CloseableThreadContext.put("health", "false")) {
chain.doFilter(request, response);
}
}
}
}
Log4j2 configuration:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" monitorInterval="30">
<Appenders>
<Routing name="Routing">
<Routes pattern="$${health}==true">
<Route>
<RollingRandomAccessFile name="FILE"
fileName="logs/reference-service.log"
filePattern="logs/reference-service.log.%d{yyyy-MM-dd-hh-mm}.gz">
<PatternLayout pattern="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n"/>
<Policies>
<SizeBasedTriggeringPolicy size="1024 KB"/>
</Policies>
<DefaultRolloverStrategy max="30"/>
</RollingRandomAccessFile>
</Route>
</Routes>
<Routes pattern="$${health}==false">
<Route>
<RollingRandomAccessFile name="FILE_HEALTH"
fileName="logs/reference-service-health.log"
filePattern="logs/reference-service-health.log.%d{yyyy-MM-dd-hh-mm}.gz">
<PatternLayout pattern="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n"/>
<Policies>
<SizeBasedTriggeringPolicy size="1024 KB"/>
</Policies>
<DefaultRolloverStrategy max="30"/>
</RollingRandomAccessFile>
</Route>
</Routes>
</Routing>
</Appenders>
<Loggers>
<Logger name="org.hibernate" level="info" additivity="false">
<AppenderRef ref="FILE"/>
<AppenderRef ref="FILE_HEALTH"/>
</Logger>
<Logger name="org.springframework" level="info" additivity="false">
<AppenderRef ref="FILE"/>
<AppenderRef ref="FILE_HEALTH"/>
</Logger>
<Root level="debug">
<AppenderRef ref="FILE"/>
<AppenderRef ref="FILE_HEALTH"/>
</Root>
</Loggers>
</Configuration>
With the configuration presented above logging is not working at all. The task is easy to implement using Logback, but unfortunately I must stay with Log4j2.
==================================== UPDATE
This is how it's implemented with logback.
@Component
public class LogFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
try {
if (request.getServletPath().contains("healthcheck")) {
MDC.put("health", "true");
}
chain.doFilter(request, response);
} finally {
MDC.remove("health");
}
}
}
public class MdcFilterHealth extends Filter<ILoggingEvent> {
@Override
public FilterReply decide(ILoggingEvent event) {
String marked = event.getMDCPropertyMap().get("health");
if (!"true".equals(marked)) {
return FilterReply.DENY;
} else {
return FilterReply.NEUTRAL;
}
}
}
public class MdcFilterNonHealth extends Filter<ILoggingEvent> {
@Override
public FilterReply decide(ILoggingEvent event) {
String marked = event.getMDCPropertyMap().get("health");
if ("true".equals(marked)) {
return FilterReply.DENY;
} else {
return FilterReply.NEUTRAL;
}
}
}
<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="myservice.config.MdcFilterNonHealth"/>
<file>logs/reference-service.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>%d{dd-MM-yyyy HH:mm:ss.SSS} | [%thread] | %-5level | %-30.30M | %msg%n</Pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/archived/reference-service_%d{dd-MM-yyyy}.log</fileNamePattern>
<maxHistory>10</maxHistory>
<totalSizeCap>1024KB</totalSizeCap>
</rollingPolicy>
</appender>
<appender name="FILE_HEALTH" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="myservice.config.MdcFilterHealth"/>
<file>logs/reference-service-health.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>%d{dd-MM-yyyy HH:mm:ss.SSS} | [%thread] | %-5level | %-30.30M | %msg%n</Pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/archived/reference-service-health_%d{dd-MM-yyyy}.log</fileNamePattern>
<maxHistory>10</maxHistory>
<totalSizeCap>1024KB</totalSizeCap>
</rollingPolicy>
</appender>
<Logger name="org.hibernate" level="info" additivity="false">
<appender-ref ref="FILE"/>
<appender-ref ref="FILE_HEALTH"/>
</Logger>
<Logger name="org.springframework" level="info" additivity="false">
<appender-ref ref="FILE"/>
<appender-ref ref="FILE_HEALTH"/>
</Logger>
<root level="debug">
<appender-ref ref="FILE"/>
<appender-ref ref="FILE_HEALTH"/>
</root>
</configuration>