Logback配置使用

Log Java日志:(slf4j、log4j、logback、common-logging )

  • slf4j 是规范/接口
  • 日志实现:log4j、logback、common-logging

简单地说,Logback 是一个 Java 领域的日志框架。它被认为是 Log4J 的继承人。

Logback 主要由三个模块组成:

  • logback-core
  • logback-classic
  • logback-access

logback-core 是其它模块的基础设施,其它模块基于它构建,显然,logback-core 提供了一些关键的通用机制。
logback-classic 的地位和作用等同于 Log4J,它也被认为是 Log4J 的一个改进版,并且它实现了简单日志门面 SLF4J。
logback-access 主要作为一个与 Servlet 容器交互的模块,比如说 tomcat 或者 jetty,提供一些与 HTTP 访问相关的功能。


根据不同的日志系统,你可以按如下规则组织配置文件名,就能被正确加载:

  • Logback:logback-spring.xml, logback-spring.groovy, logback.xml, logback.groovy
  • Log4j:log4j-spring.properties, log4j-spring.xml, log4j.properties, log4j.xml
  • Log4j2:log4j2-spring.xml, log4j2.xml
  • JDK (Java Util Logging):logging.properties

Logback 与 Log4J

实际上,这两个日志框架都出自同一个开发者之手,Logback 相对于 Log4J 有更多的优点:

  • 同样的代码路径,Logback 执行更快
  • 更充分的测试
  • 原生实现了 SLF4J API(Log4J 还需要有一个中间转换层)
  • 内容更丰富的文档
  • 支持 XML 或者 Groovy 方式配置
  • 配置文件自动热加载
  • 从 IO 错误中优雅恢复
  • 自动删除日志归档
  • 自动压缩日志成为归档文件
  • 支持 Prudent 模式,使多个 JVM 进程能记录同一个日志文件
  • 支持配置文件中加入条件判断来适应不同的环境
  • 更强大的过滤器
  • 支持 SiftingAppender(可筛选 Appender)
  • 异常栈信息带有包信息
添加依赖


    org.slf4j
    slf4j-api
    1.7.12


    ch.qos.logback
    logback-core
    1.1.1



    ch.qos.logback
    logback-classic
    1.1.1

添加配置

Automatic configuration with logback-test.xml or logback.xml




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

    
        
    

这是和默认配置等效的一条配置。

使用logback
package chapters.configuration;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MyApp1 {
  final static Logger logger = LoggerFactory.getLogger(MyApp1.class);

  public static void main(String[] args) {
    logger.info("Entering application.");
  }
}
16:06:09.031 [main] INFO  chapters.configuration.MyApp1 - Entering application.

注意到这里,代码里并没有引用任何一个跟 Logback 相关的类,而是引用了 SLF4J 相关的类,这就是使用 SLF4J 的好处,在需要将日志框架切换为其它日志框架时,无需改动已有的代码。

LoggerFactorygetLogger()方法接收一个参数,以这个参数决定logger的名字,这里传入了 MyApp1这个类的 Class 实例,那么 logger 的名字便是 MyApp1 这个类的全限定类名:chapters.configuration.MyApp1

下面三种方法是等效的:

1. Logger logger = LoggerFactory.getLogger(MyApp1.class)
2. Logger logger = LoggerFactory.getLogger(MyApp1.class.getName())
3. Logger logger = LoggerFactory.getLogger("chapters.configuration.MyApp1")

让 Logback 打印出一些它自身的内部消息

LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
StatusPrinter.print(lc);

日志打印级别

TRACE < DEBUG < INFO < WARN < ERROR
如果一个 logger 允许打印一条具有某个日志级别的信息,那么它也必须允许打印具有比这个日志级别更高级别的信息,而不允许打印具有比这个日志级别更低级别的信息。

Logger,Appenders 与 Layouts

