使用SLF4J和LOGBACK (二 :核心组件 )
在正式使用和配置logback之前,先来了解一下logback中的三个核心组件,日后的使用,我们配置的也是这三类核心组件。所以有必要先对它们有个基础了解。
1. 日志记录器(Logger)
Logger
Logger是一个命名实体,并遵循分层命名规则,它的层次由命名中的.符号表示。例如一个logger名为:com.foo,它就是com.foo.bar的父logger,二者有继承关系。
RootLogger
RootLogger是一个特殊的logger实体,它由logback自身提供,无需我们定义,同时它也是logger继承结构中的顶级父对象(类似于Java中的Object),所有未定义层级
关系的logger默认都是RootLogger的子集。
Logger的继承关系
如果一个给定的Logger未指定级别,那么它将从具有明确级别的最近的父类中继承到父类的日志级别,上边说了,RootLogger是这个级别中顶级的存在,
如果给定的Logger没有其他父级,那么最终将继承RootLogger的日志级别,默认为:DEBUG
Logger名称 | 指定的级别 | 有效级别 |
root | DEBUG | DEBUG |
X | none | DEBUG |
X.Y | none | DEBUG |
X.Y.Z | none | DEBUG |
在这个表中root代表RootLogger,它的默认级别是DEBUG,剩下三行的X X.Y X.Y.Z均未明确指定级别,根据继承关系,它们的有效级别都为DEBUG,由RootLogger继承而来
Logger名称 | 指定的级别 | 有效级别 |
root | DEBUG | DEBUG |
X | INFO | INFO |
X.Y | none | INFO |
X.Y.Z | none | INFO |
在这个表格中,X指定了为INFO级别,而X.Y和X.Y.Z均未指定级别,但是它们的有效级别为INFO,是因为距离它们最近的父级X指定了级别为INFO,所以它们继承了离它们最近的父级日志的级别。
通过上述两个表格可以明白logger日志等级的继承关系,下边来说一下当使用logger.xxx()方法打印日志时的输出有效规则,所谓的输出有效规则就是对应级别的日志是否会输出。
Logger打印输出规则
按照日志级别由低到高有五个级别,依次为:TRACE, DEBUG, INFO, WARN, ERROR,对应的Logger实体中有五个打印方法:trace, debug, info, warn, error
我们要打印info级别的日志,需要使用logger.info()方法,但是日志是否输出有其自身的规则。在这里我们将Logger对象的五个级别设为q,而对应的五个打印方法的级别设为p,则有如下规则:
打印方法(p) | Logger级别(q) | ||||
TRACE | DEBUG | INFO | WARN | ERROR | |
trace | YES | NO | NO | NO | NO |
debug | YES | YES | NO | NO | NO |
info | YES | YES | YES | NO | NO |
warn | YES | YES | YES | YES | NO |
error | YES | YES | YES | YES | YES |
上述表格用一句话总结:打印方法的级别(p)必须>=Logger的级别(q),如果Logger的级别为info,那么debug和trace方法都不会输出,因为这两个级别低于info,不满足p >= q的条件
关于logger的继承关系和打印级别的输出,我写了一个简单的demo做为上述表格的演示,代码如下:
import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; import org.slf4j.LoggerFactory; public class SimpleLogLevel { //注意此处的logger对象为:ch.qos.logback.classic.Logger,为了下边设置日志级别 private static Logger loggerX = (Logger) LoggerFactory.getLogger("X"); private static Logger loggerXY = (Logger) LoggerFactory.getLogger("X.Y"); public static void main(String[] args) { //loggerX未设置日志级别,因此从RootLogger继承到默认的DEBUG级别 //trace日志不会输出,因为loggerX级别为debug,只会输出级别>=debug的日志 loggerX.info("-------------loggerX level from RootLogger------------"); loggerX.trace("loggerX trace"); loggerX.debug("loggerX debug"); loggerX.info("loggerX info"); //将loggerX显示设置为info级别,所以低于info级别的debug和trace都不会输出 loggerX.info("-------------loggerX level from self------------"); loggerX.setLevel(Level.INFO); //这里的debug日志不会输出,理由同上 loggerX.debug("loggerX-INFO debug log"); loggerX.info("loggerX-INFO info log"); loggerX.warn("loggerX-INFO warn log"); //loggerXY未配置级别,它会继承距离它最近的父级日志级别,这里就是loggerX,所以loggerXY的级别也为INFO //debug日志不会输出 loggerX.info("-------------loggerXY level from loggerX------------"); loggerXY.debug("loggerXY-debug debug log"); loggerXY.info("loggerXY-info info log"); loggerXY.warn("loggerXY-warn warn log"); } }