filter分为两类,

第一类,TurboFilters,它构成了filter链,类似于servlet的filter。适用于处理请求流程的第一步。

第二类,Appender中配置的filter。适用于其对应的appender,在FileAppender中配置的filter不会对ConsoleAppender有效。

1、TurboFilters

 它的知识点分为两部分。

第一部分,介绍内置的TurboFilter。

第二部分,介绍如何自定义Filter。

1.1  MDCTurboFilter

MDCTurboFilter根据MDC中的变量进行过滤,首先检查变量是否存在,其次检查变量的值是否与配置的值相等。

示例:只输出test用户的日志。

<turboFilter class="ch.qos.logback.classic.turbo.MDCFilter">
	<MDCKey>username</MDCKey>
	<Value>test</Value>
	<OnMatch>ACCEPT</OnMatch>
	<OnMismatch>DENY</OnMismatch>
</turboFilter>

1.2   MarkerFilter

MarkerFilter根据日志请求携带的标记进行过滤,检查二者的Marker对象是否相等,即name属性是否相等。

示例:输出只携带Important标记的日志

<turboFilter class="ch.qos.logback.classic.turbo.MarkerFilter">
	<Marker>Important</Marker>
	<OnMatch>DENY</OnMatch>
</turboFilter>

1.3   DuplicateMessageFilter

DuplicateMessageFilter根据日志信息的重复次数进行过滤。日志信息重复的判断条件有:

  1. 非参数化情形下,日志信息完全相同。即日志信息中不包含{}。
  2. 参数化情况下,日志信息相同,包含的{}个数和位置相同,参数的值可以不同。

它的AllowedRepetitions代表可以重复的次数,默认值为5。

需要注意的是日志信息第一次出现,第二次出现表示第一次重复的含义,所以当设置为5时,总共包含日志信息本身和5次重复信息,总共是6次。

示例:

<turboFilter class="ch.qos.logback.classic.turbo.DuplicateMessageFilter">
	<!-- 最多重复3次 -->
	<AllowedRepetitions>3</AllowedRepetitions>
</turboFilter>

1.4  自定义

步骤如下:

第一步,继承TurboFilter,重写decide方法。

public class MyTurboFilter extends TurboFilter {
	private String testMarkerStr;
	private Marker testMarker;

	@Override
	public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable t) {
		if (!isStarted()) {
			return FilterReply.NEUTRAL;
		}
		// Marker对象重写了equals方法,Marker相等只需要Marker的name属性相等
		if ((testMarker.equals(marker))) {
			return FilterReply.NEUTRAL;
		} else {
			return FilterReply.DENY;
		}
	}

	public String getTestMarkerStr() {
		return testMarkerStr;
	}

	public void setTestMarkerStr(String testMarkerStr) {
		this.testMarkerStr = testMarkerStr;
	}

	// 每一种日志框架的核心对象都有生命周期的概念,在使用前必须确保已经start
	@Override
	public void start() {
		if (testMarkerStr != null && testMarkerStr.length() != 0) {
			// 将字符串转换为Marker对象
			testMarker = MarkerFactory.getMarker(testMarkerStr);
			super.start();
		}
	}
}

  第二步,注册。

<turboFilter class="learn.logback.chapter7.MyTurboFilter">
	<Marker>sample</Marker>
</turboFilter>

2、Appender Filter

与TurboFilter类似,它的知识点也分为两部分,内置和自定义。

2.1  LevelFilter

当logging request的日志级别与levelFilter中配置的日志级别相等时,符合过滤器条件。

示例:只输出info级别的日志

<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
	<!-- 配置levelFilter -->
	<filter class="ch.qos.logback.classic.filter.LevelFilter">
		<level>INFO</level>
		<onMatch>NEUTRAL</onMatch>
		<onMismatch>DENY</onMismatch>
	</filter>
	<encoder>
		<pattern>${default_pattern}</pattern>
	</encoder>
</appender>

2.2  ThresholdFilter

当logging request的日志级别大于等于配置中的日志级别时,符合过滤器条件。

示例:输出info和高于info级别的日志

<appender name="console"
	class="ch.qos.logback.core.ConsoleAppender">
	<!-- 配置ThresholdFilter -->
	<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
		<level>INFO</level>
	</filter>
	<encoder>
		<pattern>${default_pattern}</pattern>
	</encoder>
</appender>

2.3   EvaluatorFilter

官网中提及两种EvaluatorFilter,一种是GEventEvaluatorFilter,它需要在配置文件中添加Groovy表达式作为过滤条件,另外一种是JaninoEventEvaluator,它需要在配置文件中添加Java代码作为过滤条件。

首先不建议在配置文件中夹杂其他语言的语法,不论是Groovy还是Java。

其次是EvaluatorFilter它实现的功能,其他过滤器也可以实现。

这样做可以避免在配置文件中夹杂其他语言的语法,使得配置文件更简洁,更方便阅读和维护。

2.4  自定义

步骤如下:

第一步,继承Filter抽象类,实现decide方法。

public class MyFilter extends Filter<ILoggingEvent> {
	@Override
	public FilterReply decide(ILoggingEvent event) {
		// 如果loggerName 中存在 test,忽略这些日志信息
		if (event.getLoggerName().toUpperCase().contains("TEST")) {
			return FilterReply.DENY;
		}
		return FilterReply.DENY;
	}
}

  第二步,注册

<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
	<!-- 注册myFilter -->
	<filter class="learn.logback.chapter7.MyFilter"/>
	<encoder>
		<pattern>${default_pattern}</pattern>
	</encoder>
</appender>

3、比较

第一点,适用范围不同。TurboFilter是影响所有的log 请求。Appender filter只适用于其对应的Appender。

第二点,执行顺序不同,获取到的信息也不同。TurboFilter发生在流程第一步,此时未生成LoggingEvent对象。Appender filter在流程第四步,获取到的信息更全面,可以获取到LoggingEvent对象

作者:蜗牛旅行1899