最近同事提了一个需求过来,他觉得项目对于第三方日志记录的太多了,只想记录一些业务相关的日志减少对于框架日志的显示。
具体要求就是对于框架日志只显示warn等级以上的,而业务日志显示info等级以上的。
这里主要使用的是slf4j与logback结合的方法。使用过滤器来实现对日志的过滤。
首先是现在项目内封装一个日志管理工具。在需要使用到日志记录程序运行状态时直接调用该方法,而不是重新生成一个Logger对象。
这个地方有需要考虑取舍的,比如如果我直接在类中声明创建一个Logger那么在日志记录的时候我可以直接通过看Logger的name就能知道我这个Logger是记录在哪里的,方便迅速排查问题。但是对于对日志记录格式有操作需求的,就需要自己封装。这里指的并不是对于显示线程,显示日期之类的要求,那些只需要规定好pattern格式就可以了。
首先先介绍一下用到的maven依赖:
<dependencies>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
dependency>
<dependency>
<groupId>ch.qos.logbackgroupId>
<artifactId>logback-classicartifactId>
<version>1.2.3version>
dependency>
<dependency>
<groupId>org.codehaus.janinogroupId>
<artifactId>janinoartifactId>
<version>3.0.7version>
dependency>
dependencies>
下面是我的Log管理器的样例:
package log.demo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public final class LogDemo {
private static final Logger LOGGER = LoggerFactory.getLogger("LogDemo");
public static void debug(String format, Object... args) {
LOGGER.debug(format, args);
}
public static void info(String format, Object... args) {
LOGGER.info(format, args);
}
public static void warn(String format, Object... args) {
LOGGER.warn(format, args);
}
public static void error(String format, Object... args) {
LOGGER.error(format, args);
}
}
接下来是配置logback.xml:
<configuration debug="false">
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
<evaluator>
<expression>return logger.equals("LogDemo");expression>
evaluator>
<onMatch>ACCEPTonMatch>
<onMismatch>NEUTRALonMismatch>
filter>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>WARNlevel>
filter>
<encoder>
<pattern>[%-5level] %d{HH:mm:ss.SSS} [%thread] %logger{36} - %msg%n
pattern>
encoder>
appender>
<root level="ALL">
<appender-ref ref="console" />
root>
configuration>
通过两个过滤器实现第三方框架日志与项目本身的日志的过滤管理。
第三方日志只输出WARN以上的日志等级,而项目本身的日志全部输出。
首先是第一个过滤器EvaluatorFilter,这个过滤器是通过获取LoggingEvent中的属性来进行过滤的。expression标签表达了判断属性。如果返回结果为true,则进行onMatch标签中的操作,否则则按照onMismatch标签进行处理。
标签一共有三个值:
属性 |
说明 |
DENY |
过滤该日志,不输出 |
NEUTRAL |
不做任何操作,等待下个过滤器过滤 |
ACCEPT |
接受这个日志,直接输出 |
这个过滤器将以LogDemo为名的Logger记录的日志全部输出,将其他的日志进入下一个过滤器进行过滤。在这里如果没有封装日志管理器的话,可以通过将expression改为一下形式:
return logger.contains("log.demo");
其中log.demo改为项目的根包名。
ThresholdFilter过滤器将日志等级在WARN以下的日志过滤了。
最后通过一个Test来查看运行结果。
package log.demo;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogDemoTest {
private static final Logger LOGGER = LoggerFactory.getLogger(LogDemoTest.class);
@Test
public void testInfo() {
LogDemo.debug("This is {}.", "LogDemo test");
LogDemo.info("This is {}.", "LogDemo test");
LogDemo.warn("This is {}.", "LogDemo test");
LogDemo.error("This is {}.", "LogDemo test");
LOGGER.debug("This is {}.", "LogDemo test");
LOGGER.info("This is {}.", "LogDemo test");
LOGGER.warn("This is {}.", "LogDemo test");
LOGGER.error("This is {}.", "LogDemo test");
}
}
输出日志结果:
[DEBUG] 19:02:14.479 [main] LogDemo - This is LogDemo test.
[INFO ] 19:02:14.482 [main] LogDemo - This is LogDemo test.
[WARN ] 19:02:14.483 [main] LogDemo - This is LogDemo test.
[ERROR] 19:02:14.483 [main] LogDemo - This is LogDemo test.
[WARN ] 19:02:14.483 [main] log.demo.LogDemoTest - This is LogDemo test.
[ERROR] 19:02:14.483 [main] log.demo.LogDemoTest - This is LogDemo test.
这样就完成了第三方日志过滤的功能,做的比较简陋,如果想自定义过滤方法的话,可以通过继承类EvaluatorFilter的方式来实现。