在后端logger系统中,有三个最基础的概念需要先熟悉:

  • Logger 日志记录器 - 日志记录器就是一个普通的Java类而已。
  • Appender 输出源 - 输出源是日志最终输出的地方,比如控制台或者文件
  • Layout(Encoder) 布局 - 布局决定了日志的打印格式,比如使用 %r [%t] %-5p %c %x - %m%n可以打印出 467 [main] INFO org.apache.log4j.examples.Sort - Exiting main method.这样的日志。

Logger 类位于 logback-classic 模块中, 而 Appender 和 Layout 位于 logback-core 中,

这意味着, Appender 和 Layout 并不关心 Logger 的存在,不依赖于 Logger,同时也能看出, Logger 会依赖于 Appender 和 Layout 的协助,日志信息才能被正常打印出来。

日志记录器 - logger

在logback中日志记录器是继承的,继承的规则是 com.hello.foo 会继承 com.hello 的日志配置,父子关系通过.来分割,所以 comcom.hello的父节点。在logback中默认会有一个root-logger(根 - 日志记录器)的存在,所有的其他日志记录器都会默认继承它的配置。
在配置文件中看到的:


  

就是“根”。所以当我们调用Logger logger = LoggerFactory.getLogger(App.class);的时候,默认是从root-logger那里继承了日志输出配置,而root-logger默认的log打印级别是debug,所以用logger.info打印不出日志。

那么如何配置一个普通的日志记录器呢?这是非常简单的:


这样便配置了一个名为com.hello 的日志记录器(一般会用包名作为日志记录器的名字),name是必须配置的属性。
然后可以通过 Logger logger = LoggerFactory.getLogger("com.hello")来得到这个日志记录器。

为了可以控制哪些信息需要输出,哪些信息不需要输出,logback 中引进了一个 **分层 **概念。每个 logger 都有一个 name,这个 name 的格式与 Java 语言中的包名格式相同。

日志输出源 - Appenders

输出源配置把日志打印到控制台,输出源的 nameclass 属性是必须配置的选项。

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

配置把日志打印到文件:


    myApp.log
    
      %date %level [%thread] %logger{10} [%file:%line] %msg%n
    

有了输出源之后,就可以给logger配置输出源,一个logger可以配置多个输出源:


    
    

这里给 root-logger配置了两个输出源,此时如果我们调用logger.debug方法会发现控制台和根目录下的myApp.log文件都打印了相同的日志。


在logback中,level的配置会被继承,但是appender的配置会被子logger保留。这么说有点抽象,看下面的例子:



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

  
    
  

  
    
  

这个配置会导致控制台打印两次:

11:38:06.068 [main] INFO  com.hello.App - Hello world.Info
11:38:06.068 [main] INFO  com.hello.App - Hello world.Info

当调用LoggerFactory.getLogger("com.hello.App") 的时候,它继承了来自 root-logger 的输出源,而他们的输出源都是控制台,所以导致在控制台输出了两次。

解决办法是,要么在有继承关系的logger中配置不同的输出源(从业务上避免),要么在子logger中覆盖父节点中的配置。可以通过additivity="false" 配置实现:


    

additivity属性告诉logback不要继承来自父类的设置。

布局 - Layout 和 编码 - Encoder

Layout主要用来把log事件转换成String。一般布局都是配置在 Appender 里面的:


    
        
    

注意,上面的示例使用的Appender是org.apache.log4j.ConsoleAppender,这是log4j的配置而不是这里讲的logback,这是因为在过去日志系统确实都是使用Layout来做日志转换的,但是由于一些 固有的问题 ,logback在Layout上面又封装了一层 - Encoder,表现在配置上就是这样的(这才是logback的配置):


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

但是Encoder的出现并不影响我们的配置,只是在形式上多了一个标签。一般使用最多的是 PatternLayoutPatternLayouEncoder,他们的特点是提供了很多约定的标记,这些标记都以%开头,比如logger名称、日志等级日期、线程名等。

  • %d{HH: mm:ss.SSS}——日志输出时间
  • %thread——输出日志的进程名字,这在Web应用以及异步任务处理中很有用
  • %-5level——日志级别,并且使用5个字符靠左对齐
  • %logger{36}——日志输出者的名字
  • %msg——日志消息
  • %n——平台的换行符

