logback介绍和配置详解

logback是java的日志开源组件,是log4j创始人写的,性能比log4j要好,目前主要分为3个模块

  1. logback-core:核心代码模块
  2. logback-classic:log4j的一个改良版本,同时实现了slf4j的接口,这样你如果之后要切换其他日志组件也是一件很容易的事
  3. logback-access:访问模块与Servlet容器集成提供通过Http来访问日志的功能

一、logback的使用

依赖(这个依赖直接包含了 logback-core 以及 slf4j-api的依赖)


      ch.qos.logback
      logback-classic
      1.2.11

然后就可以直接在代码中使用slf4j的接口获取Logger输出日志了。(配置在下面的章节介绍)

//这是slf4j的接口,由于我们引入了logback-classic依赖,所以底层实现是logback
private static final Logger LOGGER = LoggerFactory.getLogger(Test.class);

public static void main(String[] args) throws InterruptedException {
    LOGGER.info("hello world");
}

二、logback的配置

logback配置获取顺序

logback在启动的时候,会按照下面的顺序加载配置文件

  1. 如果java程序启动时指定了logback.configurationFile属性,就用该属性指定的配置文件。如java -Dlogback.configurationFile=/path/to/mylogback.xml Test ,这样执行Test类的时候就会加载/path/to/mylogback.xml配置
  2. 在classpath中查找 logback.groovy 文件
  3. 在classpath中查找 logback-test.xml 文件
  4. 在classpath中查找 logback.xml 文件
  5. 如果是 jdk6+,那么会调用ServiceLoader 查找 com.qos.logback.classic.spi.Configurator接口的第一个实现类
  6. 自动使用ch.qos.logback.classic.BasicConfigurator,在控制台输出日志
    上面的顺序表示优先级,使用java -D配置的优先级最高,只要获取到配置后就不会再执行下面的流程。相关代码可以看ContextInitializer#autoConfig()方法。

关于SLF4j的日志输出级别

在slf4j中,从小到大的日志级别依旧是trace、debug、info、warn、error。

logback.xml 配置样例1




    logback
    
    
    
    
        
        
        
            DEBUG
        
        
        
        
            %d [%thread] %-5level %logger{36} [%file : %line] - %msg%n
        
    

    
        
        
        
        ${scheduler.manager.server.home}/logs/${app.name}.log
        
        
            
            ${scheduler.manager.server.home}/logs/${app.name}.%d{yyyy-MM-dd.HH}.log.gz
            
            
            60
            
            20GB
        
        
            
            100MB
        
        
        
            %d [%thread] %-5level %logger{36} [%file : %line] - %msg%n
        
    

    
    
        
        
        
    

    
    
    

    
    
    
    
    
        
    
    
    
    
    

logback.xml 配置样例2


 
    
    
    
    
    

    
    

    
    
    
    
    
        
            ${log_pattern}
            utf8
        
    


    
    
        
        
        
        
        
            
            
            
            
            
            ${defaultLogDir:-/qy/qy-doctorservice/logs}/log/%d{yyyy-MM-dd, aux}/credit.%d.%i.zip
            
            ${logMaxHistory:-15}
            
            ${logMaxSize:-100MB}
            
            
            1GB
            
            true
        
        
        false
        
            ${log_pattern}
            utf8
        
    
    
    
        
        
    

配置详解

configuration节点相关属性

属性名称 默认值 介绍
debug false 要不要打印 logback内部日志信息,true则表示要打印。
scan true 配置发送改变时,要不要重新加载
scanPeriod 1 seconds 检测配置发生变化的时间间隔。如果没给出时间单位,默认时间单位是毫秒

configuration子节点介绍

1. contextName节点

设置日志上下文名称,后面输出格式中可以通过定义 %contextName 来打印日志上下文名称

2.property节点

用来设置相关变量,通过key-value的方式配置,然后在后面的配置文件中通过 ${key}来访问

3.appender 节点

日志输出组件,主要负责日志的输出以及格式化日志。常用的属性有name和class

属性名称 默认值 介绍
name 无默认值 appender组件的名称,后面给logger指定appender使用
class 无默认值 appender的具体实现类。常用的有 ConsoleAppender、FileAppender、RollingFileAppender

3.1 ConsoleAppender:向控制台输出日志内容的组件,只要定义好encoder节点就可以使用。

