一文理解logback

Posted 小白懂编程

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一文理解logback相关的知识,希望对你有一定的参考价值。

Logback是由log4j创始人设计的又一个开源日志组件,可以认为是log4j的改进版本。非常简单灵活,是目前主流的日志记录工具。推荐你也开始使用logback。

很多人都会使用log4j或logback。但我也相信,大多数人其实并不是很好的理解了它们,大部分场景下都是复制个配置文件改下就应付了。其实稍微花点时间研究下,就能更加合理的配置和使用logback。

开始使用

maven或gradel引入logback的两个jar包即可开始使用了。

gradle:

 
   
   
 
  1. dependencies {

  2.    testCompile group: 'junit', name: 'junit', version: '4.11'

  3.    compile group: 'ch.qos.logback', name: 'logback-core', version: '1.1.8'

  4.    compile group: 'ch.qos.logback', name: 'logback-classic', version: '1.1.8'

  5. }

新建个类即可开始使用

 
   
   
 
  1. package bumishi.logback;

  2. import org.slf4j.Logger;

  3. import org.slf4j.LoggerFactory;

  4. /**

  5. * Created by @bumishi(http://bumishi.cn) on 2017/1/19.

  6. */

  7. public class LogbackStudy {

  8.    public static void main(String[] arg){

  9.        //创建一个名字为test的logger

  10.        Logger logger= LoggerFactory.getLogger("test");

  11.        logger.debug("debug");

  12.        logger.info("info");

  13.        logger.warn("warn");

  14.        logger.error("error");

  15.    }

  16. }

logback需要一个配置文件来描述以怎样的格式输出日志,以及日志要输出到哪里去,以及日志的级别等。

加载配置文件

程序启动时,logback先从classpath中查找一个名为logback.groovy的配置文件

如果没有找到,再查找名为logback-test.xml的文件

如果没有找到,再查找名为logback.xml的文件

如果没有找到,会尝试从classpath的 META-INF\services\ch.qos.logback.classic.spi.Configurator文件中解析一个实现了 com.qos.logback.classic.spi.Configurator接口的完整类作为一个配置对象来配置

如果还是没有找到可以配置的方式,那么logback默认地会调用BasicConfigurator,创建一个最小化配置。最小化配置由一个关联到根logger的ConsoleAppender 组成。输出用模式为

 
   
   
 
  1. %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n

的PatternLayoutEncoder 进行格式化。根logger 默认级别是 DEBUG。

此外,我们也可以在启动程序时通过命令行参数指定。
通过指定一个名为 “logback.configurationFile”的Java system属性,这个属性的值可以是一个url,一个classpath中的文件,或者一个外部的文件。

 
   
   
 
  1. java -Dlogback.configurationFile=/path/to/config.xml chapters.configuration.MyApp1

需要注意的是,这个文件的扩展名必须是.xml或.groovy,其它扩展名将会被忽略。

通常,我们在测试环境下使用logback-test.xml,生产环境使用logback.xml

这里,我们创建一个logback-test.xml

 
   
   
 
  1. <configuration>

  2.    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">

  3.        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">

  4.            <pattern>%d{MM/dd/yyyy HH:mm:ss} %-5level [%thread%X{sourceThread}]%logger{24} - %msg%n</pattern>

  5.        </encoder>

  6.    </appender>

  7.    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">

  8.        <file>/var/log/admin-manage/log.log</file>

  9.        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

  10.            <fileNamePattern>/var/log/admin-manage/log.%d{yyyy-MM-dd}.log.gz</fileNamePattern>

  11.            <maxHistory>7</maxHistory>

  12.        </rollingPolicy>

  13.        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">

  14.            <pattern>%d{MM/dd/yyyy HH:mm:ss} %-5level ${version} [%thread]%logger{16} - %msg%n

  15.            </pattern>

  16.        </encoder>

  17.    </appender>

  18.       <root level="DEBUG">

  19.        <appender-ref ref="STDOUT"/>

  20.    </root>

  21. </configuration>

