You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Logback自定义过滤器未过滤指定消息问题求助

问题分析与解决方案

你遇到的问题其实是个很典型的Logback过滤器误区:你的代码只检查了ILoggingEvent.getMessage()返回的日志消息文本,但那些你想过滤的「Connection reset by peer」「Broken pipe」等内容,实际是存放在日志事件附带的Throwable异常栈轨迹里,并非直接在日志消息中。

看你提供的日志示例就能明白:

2018-03-05 21:05:09,933 WARN [epollEventLoopGroup-2-6] - [io.netty.channel.DefaultChannelPipeline] - An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.
io.netty.channel.unix.Errors$NativeIoException: syscall:read(..) failed: Connection reset by peer

这里的日志消息是第一行的描述文本,而「Connection reset by peer」是NativeIoException的异常信息,属于ILoggingEvent.getThrowableProxy()的内容,你的原过滤器完全没检查这部分,自然无法过滤。

修复后的自定义过滤器代码

修改你的LogbackCustomFilter,添加对异常栈的递归检查逻辑,覆盖整个异常链(避免嵌套cause异常漏检):

package logging;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.IThrowableProxy;
import ch.qos.logback.core.filter.Filter;
import ch.qos.logback.core.spi.FilterReply;

public class LogbackCustomFilter extends Filter<ILoggingEvent> {
    private static final String[] FILTERED_PHRASES = {
        "ClosedChannelException",
        "An established connection was aborted",
        "Connection reset by peer",
        "Broken pipe"
    };

    @Override
    public FilterReply decide(ILoggingEvent event) {
        // 先过滤非WARN/ERROR级别的日志
        if (!event.getLevel().isGreaterOrEqual(Level.WARN)) {
            return FilterReply.DENY;
        }

        // 检查日志消息本身是否包含过滤关键词
        String message = event.getMessage();
        if (containsFilteredPhrase(message)) {
            return FilterReply.DENY;
        }

        // 检查异常栈中的所有异常信息
        IThrowableProxy throwableProxy = event.getThrowableProxy();
        if (throwableProxy != null && containsFilteredPhraseInThrowable(throwableProxy)) {
            return FilterReply.DENY;
        }

        // 无匹配关键词,允许日志通过
        return FilterReply.NEUTRAL;
    }

    // 辅助方法:检查字符串是否包含任意过滤关键词
    private boolean containsFilteredPhrase(String text) {
        if (text == null) {
            return false;
        }
        for (String phrase : FILTERED_PHRASES) {
            if (text.contains(phrase)) {
                return true;
            }
        }
        return false;
    }

    // 辅助方法:递归遍历异常链,检查是否有包含关键词的异常信息
    private boolean containsFilteredPhraseInThrowable(IThrowableProxy throwableProxy) {
        if (throwableProxy == null) {
            return false;
        }
        // 检查当前异常的消息
        if (containsFilteredPhrase(throwableProxy.getMessage())) {
            return true;
        }
        // 递归检查嵌套的cause异常
        return containsFilteredPhraseInThrowable(throwableProxy.getCause());
    }
}

额外注意事项

  • 确保你的过滤器类已正确编译,且在Logback的类路径中,避免类加载失败导致过滤器失效
  • 若使用较旧版本的Logback,IThrowableProxy的API可能略有差异,但核心逻辑一致:必须遍历异常链检查消息
  • 调试时可以临时添加打印日志(比如输出event.getMessage()和异常信息),确认过滤器确实能捕获到目标内容

内容的提问来源于stack exchange,提问作者Martin Asenov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:50:54