3.2 FileAppender:向文件输出日志内容的组件,用法也很简单,不过由于没有日志滚动策略,一般很少使用

FileAppenderOutputStreamAppender 的子类,将日志事件输出到文件中。通过 file 来指定目标文件。如果该文件存在,根据 append 的值,要么将日志追加到文件中,要么该文件被截断。

3.3 RollingFileAppender:向文件输出日志内容的组件,同时可以配置日志文件滚动策略,在日志达到一定条件后生成一个新的日志文件。

appender节点中有一个子节点filter,配置具体的过滤器,比如上面的例子配置了一个内置的过滤器ThresholdFilter,然后设置了level的值为DEBUG。这样用这个appender输出日志的时候都会经过这个过滤器,日志级别低于DEBUG的都不会输出来。
RollingFileAppender 的属性如下所示:

属性名 类型 描述
file String 参见 FileAppender
append boolean 参见 FileAppender
encoder Encoder 参见 OutputStreamAppender
rollingPolicy RollingPolicy 当轮转发生时,指定 RollingFileAppender的行为。下面将会详细说明
triggeringPolicy TriggeringPolicy 告诉 RollingFileAppender 什么时候发生轮转行为。下面将会详细说明
prudent boolean FixedWindowRollingPolicy不支持该属性。
RollingFileAppender 在使用严格模式时要与 TimeBasedRollingPolicy结合使用,但是有两个限制:
1. 在严格模式下,也不支持也不允许文件压缩(我们不能让一个 JVM 在写入文件时,另一个 JVM 在压缩该文件)
2. 不能对 FileAppenderfile 属性进行设置。实际上,大多数的操作系统不允许在有进程操作文件的情况下对文件改名。
其它的参考 FileAppender

RollingFileAppender的两种策略:
RollingPolicy 负责轮转的方式为:移动文件以及对文件改名。

1.SizeAndTimeBasedRollingPolicy基于大小以及时间的轮转策略。

有时你希望按时轮转,但同时又想限制每个日志文件的大小。特别是如果后期处理工具需要对日志进行大小限制。为了满足这个需求,logback 配备了 SizeAndTimeBasedRollingPolicy

注意,TimeBasedRollingPolicy 可以限制归档文件总的大小。所以如果你想要这个限制,你可以通过设置 totalSizeCap 来达到这个目的。

2.TimeBasedRollingPolicy 是最常用的轮转策略,它是基于时间来定义轮转策略。
TimeBasedRollingPolicy 是最常用的轮转策略。它是基于时间来定义轮转策略。例如按天或者按月。TimeBasedRollingPolicy 既负责轮转的行为,也负责触发轮转。实际上,TimeBasedRollingPolicy 同时实现了 RollingPolicyTriggeringPolicy 接口。
TimeBasedRollingPolicy 的配置需要一个强制的属性 fileNamePattern 以及其它的可选属性。

例如按天或者按月。TimeBasedRollingPolicy 既负责轮转的行为,也负责触发轮转。实际上,TimeBasedRollingPolicy 同时实现了 RollingPolicyTriggeringPolicy 接口。

属性名 类型 描述
fileNamePattern String 该属性定义了轮转时的属性名。它的值应该由文件名加上一个 %d 的占位符。%d 应该包含 java.text.SimpleDateFormat 中规定的日期格式。如果省略掉这个日期格式,那么就默认为 yyyy-MM-dd。轮转周期是通过 fileNamePattern 推断出来的。

注意:可以选择对 RollingFileAppenderTimeBasedRollingPolicy的父类)中的 file 属性进行设置,也可以忽略。通过设置 FileAppenderfile 属性,你可以将当前活动日志的路径与归档日志的路径分隔开来。当前日志永远会是通过 file 指定的文件。它的名字不会随着时间的推移而发生变化。但是,如果你选择忽略 file 属性,当前活动日志在每个周期内将会根据 fileNamePattern 的值变化。稍后的例子将会说明这一点。
%d{} 中的日期格式将会遵循 java.text.SimpleDateFormat 中的约定。斜杆 '/' 或者反斜杠 '' 都会被解析成目录分隔符。

指定多个 %d

可以指定多个 %d,但是只能有一个是主要的,用于推断轮转周期。其它的 %d 占位符必须通过 'aux' 标记为辅助的。见下面的示例:
多个 %d 占位符允许你在文件夹中去管理归档文件,这个跟轮转周期不同。如下所示:通过年月来管理日志文件夹,但是轮转周期是在每天晚上零点。
/var/log/%d{yyyy/MM, aux}/myapplication.%d{yyyy-MM-dd}.log