我们来逐一解释配置中的项目。

configuration是根节点。appender是用来表示日志要输出到哪里的组件。encoder用来将日志信息解析成具有一定格式的信息。

我们创建了一个名为STDOUT,类型为ch.qos.logback.core.ConsoleAppender的appender,这个appender用于把日志信息输出到控制台,就像System.out.println()一样。其中的pattern表示一个格式,%d表示日期,%d{MM/dd/yyyy HH:mm:ss} 表示以MM/dd/yyyy HH:mm:ss 这个格式显示当前时间,%thread表示线程名,%-5:级别从左显示5个字符宽度,level是日志级别,%msg:日志消息,%n是换行符。我们根据输出来的日志信息就能明白其中的含义。

我们同时创建了一个名为FILE,类型为ch.qos.logback.core.rolling.RollingFileAppender的appender,这是一个可以将日志输出到一个文件的appender,并且可以按照日期自动滚动,不至于让所有日志都写在一个文件上。rollingPolicy是一种文件滚动策略,可以让日志文件按日或按月归档。
上面的配置表示按照每天生成日志文件,最多保留7天,日志文件存放在/var/log/admin-manage/log.log。每过一天,日志名就变成类似log.2017-01-19.log.gz的形式。

只配置appender并不能直接输出日志,logback中,appender是要给logger用的,我们需要配置logger。

每个logger都是ch.qos.logback.classic.Logger的一个实例,每个logger有一个名称,有一个级别,以及0个或多个appender,这意味着同一条日志信息可以同时输出到多个地方去。

整个logback中,最为重要的部分就是理解logger的继承层次了,绝大多数人并不理解。理解了这个后你就能随心所欲的使用logback来按你你想要的方式来输出日志了。

logback及log4j中logger的继承层次都类似。

logger是一个具备父子关系的树结构。最顶端的logger是一个固定名称为ROOT的logger,所有的logger都是它的孩子,就像Java的Object一样。然而logger的继承层次却是完全根据logger的name来决定的。logback根据logger的name按照”.”来进行分割,就像Java的包名一样。名为com.bumishi的logger是名为com的logger的子logger,名为com的logger是ROOT的子logger,任何一个logger如果向上找不到父logger那它的父logger就是ROOT。

在logback的配置文件中,ROOT logger用<root>表示,其它logger用<logger>表示。每个logger都有几个属性:

name:名称,根据此名称建立继承层次结构

level:级别,如debug,info,warn,error等,级别依次越来越高,给logger指定高级别时,低于这个级别的日志信息将不会被发送到appender。

additivity:表示此logger输出的日志是否要向上传递到父logger的appender,默认是true。传递到父logger的意思是,日志信息除了在当前logger的appender中输出,还会在父logger中的appender输出。

appender列表
一个logger可以有0个或多个appdner,通过appender-ref节点引用前面定义的appender。

上面的配置中,我们只配置了一个根logger——root,指定了它的级别为debug,指定了appender输出到控制台。

由于配置的是root,所有这个配置会对所有的logger有效,我们在应用中任何名称的logger输出的所有级别大于或等于debug的信息都将输出到控制台中。

我们运行上述程序即可看到效果:

 
   
   
 
  1. 01/19/2017 21:58:12 DEBUG [main]test - debug

  2. 01/19/2017 21:58:12 INFO  [main]test - info

  3. 01/19/2017 21:58:12 WARN  [main]test - warn

  4. 01/19/2017 21:58:12 ERROR [main]test - error

