Logback.xml配置文件(过滤器、重复记录日志问题)

日志重复打印问题

案例一:

logback.xml

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
	<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
		<encoder>
			<pattern>[%-5p][%d{yyyy/MM/dd HH:mm:ss}][%t] %logger - %m%n</pattern>
			<charset>UTF-8</charset>
		</encoder>
	</appender>
	<logger name="log.LogTest" level="DEBUG">
		<appender-ref ref="CONSOLE"/>
	</logger>
	<root level="INFO">
		<appender-ref ref="CONSOLE"/>
	</root>
</configuration>

示例代码:

public class LogTest {
	private static final Logger log = LoggerFactory.getLogger(LogTest.class);
	@Test
	public void testLogback() {
		log.debug("debug");
		log.info("info");
		log.warn("warn");
		log.error("error");
	}
}

打印结果:

[DEBUG][2020/09/06 20:47:30][main] log.LogTest - debug
[DEBUG][2020/09/06 20:47:30][main] log.LogTest - debug
[INFO ][2020/09/06 20:47:30][main] log.LogTest - info
[INFO ][2020/09/06 20:47:30][main] log.LogTest - info
[WARN ][2020/09/06 20:47:30][main] log.LogTest - warn
[WARN ][2020/09/06 20:47:30][main] log.LogTest - warn
[ERROR][2020/09/06 20:47:30][main] log.LogTest - error
[ERROR][2020/09/06 20:47:30][main] log.LogTest - error

可见打印代码是重复的,问题出在哪里?

日志重复原因

原因是,logger 标签和root都配置了appender,当日志打印的时候,两个都会打印日志,可以将logger中的appender删除

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
	<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
		<encoder>
			<pattern>[%-5p][%d{yyyy/MM/dd HH:mm:ss}][%t] %logger - %m%n</pattern>
			<charset>UTF-8</charset>
		</encoder>
	</appender>
	<logger name="log.LogTest" level="DEBUG"/>
	<root level="INFO">
		<appender-ref ref="CONSOLE"/>
	</root>
</configuration>
[DEBUG][2020/09/06 20:52:01][main] log.LogTest - debug
[INFO ][2020/09/06 20:52:01][main] log.LogTest - info
[WARN ][2020/09/06 20:52:01][main] log.LogTest - warn
[ERROR][2020/09/06 20:52:01][main] log.LogTest - error

案例二:

我们想实现将INFO日志写入INFO_FILE,ERROR日志写入ERROR_FILE,java测试代码不变,logback.xml如下:

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
	<property name="logDir" value="./logs" />
	<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
		<encoder>
			<pattern>[%-5p][%d{yyyy/MM/dd HH:mm:ss}][%t] %logger - %m%n</pattern>
			<charset>UTF-8</charset>
		</encoder>
		<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
			<level>DEBUG</level>
		</filter>
	</appender>
	<appender name="INFO_FILE" class="ch.qos.logback.core.FileAppender">
		<File>${logDir}/INFO_FILE.log</File>
		<encoder>
			<pattern>[%-5p][%d{yyyy/MM/dd HH:mm:ss}][%t] %logger - %m%n</pattern>
			<charset>UTF-8</charset>
		</encoder>
		<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
			<level>INFO</level>
		</filter>
	</appender>
	<appender name="ERROR_FILE" class="ch.qos.logback.core.FileAppender">
		<File>${logDir}/ERROR_FILE.log</File>
		<encoder>
			<pattern>[%-5p][%d{yyyy/MM/dd HH:mm:ss}][%t] %logger - %m%n</pattern>
			<charset>UTF-8</charset>
		</encoder>
		<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
			<level>ERROR</level>
		</filter>
	</appender>
	<logger name="log.LogTest" level="DEBUG"/>
	<root level="INFO">
		<appender-ref ref="CONSOLE"/>
		<appender-ref ref="INFO_FILE"/>
		<appender-ref ref="ERROR_FILE"/>
	</root>
</configuration>
INFO_FILE:
[INFO ][2020/09/06 21:06:26][main] log.LogTest - info
[WARN ][2020/09/06 21:06:26][main] log.LogTest - warn
[ERROR][2020/09/06 21:06:26][main] log.LogTest - error
ERROR_FILE:
[ERROR][2020/09/06 21:06:26][main] log.LogTest - error

可见,info日志把warn和error也打印出来了,与error日志产生重复,不符合我们开始的需求,这里是什么问题呢?

问题原因

配置错误,这里要讲到两个比较常见的过滤器,ThresholdFilter和LevelFilter
其中ThresholdFilter是记录比配置的level大的所有日志,LevelFilter配合Onmatch和misMatch过滤某几个特定的level日志。

  • ThresholdFilter:
    public FilterReply decide(ILoggingEvent event) {
        if (!isStarted()) {
            return FilterReply.NEUTRAL;
        }
		// 大于等于配置的level,则通过,返回NEUTRAL,否则deny
        if (event.getLevel().isGreaterOrEqual(level)) {
            return FilterReply.NEUTRAL;
        } else {
            return FilterReply.DENY;
        }
    }

其中NEUTRAL为透传,直接传递到下一个filter,如果不存在下一个filter,就打印日志。示例中用了ThresholdFilter,level为INFO,所以大于等于INFO的日志都会打印。

  • LevelFilter
    public FilterReply decide(ILoggingEvent event) {
        if (!isStarted()) {
            return FilterReply.NEUTRAL;
        }
        // 如果日志level与配置相同,则根据配置的onMatch与onMismatch决定
        if (event.getLevel().equals(level)) {
            return onMatch;
        } else {
            return onMismatch;
        }
    }