TimeZone

在某些情况下,你可能想要根据时区而不是主机的时钟来轮转日志。你可以通过如下方式来指定一个时区,例如:
aFloder/test.%d{yyyy-MM-dd-HH, UTC}.log
如果指定的 timezone 不能被识别或者拼写错误,将会根据 TimeZone.getTimeZone(String) 方法指定为 GMT。
maxHistory int 这个可选的属性用来控制最多保留多少数量的归档文件,将会异步删除旧的文件。比如,你指定按月轮转,指定 maxHistory = 6,那么 6 个月内的归档文件将会保留在文件夹内,大于 6 个月的将会被删除。注意:当旧的归档文件被移除时,当初用来保存这些日志归档文件的文件夹也会在适当的时候被移除。
totalSizeCap int 这个可选属性用来控制所有归档文件总的大小。当达到这个大小后,旧的归档文件将会被异步的删除。使用这个属性时还需要设置 maxHistory 属性。而且,maxHistory 将会被作为第一条件,该属性作为第二条件。
cleanHistoryOnStart boolean 如果设置为 true,那么在 appender 启动的时候,归档文件将会被删除。默认的值为 false。
归档文件的删除通常在轮转期间执行。但是,有些应用的存活时间可能等不到轮转触发。对于这种短期应用,可以通过设置该属性为 true,在 appender 启动的时候执行删除操作。

3.4 SMTPAppender
SMTPAppender收集日志事件到一个或多个固定大小的缓冲区,当用户指定的事件发生时,将从缓冲区中取出适当的内容进行发送。SMTP 邮件是异步发送的。默认情况下,当日志的级别为 ERROR 时,邮件发送将会被触发。而且默认的情况下,所有事件都使用同一个缓冲区。
SMTPAppender 的属性如下表所示:

属性名 类型 描述
smtpHost String SMTP 服务器的主机名。强制性的。
smtpPort int SMPT 服务监听的端口。默认为 25.
to String 接收者的邮件地址。触发事件发送给接收者。多个收件人可以使用逗号(,)分隔,或者使用多个 元素来指定。
from String SMTPAppender 使用的发件人,格式遵循邮件通用格式,如果你想要包含发送者的名字,使用这种格式 " Adam Smith ",那么邮件将会显示收件人为 " Adam Smith "
subject String 邮件的主题。它可以是通过 PatternLayout 转换后的有效值。关于 Layout 将在接下来的章节讨论。
邮件应该有一个主题行,对应触发的邮件信息。
假设 subject 的值为:"Log: %Logger - %msg",触发事件的 logger 名为 "com.foo.Bar",并且日志信息为 "Hello world"。那么发出的邮件信息将会有一个名为 "Log: com.foo.Bar - Hello World" 的主题行。
默认情况下,这个属性的值为 "%logger{20} - %m"
discriminator Discriminator 在 Discriminator 的帮助下,SMTPAppender 根据 discriminator 返回的值可以将不同日志事件分散到不同的缓冲区中。默认的 discriminator 将返回同一个值,所以所有的事件都使用同一个缓冲区。
evaluator IEvaluator 通过创建一个新的 元素来声明此选项。通过 class 属性指定 class 的名字表示用户希望通过哪个类来满足 SMTPAppenderEvaluator 的需要。
如果没有指定此选项,当触发一个大于等于 ERROR 级别的事件时,SMTPAppender 将会被分配一个 OnErrorEvaluator 的实例。
logback 配备了几个其它的 evaluator,分别叫 OnMarkerEvaluator (将在下面讨论),一个相对强大的 evaluator 叫 JaninoEventEvaluator(在其它章节讨论) 以及最近版本才有的一个更加强大的 evaluator 叫 GEventEvaluator
cyclicBufferTracker CyclicBufferTracker 从名字可以看出,是一个 CyclicBufferTracker 的实例追踪循环缓冲区。它基于 discriminator 返回的 key (见上)。
如果你不想指定一个 cyclicBufferTracker,那么将会自动创建一个 CyclicBufferTracker 的实例。默认的,这个实例用来保留事件的循环缓冲区的大小为 256。你需要改变 bufferSize 选项的大小(见下面)
username String 默认为 null
password String 默认为 null
STARTTLS boolean 如果为 true,那么 appender 将会发送 STARTTLS 命令(如果服务器支持)将连接变成 SSL 连接。注意,连接初始的时候是为加密的。默认为 false。
SSL boolean 如果为 true,将通过 SSL 连接服务器。默认为 false。
charsetEncoding String 邮件信息将会通过 charset 进行编码。默认编码为 "UTF-8"
localhost String 一旦 SMTP 客户端的主机名没有配置正确,例如客户端的 hostname 不是全限定的,那么服务端会拒绝客户端发送的 HELO/EHLO 命令。为了解决这个问题,你可以将 localhost 的值设置为客户端主机的全限定名。详情见 com.sun.mail.smtp 包文档中的 "mail.smtp.localhost" 属性。(这个网站已经关闭了...)
asynchronousSending boolean 决定邮件传输是否是异步进行。默认为 'true'。但是,在某些特定的情况下,异步发送不怎么合适。例如,当发生一个严重错误时,你的应用使用 SMTPAppender 去发送一个警告,然后退出。但是相关线程可能没有时间去发送警告邮件。在这种情况下,你可以设置该属性的值为 'false'。
includeCallerData boolean 默认为 false。如果 asynchronousSending 的值为 true,并且你希望在日志中看到调用者的信息,你可以设置该属性的值为 true
sessionViaJNDI boolean SMTPAppender 基于 javax.mail.Session 来发送邮件信息。默认情况下,该属性的值为 false,所以需要用户指定相关属性通过 SMTPAppender 来构建 javax.mail.Session 实例。如果设置为 true,javax.mail.Session 实例将会通过 JNDI 来获取。参见 jndiLocation 属性。
通过 JNDI 获取 Session 实例可以减少需要配置的数量,使你的应用减少重复(dryer)的工作。更多关于在 Tomcat 配置 JNDI 的信息请参考 JNDI Resources How-to。
注意:通过 JNDI 获取 Session 的时候请移除 web 应用下 WEB-INF/lib 文件夹下的 mail.jaractivation.jar
jndiLocation String JNDI 中放置 javax.mail.Session 的地方。默认为:" java:comp/env/mail/Session "

