1、配置文件的基本结构
以<configuration>开头,后面有零个或多个<appender>元素,有零个或多个<logger>元素,有最多一个<root>元素。
Logback默认配置的步骤
(1). 尝试在 classpath 下查找文件 logback-test.xml;
(2). 如果文件不存在,则查找文件 logback.xml;
(3). 如果两个文件都不存在,logback 用 BasicConfigurator 自动对自己进行配置,这会导致记录输出到控制台。
BasicConfigurator 创建的是一个最小化配置。最小化配置由一个关联到根 logger 的ConsoleAppender 组成。输出用模式为%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 的 PatternLayoutEncoder 进行格式化。root logger 默认级别是 DEBUG。
2、根节点<configuration>包含的属性
scan: 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
scanPeriod: 设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。
debug: 当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 其他配置省略-->
</configuration>
3、appender
Appender主要用于指定日志输出的目的地,目的地可以是控制台、文件、远程套接字服务器、 MySQL、 PostreSQL、 Oracle和其他数据库、 JMS和远程UNIX Syslog守护进程等。并可以指定日志文件的一些属性。主要属性 :
(1)<File> 指定日志输出的目的地
(2)RollingFileAppender 包含的组件
<rollingPolicy> 负责日志轮转动作,可移动文件以及对文件改名
<triggeringPolicy>负责日志轮转的时机
(3)<layout> 负责把事件转换成字符串,格式化的日志信息的输出。日志具体格式参见:https://www.jianshu.com/p/75f7ace1bb96
(4)<filter> 可结合过滤器使用,只打印过滤器中级别的日志。
具体解析如下:
常用的appender
RollingPolicy
rollingPolicy 负责日志轮转动作,可移动文件以及对文件改名
TimeBasedRoolingPolicy:时间滚动策略,可以基于时间滚动按时间生成日志。即负责轮转的行为,也负责触发轮转 ,同时实现了RollingPolicy 和 TriggeringPolicy 接口。属性:
(1) fileNamePattern :定义了轮转时的属性名,强制属性 。 格式如:${LOG_HOME}/${LOGERROR_NAME}.%d{yyyy-MM-dd}.%i.log(每天轮转(晚上零点))
(2) maxHistory:保存历史记录的天数
(3) totalSizeCap:归档文件总大小
(4) cleanHistoryOnStart :boolean类型,如果设置为 true,那么在 appender 启动的时候,归档文件将会被删除。默认的值为 false。归档文件的删除通常在轮转期间执行。但是,有些应用的存活时间可能等不到轮转触发。对于这种短期应用,可以通过设置该属性为 true,在 appender 启动的时候执行删除操作。
(5) 多个JVM写同一个日志文件的配置,需要开启(节俭)prudent模式:<prudent>true</prudent>。TimeBasedRollingPolicy支持文件自动压缩。如果 fileNamePattern以 .gz 或者 .zip结尾,将会启动这个特性。
SizeAndTimeBasedRollingPolicy :基于大小和时间的滚动策略 。属性: maxFileSize(单个文件最大值)、maxHistory、 totalSizeCap。注意: %d 、 %i 这两个占位符都是强制要求的。在当前时间还没有到达周期轮转之前,日志文件达到了maxFileSize 指定的大小,会进行归档,递增索引从 0 开始。
注:在此之前使用的SizeAndTimeBasedFNATP,只定义文件大小maxFileSize ,结合TimeBasedRollingPolicy 中定义的时间maxHistory,来达到基于大小和时间的滚动,如下图(基于大小和时间的滚动策略 -旧版配置)。目前,SizeAndTimeBasedFNATP is deprecated. Use SizeAndTimeBasedRollingPolicy instead .
https://stackoverflow.com/questions/54033579/moving-to-sizeandtimebasedrollingpolicy-from-timebasedrollingpolicy-to-rollover
FixedWindowRollingPolicy :基于固定窗口的滚动策略 。这个策略的出现,我个人猜测是因为需要日志文件保持为某个特定的数量,防止滚动测策略导致过多的日志文件出现。这个策略出现得配合triggeringPolicy,给一个什么时候日志滚动一次的控制,这部分是跟上面两种策略所不一样的地方。属性:minIndex(窗口索引最小值)、maxIndex(窗口索引最大值)、fileNamePattern (必须包含%i)
TriggeringPolicy
TriggeringPolicy 用于通知RollingFileAppender 何时轮转。TriggeringPolicy接口仅仅只包含了一个方法。isTriggeringEvent() 接收当前活动的文件以及当前的日志事件作为参数。基于这些参数,通过具体的实现来决定轮转是不是应该发生。
TimeBasedRollingPolicy 是使用最广泛的触发策略。也可以用作轮转策略来使用。
SizeBasedTriggeringPolicy 观察当前活动文件的大小,如果已经大于了指定的值,它会给 RollingFileAppender 发一个信号触发对当前活动文件的轮转。只接收 maxFileSize 这一个参数,它的默认值是 10 MB。
TimeBasedRollingPolicy和SizeBasedTriggeringPolicy冲突,不能用这两个一起来控制时间和文件大小,详见:https://blog.csdn.net/wujianmin577/article/details/68922545
一般的组合:
TimeBasedRoolingPolicy
TimeBasedRoolingPolicy+SizeAndTimeBasedFNATP<=>SizeAndTimeBasedRollingPolicy
TimeBasedRollingPolicy + SizeBasedTriggeringPolicy 冲突FixedWindowRollingPolicy 单独不能使用
FixedWindowRollingPolicy +SizeBasedTriggeringPolicy
filter
1) LevelFilter 级别过滤器
根据日志级别进行过滤。当检测到当前日志的打印级别与当前过滤器配置的一样时,如logger.info(msg),同时过滤器设置为<level>info</level>,过滤器会根据onMath 和 onMismatch接收或拒绝日志.
子节点:
<level>:设置过滤级别
<onMatch>:用于配置符合过滤条件的操作
<onMismatch>:用于配置不符合过滤条件的操作
例:将过滤器的日志级别配置为INFO,所有INFO级别的日志交给appender处理,非INFO级别的日志,被过滤掉。
注意:LevelFilter 仅仅配置 level 是无法真正起作用的。由于没有配置 onMatch 和 onMismatch 属性,所以相当于这个过滤器是无用的,导致 level配置以上级别的日志都记录了。
可以看到,_info.log 中包含了 INFO、WARN 和 ERROR 三个级别的日志,不符合我们的预期;
2) ThresholdFilter 临界值过滤器
过滤掉低于指定临界值的日志。当日志级别等于或高于临界值时,过滤器返回NEUTRAL;当日志级别低于临界值时,日志会被拒绝。
例:error.log 包含了 WARN 和 ERROR 两个级别的日志。
3) EvaluatorFilter 求值过滤器
自定义条件,随意控制输出。需要额外的两个JAR包,commons-compiler.jar和janino.jar
<!-- https://mvnrepository.com/artifact/org.codehaus.janino/janino -->
<dependency>
<groupId>org.codehaus.janino</groupId>
<artifactId>janino</artifactId>
<version>3.1.0</version>
</dependency>
子节点:
<evaluator> : 鉴别器,常用的鉴别器是JaninoEventEvaluato,也是默认的鉴别器,它以任意的java布尔值表达式作为求值条件,求值条件在配置文件解释过成功被动态编译,布尔值表达式返回true就表示符合过滤条件
<expression>: 用于配置求值条件。求值表达式作用于当前日志,logback向求值表达式暴露日志的各种字段:
<onMatch>:用于配置符合过滤条件的操作
<onMismatch>:用于配置不符合过滤条件的操作
例:过滤掉所有日志消息中不包含“billing”字符串的日志。
例:记录带有 time 标记的日志
4、Logger、ROOT
(1)设置logger
用来设置某一个包或者具体的某一个类的日志打印级别、以及指定。仅有一个name属性,一个可选的level和一个可选的addtivity属性。
name:用来指定受此loger约束的某一个包或者具体的某一个类。即打印该包下的日志。
level:用来设置打印级别(日志级别),大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。如果未设置此属性,那么当前loger将会继承上级的级别。
addtivity:是否向上级loger传递打印信息。默认是true。设置为true,将该logger的name定义的包以及打印日志的级别level等都传给root,交由root再打印,而该logger是否打印取决于是否配置了appender。(相当于子类重写了父类的方法,level由子类决定)
可以包含零个或多个元素,标识这个appender将会添加到这个loger。
设置root
也是元素,但是它是根loger。只有一个level属性,应为已经被命名为"root".
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,不能设置为INHERITED或者同义词NULL。默认是DEBUG。
root可以理解为一个根节点,而其他的logger都可以看做root的子节点
所以默认root配置的appender属性logger都是使用的,如果不想使用可以logger定义时增加属性additivity="false"
ps:<logger name="net.jy.redis.controller.logback.LogbackController" level="warn" additivity="false"><appender-ref ref="stdout"/></logger>
因为上述关系,在class类使用getLogger("name/class")引入logger时,如果"name/class"未在配置文件中找到,则默认使用root配置
如果匹配到"name/class",则使用匹配到的appender配置的输出,同时可自行选择是否关闭root配置的appender输出
可以包含零个或多个元素,标识这个appender将会添加到这个loger。
<logger name="logback" />将控制logback包下的所有类的日志的打印,但是并没用设置打印级别,所以继承他的上级<root>的日志级别“DEBUG”;
没有设置addtivity,默认为true,将此loger的打印信息向上级传递;
没有设置appender,此loger本身不打印任何信息。
<root level="DEBUG">将root的打印级别设置为“DEBUG”,指定了名字为“STDOUT”的appender。
当执行logback.LogbackDemo类的main方法时,因为LogbackDemo 在包logback中,所以首先执行<logger name="logback" />,将级别为“DEBUG”及大于“DEBUG”的日志信息传递给root,本身并不打印;root接到下级传递的信息,交给已经配置好的名为“STDOUT”的appender处理,“STDOUT”appender将信息打印到控制台;
<logger name="logback" />将控制logback包下的所有类的日志的打印,但是并没用设置打印级别,所以继承他的上级<root>的日志级别“DEBUG”;
没有设置addtivity,默认为true,将此loger的打印信息向上级传递;
没有设置appender,此loger本身不打印任何信息。
<logger name="logback.LogbackDemo" level="INFO" additivity="false">控制logback.LogbackDemo类的日志打印,打印级别为“INFO”;
additivity属性为false,表示此loger的打印信息不再向上级传递,
指定了名字为“STDOUT”的appender,
<root level="DEBUG">将root的打印级别设置为“DEBUG”,指定了名字为“STDOUT”的appender。
当执行logback.LogbackDemo类的main方法时,先执行<logger name="logback.LogbackDemo" level="INFO" additivity="false">,将级别为“INFO”及大于“INFO”的日志信息交给此loger指定的名为“STDOUT”的appender处理,在控制台中打出日志,不再向次loger的上级 <logger name="logback"/> 传递打印信息;
<logger name="logback"/>未接到任何打印信息,当然也不会给它的上级root传递任何打印信息;
如果将<logger name="logback.LogbackDemo" level="INFO" additivity="false">修改为 <logger name="logback.LogbackDemo" level="INFO" additivity="true">那打印结果将是什么呢?
没错,日志打印了两次,想必大家都知道原因了,因为打印信息向上级传递,logger本身打印一次,root接到后又打印一次。
注意,虽然root中level为debug,但是logger相当于子类重写父类方法,以logger中的level为准,只打印info日志,不打印debug日志。