SiftingAppender:将不同的线程记录到不同的日志文件中

Logback的SiftingAppender功能允许根据MDC属性或线程名称创建多个子附加器,每个都有独特的日志文件。在Spring Security应用中,通过配置servlet过滤器,可以实现按用户名划分日志。对于限制线程数量的应用场景,如EDT或IO线程,这是一个有用的日志管理策略。
摘要由CSDN通过智能技术生成

Logback的一项新颖功能是SiftingAppenderJavaDoc )。 简而言之,它是一个代理附加器,它为给定运行时属性的每个唯一值创建一个子附加器。 通常,此属性来自MDC 。 这是基于上面链接的官方文档的示例:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
 
    <appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender">
        <discriminator>
            <key>userid</key>
            <defaultValue>unknown</defaultValue>
        </discriminator>
        <sift>
            <appender name="FILE-${userid}" class="ch.qos.logback.core.FileAppender">
                <file>user-${userid}.log</file>
                <layout class="ch.qos.logback.classic.PatternLayout">
                    <pattern>%d{HH:mm:ss:SSS} | %-5level | %thread | %logger{20} | %msg%n%rEx</pattern>
                </layout>
            </appender>
        </sift>
    </appender>
 
    <root level="ALL">
        <appender-ref ref="SIFT" />
    </root>
</configuration>

注意, <file>属性是使用${userid}属性进行参数化的。 这个财产来自哪里? 它必须放在MDC中。 例如,在使用Spring Security的Web应用程序中,我倾向于在SecurityContextHolder的帮助下使用servlet过滤器:

import javax.servlet._
import org.slf4j.MDC
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.core.userdetails.UserDetails
 
class UserIdFilter extends Filter
{
    def init(filterConfig: FilterConfig) {}
 
    def doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {
        val userid = Option(
            SecurityContextHolder.getContext.getAuthentication
        ).collect{case u: UserDetails => u.getUsername}
 
        MDC.put("userid", userid.orNull)
        try {
            chain.doFilter(request, response)
        } finally {
            MDC.remove("userid")
        }
 
    }
 
    def destroy() {}
}

只要确保在Spring Security过滤器之后应用此过滤器即可。 但这不是重点。 文件名中${userid}占位符的存在会导致筛选追加程序为该属性的每个不同值(因此:不同的用户名)创建一个子追加程序。 如果未设置MDC属性,以这种配置运行Web应用程序将快速创建多个日志文件,例如user-alice.loguser-bob.loguser-unknown.log user-bob.log 。 另一个用例是使用线程名称而不是MDC属性。 不幸的是,它不是内置的,但是可以使用自定义Discriminator而不是默认的MDCBasedDiscriminator轻松插入:

public class ThreadNameBasedDiscriminator implements Discriminator<ILoggingEvent> {
 
    private static final String KEY = "threadName";
 
    private boolean started;
 
    @Override
    public String getDiscriminatingValue(ILoggingEvent iLoggingEvent) {
        return Thread.currentThread().getName();
    }
 
    @Override
    public String getKey() {
        return KEY;
    }
 
    public void start() {
        started = true;
    }
 
    public void stop() {
        started = false;
    }
 
    public boolean isStarted() {
        return started;
    }
}

现在,我们必须指示logback.xml使用我们的自定义标识符:

<appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender">
    <discriminator class="com.blogspot.nurkiewicz.ThreadNameBasedDiscriminator"/>
    <sift>
        <appender class="ch.qos.logback.core.FileAppender">
            <file>app-${threadName}.log</file>
            <layout class="ch.qos.logback.classic.PatternLayout">
                <pattern>%d{HH:mm:ss:SSS} | %-5level | %logger{20} | %msg%n%rEx</pattern>
            </layout>
        </appender>
    </sift>
</appender>

请注意,我们不再将%thread放入PatternLayout –不必要,因为线程名是日志文件名的一部分:

  • app-main.log
  • app-http-nio-8080-exec-1.log
  • app-taskScheduler-1
  • app-ForkJoinPool-1-worker-1.log
  • ……依此类推

对于服务器应用程序,这可能不是最方便的设置,但是在台式机上,如EDT ,IO线程等专注线程数量有限,这可能是一个重要的选择。


翻译自: https://www.javacodegeeks.com/2013/04/siftingappender-logging-different-threads-to-different-log-files.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值