事实上我们在使用logback的时候很少见到直接使用layout,这是因为layout只能把一条log事件转化成String,layout不能控制log什么时候被写入文件,也不能做到批量处理。Encoder是被发明出来解决这些问题的。
目前为止Encoders只有一个实现 - PatternLayoutEncoder,它内部包含了一个PatternLayout,所以可以像使用PatternLayout一样使用Encoder。

常见配置

根节点包含的属性
  • scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
  • scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。
  • debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。

下面一共有2个属性,3个子节点,分别是:

属性一:设置上下文名称

每个logger都关联到logger上下文,默认上下文名称为“default”。但可以使用设置成其他名字,用于区分不同应用程序的记录。一旦设置,不能修改,可以通过%contextName来打印日志上下文名称。

logback
属性二:设置变量

用来定义变量值的标签,有两个属性,namevalue;其中name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使${}来使用变量。


变量有三个作用域:

  • local
  • context
  • system

local 作用域在配置文件内有效,context 作用域的有效范围延伸至 logger context,system 作用域的范围最广,整个 JVM 内都有效。

logback 在替换变量时,首先搜索 local 变量,然后搜索 context,然后搜索 system。


也可以通过外部文件来定义:


子节点一:

appender用来格式化日志输出节点,有俩个属性nameclass,class用来指定哪种输出策略,常用就是控制台输出策略和文件输出策略。

1、控制台输出ConsoleAppender:


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

ThresholdFilter为系统定义的拦截器,例如我们用ThresholdFilter来过滤掉ERROR级别以下的日志不输出到文件中。如果不用记得注释掉,不然你控制台会发现没日志~

2、输出到文件RollingFileAppender

另一种常见的日志输出到文件,随着应用的运行时间越来越长,日志也会增长的越来越多,将他们输出到同一个文件并非一个好办法。

RollingFileAppender用于切分文件日志:



    ${log.path}
    
        logback.%d{yyyy-MM-dd}.log
        30
        1GB
    
    
        %d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n
    

  • logback.%d{yyyy-MM-dd}.log定义了日志的切分方式——把每一天的日志归档到一个文件中。
  • 30表示只保留最近30天的日志,以防止日志填满整个磁盘空间。同理,可以使用%d{yyyy-MM-dd_HH-mm}来定义精确到分的日志切分方式。
  • 1GB用来指定日志文件的上限大小,例如设置为1GB的话,那么到了这个值,就会删除旧的日志。
子节点二:

root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性。


  
  

子节点三:

用来设置某一个包或者具体的某一个类的日志打印级别、以及指定

仅有一个name属性,一个可选的level和一个可选的addtivity属性。

if表达式(条件化处理配置文件)

logback 允许在配置文件中定义条件语句,以决定配置的不同行为,

   
   
    
      ...
    
  

  
  
    
      ...
    
    
      ...
        
  
常用条件表达式函数
1. property('key')
2. isDefined('key')
3. isNull("key")
文件包含

可以使用 ≶include> 标签在一个配置文件中包含另外一个配置文件。


  

  
    
  


被包含的文件必须有以下格式:


  
    
      "%d - %m%n"
    
  

支持从多种源头包含

  1. 从文件中包含

  1. 从 classpath 中包含

  1. 从 URL 中包含

如果包含不成功,那么 logback 会打印出一条警告信息,如果不希望 logback 抱错,只需这样做:


添加一个 Context Listener

LoggerContextListener接口的实例能监听 logger context 上发生的事件,比如说日志级别的变化,添加的方式如下所示:


  
  .... 

多环境日志输出

据不同环境(prod:生产环境,test:测试环境,dev:开发环境)来定义不同的日志输出。

文件名称不是logback.xml,想使用spring扩展profile支持,要以logback-spring.xml命名



    



    

你可能感兴趣的:(Logback配置使用)