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