如果想只打印INFO日志,可以使用LevelFilter,做如下修改:

	...
	<appender name="INFO_FILE" class="ch.qos.logback.core.FileAppender">
		<File>${logDir}/INFO_FILE.log</File>
		<filter class="ch.qos.logback.classic.filter.LevelFilter">
			<level>INFO</level>
			<onMatch>ACCEPT</onMatch>
			<onMismatch>DENY</onMismatch>
		</filter>
		<encoder>
			<pattern>[%-5p][%d{yyyy/MM/dd HH:mm:ss}][%t] %logger - %m%n</pattern>
			<charset>UTF-8</charset>
		</encoder>
		...
拓展

除了上面的过滤器,还有一些,如EvaluatorFilter,这是一个运算过滤器,你可以自行实现一个ch.qos.logback.core.boolex.EventEvaluator接口的boolean evaluate(E event)方法实例作为运算器,运算返回true的日志将会通过校验。
目前已有几个默认可用的实现:
在这里插入图片描述
选OnMarkerEvaluator讲一下,它可以用来收集打标记的日志。如下面的<appender name="LOGIN_SUCCESS_FILE:

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
	<property name="logDir" value="./logs" />
	<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
		<encoder>
			<pattern>[%-5p][%d{yyyy/MM/dd HH:mm:ss}][%t] %logger - %m%n</pattern>
			<charset>UTF-8</charset>
		</encoder>
		<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
			<level>DEBUG</level>
		</filter>
	</appender>
	<appender name="INFO_FILE" class="ch.qos.logback.core.FileAppender">
		<File>${logDir}/INFO_FILE.log</File>
		<filter class="ch.qos.logback.classic.filter.LevelFilter">
			<level>INFO</level>
			<onMatch>ACCEPT</onMatch>
			<onMismatch>DENY</onMismatch>
		</filter>
		<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
			<evaluator class="ch.qos.logback.classic.boolex.OnErrorEvaluator">
			</evaluator>
			<onMatch>ACCEPT</onMatch>
			<onMismatch>DENY</onMismatch>
		</filter>
		<encoder>
			<pattern>[%-5p][%d{yyyy/MM/dd HH:mm:ss}][%t] %logger - %m%n</pattern>
			<charset>UTF-8</charset>
		</encoder>
	</appender>
	<appender name="ERROR_FILE" class="ch.qos.logback.core.FileAppender">
		<File>${logDir}/ERROR_FILE.log</File>
		<encoder>
			<pattern>[%-5p][%d{yyyy/MM/dd HH:mm:ss}][%t] %logger - %m%n</pattern>
			<charset>UTF-8</charset>
		</encoder>
		<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
			<level>ERROR</level>
		</filter>
	</appender>
	// 看这里!!!!!!!!
	<appender name="LOGIN_SUCCESS_FILE" class="ch.qos.logback.core.FileAppender">
		<File>${logDir}/LOGIN_SUCCESS_FILE.log</File>
		<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
			<evaluator class="ch.qos.logback.classic.boolex.OnMarkerEvaluator">
				// login_success标记
				<marker>login_success</marker>
			</evaluator>
			<onMatch>ACCEPT</onMatch>
			<onMismatch>DENY</onMismatch>
		</filter>
		<encoder>
			<pattern>[%-5p][%d{yyyy/MM/dd HH:mm:ss}][%t] %logger - %m%n</pattern>
			<charset>UTF-8</charset>
		</encoder>
	</appender>
	<logger name="log.LogTest" level="DEBUG"/>
	<root level="INFO">
		<appender-ref ref="CONSOLE"/>
		<appender-ref ref="INFO_FILE"/>
		<appender-ref ref="ERROR_FILE"/>
		<appender-ref ref="LOGIN_SUCCESS_FILE"/>
	</root>
</configuration>

创建login_success标记,表示对带有login_success标记的日志进行收集,其余日志不收集。

  • 示例代码:
public class LogTest {
	private static final Logger log = LoggerFactory.getLogger(LogTest.class);
	@Test
	public void testLogback() {
		// 获取marker,打日志的时候传入marker标记
		Marker timeMarker = MarkerFactory.getMarker("login_success");
		log.info(timeMarker,"XXX用户登录成功!");
		log.debug("debug");
		log.info("info");
		log.warn("warn");
		log.error("error");
	}
}

日志打印结果:
在这里插入图片描述
成功!

logback.xml配置文件Logback框架的核心配置文件,它可以直接拷贝到src目录下(必须是src下)。在这个配置文件中,你可以定义日志的输出格式、输出级别、输出位置等信息,以满足不同项目的需求。一般情况下,我们可以通过在配置文件中设置appender来指定日志的输出方式,例如控制台输出或者文件输出。另外,你还可以设置logger来指定具体的日志记录器,以及设置日志的级别和过滤条件等。在代码中,你可以通过创建Logback框架提供的Logger对象来记录系统的日志信息。通过调用Logger对象提供的方法,你可以选择不同的日志级别来记录不同重要程度的信息,比如debug、info、warn、error等。配置好logback.xml文件,并使用Logger对象记录日志,可以帮助你更好地管理和追踪系统的运行情况。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [黑马Java学习第十一天配置文件(properties、XML)、日志、多线程(一)](https://blog.csdn.net/qq_57277310/article/details/129429983)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* [logbackーslf4j-配置文件实例 难得](https://download.csdn.net/download/zhongying125/1644361)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值