我觉得对于logback大家不太明白的有:过滤器、logger和root以及其中的一些属性的关系。其他的应该不是多迷糊,所以我就主要说说这几个的关系,并且为了清晰我只说控制台日志,写到文件的日志配置大同小异!
提前声明:最终打印的日志的级别是和过滤器、root、logger三者都相关的。
一、过滤器
过滤器可以在一个appender中设置多个,并且会从上到下依次过滤
1.LevelFilter
这个过滤器的作用是:过滤日志的级别,并且可以配合三个标签使用<level>、<onMatch>、<onMismatch>
<level>:设置你想要的级别,大小写无所谓(在一个地方看到一种写法<level>INFO,DEBUG</level>,然而我测试时没发现这种写法有什么作用,他还是按照info的级别没有debug,root中写的是debug)
<onMatch>:设置日志级别匹配时的操作,有三个选择:ACCEPT、DENY、NEUTRAL。
ACCEPT:接收属于设置的级别的日志
DENY:拒绝设置的级别的日志
NEUTRAL:对设置的级别的日志不作处理,如果有多个过滤器,会交给下一个过滤器进行过滤操作。
<onMismatch>:设置日志级别不匹配时的操作,三个选择同上
ACCEPT:不匹配时接收
DENY:不匹配时拒绝
NEUTRAL:不匹配时不作处理,交给下个过滤器。
<!--控制台日志--> <appender name="consoleApp" class="ch.qos.logback.core.ConsoleAppender"> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>INFO</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> <layout class="ch.qos.logback.classic.PatternLayout"> <pattern> %date{yyyy-MM-dd HH:mm:ss.SSS} %-5level[%thread]%logger{56}.%method:%L -%msg%n </pattern> </layout> </appender>
2.ThresholdFilter
这个过滤器作用是:过滤掉低于设置的等级的日志,只保留所有高于设置的等级的日志。如下:假设忽略root或logger中设置的等级,则只会在控制台输出warn、error级别的日志。
<!--控制台日志--> <appender name="consoleApp" class="ch.qos.logback.core.ConsoleAppender"> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>WARN</level> </filter> <layout class="ch.qos.logback.classic.PatternLayout"> <pattern> %date{yyyy-MM-dd HH:mm:ss.SSS} %-5level[%thread]%logger{56}.%method:%L -%msg%n </pattern> </layout> </appender>
3.自定义过滤器
比如我的业务场景是:我要在mdc中放值然后在logback中取值,如果某个值取不到就不打印日志。
1.先写主要过滤逻辑
package com.filter; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.filter.Filter; import ch.qos.logback.core.spi.FilterReply; import org.springframework.util.StringUtils; public class SimpleLogFilter extends Filter<ILoggingEvent> { @Override public FilterReply decide(ILoggingEvent event) {//通过event可以取到几乎日志的所有字段,或者判断日志中是否包含指定的文字信息,这个需要自己去写逻辑。 if (StringUtils.isEmpty(event.getMDCPropertyMap().get("name"))) { return FilterReply.DENY;//deny则是拒绝,也即如果我在mdc中不能取到name这个字段对应的信息,就不打印日志。 } else { return FilterReply.NEUTRAL;//交给下个过滤器处理,本自定义过滤器不处理。 } } }
2.在logback中添加我们自己写的过滤器,class中对应以上类的全限定名。这样即可过滤所有%X{name}取不到值的情况。
<!--控制台日志--> <appender name="consoleApp" class="ch.qos.logback.core.ConsoleAppender"> <filter class="com.filter.SimpleLogFilter"/> <layout class="ch.qos.logback.classic.PatternLayout"> <pattern>%X{name} %X{age} %X{like}-----%date{yyyy-MM-dd HH:mm:ss.SSS} %-5level[%thread]%logger{56}.%method:%L -%msg%n</pattern>
</layout>
</appender>
3.测试的controller,你会发现当你调用test1时不会打印日志,调用test2时才会打印日志。
package com.controller; import com.pojo.JsonData; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping(path = "/api/log/") public class LoggerController { Logger logger= LoggerFactory.getLogger(getClass()); @RequestMapping(path = "test1") public Object logTest1(){ logger.trace("-----trace级别日志-----"); logger.debug("-----debug级别日志-----"); logger.info("-----info级别日志-----"); logger.warn("-----warn级别日志-----"); logger.error("-----error级别日志-----"); return JsonData.buildSuccess(); } @RequestMapping(path = "test2") public Object logTest2(){ MDC.put("name","yangche"); MDC.put("age","25"); MDC.put("like","wujing"); logger.trace("-----trace级别日志-----"); logger.debug("-----debug级别日志-----"); logger.info("-----info级别日志-----"); logger.warn("-----warn级别日志-----"); logger.error("-----error级别日志-----"); logger.info(""); MDC.clear(); return JsonData.buildSuccess(); } }
二、logger和root以及其中的一些属性的关系(此处假设没有设置过滤器)
<!--控制台日志--> <appender name="consoleApp" class="ch.qos.logback.core.ConsoleAppender"> <layout class="ch.qos.logback.classic.PatternLayout"> <pattern> %date{yyyy-MM-dd HH:mm:ss.SSS} %-5level[%thread]%logger{56}.%method:%L -%msg%n </pattern> </layout> </appender>
<logger name="com.controller.LoggerController" additivity="false"> <appender-ref ref="consoleApp" /> </logger> <!--root level最低级别--> <root level="debug"> <appender-ref ref="consoleApp"/> <appender-ref ref="fileInfoApp"/> <appender-ref ref="fileErrorApp"/>
<root/>
1、logger的name属性配置的是打印某一个类,或某一个包的日志信息,additivity作用是是否相加到父,也就是如果你在logger配置了appender又在root中配置了相同的appender,设置为true会看到控制台打印了两遍日志,如果设置为false则只打印一次root中的相同appender不生效。
logger中的属性说明:
name:配置的是打印某一个类,或某一个包的日志信息
additivity:是否相加到父,也就是如果你在logger配置了appender又在root中配置了相同的appender,设置为true会看到控制台打印了两遍日志,如果设置为false则只打印一次root中的相同appender不生效。默认为true。
level:设置一个打印的最低级别,如果你设置的是debug,则appender中会收到debug、info、warn、error,然后有过滤器会再对这些级别进行过滤。如果你设置为warn,则appender中只能收到warn、error级别的日志,然后过滤器只能对这两个级别的日志进行过滤。
root中的属性说明:
level:也是设置一个最低的打印级别,appender收到的日志级别只能是大于等于这个设定级别的日志。