logback常用配置
<?xml version="1.0" encoding="UTF-8"?>
<!--debug:打印logback内部状态信息-->
<!--scan:是否开启自动扫描logback.xml,这样配置修改后,会在动读取加载生效,不用从重启系统-->
<!--sacnPeriod:扫描周期,如果没有指定时间单位默认为毫秒。30 seconds表示30秒-->
<!--packagingData:是否展示报数据。程序的异常信息会显示类来自哪个包以及对应的版本。默认为fasle-->
<!--如果扫描的logback配置文件有错误,将回退之前的配置文件-->
<configuration debug="true" scan="true" scanPeriod="1 seconds">
<!-- logback上下文名称,即给logback起个名称。在多个程序日志输入到同一个文件的时候,更好的区分它们 -->
<!-- 可以在encoder下的pattern使用声明 %contextName 来打印上下文名称 -->
<contextName>logback</contextName>
<!--===property用于声明变量或从properties文件中导入 -->
<!--name:变量名称,value变量值-->
<!--scope:变量的作用于。默认为local。本地(local scope),上下文(context scope),系统(system scope) -->
<!--file:从指定路径读取properties文件,需要指定绝对路径 -->
<!--resource:从classpath路径读取文件-->
<property name="app.name" value="logback_test"/>
<!--===include用于引入外部的配置片段 -->
<!--file从指定路径引入外部文件,需指定绝对路径-->
<!--resource从classpath路径下引入文件 -->
<!--url从网络引入文件 -->
<include resource="logback-config-1.xml"></include>
<!--===OutputStreamAppender其它Appender类的父类-->
<!--immediateFlush:是否立即刷新输出流。默认为true。立即刷新输出流可以确保Appender对象没有被正确关闭的情况下不丢失日志-->
<!--encoder:将日志事件转换为字节数组,同时将字节数组写入到一个OutputStream中。用它格式化日志-->
<!--layout:与encoder的作用一致,能在layout中配置的节点也能在encoder中配置。layout是将日志事件转换成数组-->
<!--encoder可看做是layout的一个优化版本-->
<appender name="OutputStreamAppender" class="ch.qos.logback.core.OutputStreamAppender">
<immediateFlush>true</immediateFlush>
<!--pattern:日志的格式化字符串-->
<!--outputPatternAsHeader:在日志的开头输出格式化字符串,便于其他程序解析日志-->
<!--charset:编码格式,默认为系统编码格式-->
<encoder>
<pattern></pattern>
<outputPatternAsHeader></outputPatternAsHeader>
<charset></charset>
</encoder>
</appender>
<!--===ConsoleAppender将日志输出到控制台,即通过System.out或者System.err来进行输出-->
<!--target:System.out或System.err。默认为System.out-->
<!--withJansi:是否使用ANSI 彩色代码,默认为fasle。window需要将org.fusesource.jansi:jansi:1.9包放到classpath,Unix不需要-->
<appender name="ConsoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<target>System.out</target>
<withJansi>false</withJansi>
</appender>
<!--===FileAppender将日志输出到文件中-->
<!--append:true:向文件中追加日志,false:截断日志文件(不理解什么是截断),默认为true-->
<!--file:要写入的文件名称,如果不存在将会新建。路径分隔符使用"/"或"\\"-->
<!--prudent:是否开启严格模式(即当对当前append写入的文件加锁,一般用于多个JVM向同一个文件写入日志,某一时刻只能由一个appender写入日志,默认为false。-->
<appender name="FileAppender" class="ch.qos.logback.core.FileAppender">
<append>true</append>
<prudent></prudent>
</appender>
<!--===RollingFileAppender继承自FileAppender,具有轮转日志文件的功能-->
<!--rollingPolicy:文件归档的策略,移动文件以及对文件改名-->
<!--triggeringPolicy:触发归档的策略-->
<appender name="RollingFileAppender" class="ch.qos.logback.core.RollingFileAppender">
<!--class:归档策略实现类,常用的如下:-->
<!--ch.qos.logback.core.rolling.TimeBasedRollingPolicy:基于时间来定义轮转策略-->
<!--ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy:基于文件大小和时间定义轮转策略-->
<rollingPolicy class=""></rollingPolicy>
<!--class:触发归档的策略-->
<!--ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy:基于文件大小定义触发归档的策略-->
<triggeringPolicy></triggeringPolicy>
</appender>
<!--logger作用可看做是对日志的分类。比如你的dao和service要分别输入到不同的文件中。 -->
<!--level:日志级别。INHERITED,NULL会继承父logger的level。日志级别从低到高:trace-debug-info-warn-error -->
<logger>
</logger>
<!--名称为com.zhangxy.service及其子类的logger将使用此logger节点的配置-->
<!--com.zhangxy.service子logger包括以com.zhangxy.service开头命名的logger。例如com.zhangxy.service.package1、com.zhangxy.service.ClassName等。 -->
<!--代码中通过Logger logger = LoggerFactory.getLogger("com.zhangxy.service")方式获取配置中的logger ->
<!--LoggerFactory.getLogger("com.zhangxy.service.package1"),虽然配置中没有显示配置此logger,但会获取第一个存在的父logger-->
<!-- 即logger是有继承性质的。子logger没有声明就会使用父logger,子logger的属性没有声明也会继承父logger -->
<logger name="com.zhangxy.service" level="DEBUG">
</logger>
<logger name="com.zhangxy.dao" level="INFO">
</logger>
<!--root是默认的logger,或者说是一个特殊的logger-->
<!--root只支持一个属性——level。如果不指定默认为DEBUG-->
<!--root不允许设置其它任何的属性-->
<!--root是所有logger的父类,就像java中所有的对象都默认继承Object一样-->
<root level="trace">
<!--定义了两个appender,日志会通过往这两个appender里面写-->
<appender-ref ref="stdout"/>
<appender-ref ref="file"/>
</root>
</configuration>
<!--
logback中文手册
http://www.logback.cn/
encoder节点下pattern中的转义字符说明:
http://www.logback.cn/06%E7%AC%AC%E5%85%AD%E7%AB%A0Layouts.html
appender->rollingPolicy->fileNamePattern配置项
http://www.logback.cn/04%E7%AC%AC%E5%9B%9B%E7%AB%A0Appenders.html
-->
常用Appender配置
按照时间对日志进行归档
按天对日志进行归档,保留最近30天内的日志,归档的日志不超过3GB。
<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 支持多个 JVM 同时写一个文件 -->
<prudent>true</prudent>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
按照大小以及时间对日志进行归档
最多保存近60天的日志,归档日志大小不超过20GB,当前的日志文件最大不超过100MB。
<configuration>
<appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>mylog.txt</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--后缀为.gz或zip,logback会对归档日志进行压缩-->
<fileNamePattern>mylog-%d{yyyy-MM-dd}.log.gz</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>60</maxHistory>
<totalSizeCap>20GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
以上配置等同于如下配置。其实上面的配置的SizeAndTimeBasedRollingPolicy类实现了文件归档接口和出发文件归档接口,所有可以配置maxFileSize节点。而下面配置的TimeBasedRollingPolicy只实现了文件归档接口,并没有时间触发文件归档接口,所以需要额外的配置triggeringPolicy 节点。
<configuration>
<appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>mylog.txt</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--后缀为.gz或zip,logback会对归档日志进行压缩-->
<fileNamePattern>mylog-%d{yyyy-MM-dd}.log.gz</fileNamePattern>
<maxHistory>60</maxHistory>
<totalSizeCap>20GB</totalSizeCap>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>100MB</maxFileSize>
</triggeringPolicy>
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
关于logback的自问自答
·### getLogger()获取的是什么
获取的是logback.xml中移logger节点定义的logger对象。
private static Logger logger = LoggerFactory.getLogger(CallEai.class);
假设CallEai的完全限定名称为com.zhangxy.service.CallEai。getLogger会获取CallEai的完全限定名称,根据完全限定名称找同名的logger,找不到的话,一次寻找com.zhangxy.service,com.zhangxy.service,…以此类推,直到找到为止。如果连名称为com的logger都找不到,会默认关联到root logger。也就是说getLogger()总会回去一个logger。
logback基本选择规则
各级别的排序为:TRACE < DEBUG < INFO < WARN < ERROR。基本选择规则指的是程序中打印日志的级别大于等于与之关联的logger定义的级别,此日志才会输出。
在下面的表格中,第一列表示的是日志的打印级别(程序中日志打印级别),用 p 表示。第一行表示的是 logger 的有效级别(logger标签定义的level),用 q 表示。行列交叉处的结果表示由基本选择规则得出的结果。
此表格要竖着看,才是正确的理解方式。
配置中的root节点是什么
root节点是特殊的logger,是所有logger的父logger。
root logger 通过 <root>
元素来进行配置。它只支持一个属性——level。它不允许设置其它任何的属性,因为 additivity 并不适用 root logger。而且,root logger 的名字已经被命名为 “ROOT”,也就是说也不支持 name 属性。level 属性的值可以为:TRACE、DEBUG、INFO、WARN、ERROR、ALL、OFF,但是不能设置为 INHERITED 或 NULL。跟 <logger 元素类似,<root>
元素可以包含 0 或多个<appender-ref>
元素。
root logger不能指定name,默认名称为ROOT,不指定level默认为DEBUG,这保证了总是能够找到一个logger,可能是你定义的logger,可以能是root logger。
logger的level继承规则
logback配置文件中通过logger节点配置logger对象,每个logger对象可以看多是对日志的分类,将有共同需要的日志关联到一个logger对象上。
logger对象是有继承特性的,所有的logger都默认继承root logger。
<logger name="com.zhangxy.dao"></logger>
<logger name="com.zhangxy" level="INFO"></logger>
<root level="DEBUG"></root>
以上的配置片段,com.zhangxy.dao没有声明level,com.zhangxy.dao的父logger是com.zhangxy,会继承父logger的level。
Append的叠加性
logger节点下的<appender-ref ref=""/>
节点是可以叠加的。
<logger name="com.zhangxy.dao"></logger>
<logger name="com.zhangxy" level="INFO">
<appender-ref ref="FILE"/>
</logger>
<root level="DEBUG">
<appender-ref ref="CONSOLE"/>
</root>
com.zhangxy包内的日志会输出到文件中,也会输出到控制台中。com.zhangxy.dao的父logger是com.zhangxy,因此也会输出到文件和控制台中。
如果com.zhangxy只想输出都文件中,可以设置 additivity = false
来禁用这种叠加性。