SMTPAppender 仅仅只在它的循环缓存区中保留最后 256 个日志事件,当缓存区快要满的时候丢掉旧的日志事件。因此,通过 SMTPAppender 发送任何邮件包含的日志事件都不会超过 256 个。这在保留内存需求的限制,还提供了数量可观的应用上下文。

SMTPAppender 基于 JavaMail API。在 JavaMail 1.4 版本做过测试。JavaMail 需要 JavaBeans Activation Framework 包。你可以去它们各自的网站下载 JavaMail API 与 JavaBeans Activation Framework。在运行下面的示例之前先确保将这两个 jar 包放在 classpath 下。

chapters.appenders.mail.EMail应用会生成多个日志信息,随后再生成一个错误日志信息。它接收两个参数,第一参数是整形,表示需要生成多少个日志事件。第二个参数表示 logback 的配置文件。Email 最后生成一个错误日志,将会触发发送邮件信息。

下面是一个 Email 应用的简单配置信息:

4. logger以及root节点

root节点和logger节点其实都是表示Logger组件。个人觉的可以把他们之间的关系可以理解为父子关系,root是最顶层的logger,正常情况getLogger("name/class")没有找到对应logger的情况下,都是使用root节点配置的logger。

如果配置了logger,并且通过getLogger("name/class")获取到这个logger,输出日志的时候,就会使用这个logger配置的appender输出,同时还会使用rootLogger配置的appender。我们可以使用logger节点的additivity="false"属性来屏蔽rootLogger的appender。这样就可以不使用rootLogger的appender输出日志了。

关于logger的获取,一般logger是配置name的。我们再代码中经常通过指定的CLass来获取Logger,比如这样LoggerFactory.getLogger(Test.class);,其实这个最后也是转成对应的包名+类名的字符串com.kongtrio.Test.class。假设有一个logger配置的那么是com.kongtrio,那么通过LoggerFactory.getLogger(Test.class)获取到的logger就是这个logger。

也就是说,name可以配置包名,也可以配置自定义名称。

上面说的logger和root节点的父子关系只是为了方便理解,具体的底层实现本人并没有看,他们之间真正的关系读者有兴趣的话可以去看logback的源码