我们尝试定义多个不同的logger

 
   
   
 
  1. <configuration>

  2.    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">

  3.        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">

  4.            <pattern>%d{MM/dd/yyyy HH:mm:ss} %-5level [%thread%X{sourceThread}]%logger{24} - %msg%n</pattern>

  5.        </encoder>

  6.    </appender>

  7.    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">

  8.        <file>/var/log/admin-manage/log.log</file>

  9.        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

  10.            <fileNamePattern>/var/log/admin-manage/log.%d{yyyy-MM-dd}.log.gz</fileNamePattern>

  11.            <maxHistory>7</maxHistory>

  12.        </rollingPolicy>

  13.        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">

  14.            <pattern>%d{MM/dd/yyyy HH:mm:ss} %-5level ${version} [%thread]%logger{16} - %msg%n

  15.            </pattern>

  16.        </encoder>

  17.    </appender>

  18.    <logger name="test1" level="info"/>

  19.    <logger name="test2" level="info" additivity="false"/>

  20.    <logger name="test3" level="warn" additivity="false">

  21.        <appender-ref ref="STDOUT"/>

  22.    </logger>

  23.    <logger name="test4" level="warn" >

  24.        <appender-ref ref="STDOUT"/>

  25.    </logger>

  26.    <root level="DEBUG">

  27.        <appender-ref ref="STDOUT"/>

  28.    </root>

  29. </configuration>

在Java中分别运行下不同logger的输出结果

 
   
   
 
  1. package bumishi.logback;

  2. import org.slf4j.Logger;

  3. import org.slf4j.LoggerFactory;

  4. /**

  5. * Created by @bumishi(http://bumishi.cn) on 2017/1/19.

  6. */

  7. public class LogbackStudy {

  8.    public static void main(String[] arg) {

  9.        print("test1");

  10.        print("test2");

  11.        print("test3");

  12.        print("test4");

  13.    }

  14.    public static void print(String name) {

  15.        Logger logger = LoggerFactory.getLogger(name);

  16.        logger.debug("debug");

  17.        logger.info("info");

  18.        logger.warn("warn");

  19.        logger.error("error");

  20.    }

  21. }

结果:

 
   
   
 
  1. 1/19/2017 22:58:24 INFO  [main]test1 - info

  2. 01/19/2017 22:58:24 WARN  [main]test1 - warn

  3. 01/19/2017 22:58:24 ERROR [main]test1 - error

  4. 01/19/2017 22:58:24 WARN  [main]test3 - warn

  5. 01/19/2017 22:58:24 ERROR [main]test3 - error

  6. 01/19/2017 22:58:24 WARN  [main]test4 - warn

  7. 01/19/2017 22:58:24 WARN  [main]test4 - warn

  8. 01/19/2017 22:58:24 ERROR [main]test4 - error

  9. 01/19/2017 22:58:24 ERROR [main]test4 - error

你是否能理解这个结果呢?

我一个一个解释下:


如果我们在加两个这样的logger

 
   
   
 
  1. <logger name="com.test4" level="warn" >

  2.        <appender-ref ref="STDOUT"/>

  3.    </logger>

  4.    <logger name="com" level="warn" >

  5.        <appender-ref ref="STDOUT"/>

  6.    </logger>

用com.test4打印,那么就会出现3次了。

 
   
   
 
  1. print("com.test4");

 
   
   
 
  1. 01/19/2017 23:10:36 WARN  [main]com.test4 - warn

  2. 01/19/2017 23:10:36 WARN  [main]com.test4 - warn

  3. 01/19/2017 23:10:36 WARN  [main]com.test4 - warn

  4. 01/19/2017 23:10:36 ERROR [main]com.test4 - error

  5. 01/19/2017 23:10:36 ERROR [main]com.test4 - error

  6. 01/19/2017 23:10:36 ERROR [main]com.test4 - error

专注技术研究


以上是关于一文理解logback的主要内容,如果未能解决你的问题,请参考以下文章

一文详细了解logback之日志打印FileAppender

一文带你了解 logback 的一些常用配置

从log4j日志无缝迁移至logback

一文讲尽门面日志slf4j和log4jlog4j2logback依赖jar引用关系

logback新认识:主要组件appenderrollingPolicy和triggeringPolicy的使用和理解

金蝶handler中 collection 代码片段理解