使用Log4j2和LocalThread创建两个不同的日志文件

时间:2018-08-21 08:47:02

标签: java spring log4j2

有一个Spring应用程序,我需要将不同的servlet请求路由到两个不同的日志文件中。我在Spring的过滤器链中创建了一个过滤器,并尝试设置一个有效的log4j2配置。

过滤器:

@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配置:

<?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>

使用上述配置,日志记录根本无法正常工作。 使用Logback可以轻松实现该任务,但是不幸的是,我必须坚持使用Log4j2。

==================================== 更新

这是通过注销实现的方式。

@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>

1 个答案:

答案 0 :(得分:0)

因此,找到的解决方案是:

@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 {
            chain.doFilter(request, response);
        }
    }
}

<Configuration status="WARN" monitorInterval="30">
    <Appenders>
        <Console name="CONSOLE" target="SYSTEM_OUT" follow="true">
            <PatternLayout
                    pattern="%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} %highlight{${LOG_LEVEL_PATTERN:-%5p}}{FATAL=red blink, ERROR=red, WARN=yellow, INFO=green, DEBUG=blue, TRACE=white} %style{${sys:PID}}{magenta} [%15.15t] %style{%-40.40C{1.}}{cyan} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
        </Console>
        <Routing name="ROUTING">
            <Routes pattern="$${ctx:health}">
                <Route key="true">
                    <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>
                <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>
        </Routing>
    </Appenders>
    <Loggers>
        <Logger name="org.hibernate" level="info" additivity="false">
            <AppenderRef ref="CONSOLE"/>
            <AppenderRef ref="ROUTING"/>
        </Logger>
        <Logger name="org.springframework" level="info" additivity="false">
            <AppenderRef ref="CONSOLE"/>
            <AppenderRef ref="ROUTING"/>
        </Logger>
        <Root level="debug" additivity="false">
            <AppenderRef ref="CONSOLE"/>
            <AppenderRef ref="ROUTING"/>
        </Root>
    </Loggers>
</Configuration>