三、SpringBoot中logback日志配置文件加载顺序

springboot加载日志配置文件有两种,一种是加载logback自身的配置文件,另一种是加载具有spring特性的logback配置文件:

    // @see org.springframework.boot.logging.AbstractLoggingSystem
    private void initializeWithConventions(LoggingInitializationContext initializationContext, LogFile logFile) {
        String config = getSelfInitializationConfig();
        if (config != null && logFile == null) {
            // self initialization has occurred, reinitialize in case of property changes
            reinitialize(initializationContext);
            return;
        }
        if (config == null) {
            config = getSpringInitializationConfig();
        }
        if (config != null) {
            loadConfiguration(initializationContext, config, logFile);
            return;
        }
        loadDefaults(initializationContext, logFile);
    }

其中config 指logback自身的配置文件,logFile 指logging.file.name或者logging.file.path指定的文件

// @See org.springframework.boot.logging.LogFile
public static LogFile get(PropertyResolver propertyResolver) {
        // public static final String FILE_NAME_PROPERTY = "logging.file.name"
        String file = propertyResolver.getProperty(FILE_NAME_PROPERTY);
        // public static final String FILE_PATH_PROPERTY = "logging.file.path"
        String path = propertyResolver.getProperty(FILE_PATH_PROPERTY);
        if (StringUtils.hasLength(file) || StringUtils.hasLength(path)) {
            return new LogFile(file, path);
        }
        return null;
    }

1.加载logback自身的配置文件按(二、logback的配置--logback配置获取顺序)顺序加载;
2.如果上述配置文件都不存在,则加载springboot自身具有spring特性的logback配置文件,加载顺序和logback自身配置文件一致。只是在每种配置文件的末尾加上“-spring”。

Spring Boot官方推荐优先使用带有-spring的文件名作为你的日志配置(如使用logback-spring.xml,而不是logback.xml),因为logback.xml加载早于application.properties,所以如果你在logback.xml使用了变量时,而恰好这个变量是写在application.properties时,那么就会获取不到,只要改成logback-spring.xml就可以解决。

  • logging.file.name:设置具体输出的日志名称,可以是绝对路径或者基于当前运行目录的相对路径,例如:logging.file.name=app.log、logging.file.name=/var/log/app.log
  • logging.file.path:设置输出的日志被写入到的目录,默认文件名为 spring.log,例如:logging.file.path=/var/log/
    如果你两个都同时设置,则以 logging.file.name 为准,建议直接使用 logging.file.name。

具有spring特性的logback的配置文件--logback-spring.xml

  • springProfile
    标签允许我们更加灵活配置文件,可选地包含或排除配置部分。使用该name属性指定哪个配置文件接受配置。可以使用逗号分隔列表指定多个配置文件。

    



    



    

例子



    
        
        
    
 



    
        
        
    

  • springProperty
    标签允许我们从Spring中显示属性,Environment 以便在Logback中使用。如果你想将 application.properties在回读配置中访问文件中的值,这将非常有用。
属性名字 描述
scope 作用域(设置属性的范围,例local(默认)、context、system)
name 变量名字
source 需要引用的yml文件中配置名称
  1. local--从配置文件中定义其属性的位置到该配置文件的解释/执行结束为止,都存在具有本地范围的属性。因此,每次解析和执行配置文件时,都会重新定义本地作用域中的变量。

  2. context--具有上下文范围的属性被插入到上下文中,并且持续时间与上下文一样长,直到被清除为止。一旦定义,上下文范围内的属性就是上下文的一部分。这样,它在所有日志记录事件中都可用,包括那些通过序列化发送到远程主机的事件。

  3. system--具有系统范围的属性被插入 JVM 的系统属性中,并且持续时间与 JVM 一样长,或者直到被清除为止。
    例子



    
    
    
    
    
    
    
    
    
    
        
            ${FILE_LOG_PATTERN}
            ${FILE_LOG_CHARSET}
        
        ${LOG_ERROR_FILE}
        
        
            ERROR
            ACCEPT
            DENY
        
        
            ${LOG_ERROR_FILE}.%d{yyyy-MM-dd}.%i.gz
            false
            10MB
            0
            7
        
    

    
    
        
        
        
    

参考:26. Logging (spring.io)

你可能感兴趣的:(logback介绍和配置详解)