logback 的属性

logback

logback 是log4j比较流行的实现方式。

一、使用
1、依赖
	<!--logback 是slf4j 的实现方式 ,logback-classic需要依赖slf4j-->
	<dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.28</version>
    </dependency>
    
	<!----logback相关依赖 -->
    <!--核心功能,定义了appender 和encoder -->
     <dependency>
       <groupId>ch.qos.logback</groupId>
       <artifactId>logback-core</artifactId>
       <version>1.2.3</version>
     </dependency>
    <dependency>
       <groupId>ch.qos.logback</groupId>
       <artifactId>logback-access</artifactId>
       <version>1.2.3</version>
     </dependency>
     <dependency>
       <groupId>ch.qos.logback</groupId>
       <artifactId>logback-classic</artifactId>
       <version>1.2.3</version>
     </dependency>
  
	 <!--支持logback 配置文件中  使用 if else 条件判断等一个控制语句 -->	
	  <dependency>
	            <groupId>org.codehaus.janino</groupId>
	            <artifactId>janino</artifactId>
	            <version>3.0.6</version>
	  </dependency>

logback-core: 核心功能。
logback-classic:实现了slf4j的API
logback-access: 于Servlet容器集成,提供了访问Http-access日志的功能。

2、简单使用

由于日志服务一般都在ApplicationContext创建前就初始化了,它并不是必须通过Spring的配置文件控制。因此通过系统属性和传统的Spring Boot外部配置文件依然可以很好的支持日志控制和管理。

在没有进行任何配置时,logback会按照级别(debug),默认的格式输出(%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n)。

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

public class LogbackTest {
    private static Logger logger = LoggerFactory.getLogger(LogbackTest.class);

    public static void main(String[] args) {
        logger.trace("trace");
        logger.debug("debug");
        logger.info("info");
        logger.warn("warn");
        logger.error("error");
    }
}

15:45:39.524 [main] DEBUG test.LogbackTest - debug
15:45:39.531 [main] INFO test.LogbackTest - info
15:45:39.531 [main] WARN test.LogbackTest - warn
15:45:39.532 [main] ERROR test.LogbackTest - error

日志信息默认输出到控制台,输出级别为DEBUG,所以trace级别的日志信息是不能输出的。

默认的配置满足最基本的开发、测试要求。

如果需要更高的要求,不同的java包设置不同的日志输出级别,控制输出日志信息格式,生产环境将日志信息保存到本地磁盘。这就需要进行自定义配置

3、日志级别

日志级别:
TRACE < DEBUG < INFO < WARN < ERROR.

logback中有一个基本显示规则:

A log request of level p issued to a logger having an effective level q, is enabled if p >= q.

如果日志的有效输出级别为 INFO ,那么INFO,WARN 和ERROR 级别的日志都可以打印。

4、配置文件

下面这个是比较全的配置,之后会详细介绍几个重要的元素。

<?xml version="1.0" encoding="UTF-8"?>
<!--    
	scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。

    scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,
    			此属性生效。默认的时间间隔为1分钟。

    debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
 -->
<configuration  scan="true" scanPeriod="60 seconds" debug="false">

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

    <!--    设置变量<property> 用来定义变量值的标签,有两个属性,name和value;其中name的值是变量的名称,value的值时变量定义的值。
        通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。-->
    <property name="log.path" value="log" />

    <!--  appender用来格式化日志输出节点,有俩个属性name和class,class用来指定哪种输出策略,常用就是控制台输出策略和文件输出策略。-->
    <!--    <encoder>表示对日志进行编码:

        %d{HH: mm:ss.SSS}——日志输出时间。

        %thread——输出日志的进程名字,这在Web应用以及异步任务处理中很有用。

        %-5level——日志级别,并且使用5个字符靠左对齐。

        %logger{36}——日志输出者的名字。

        %msg——日志消息。

        %n——平台的换行符。    -->
        
    <!--输出到控制台-->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
     	<!-- ThresholdFilter为系统定义的拦截器,例如我们用ThresholdFilter来过滤掉ERROR级别以下的日志不输出到文件中-->
        <!-- <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
             <level>ERROR</level>
         </filter>-->
        <encoder>
        	 <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度,%msg:日志消息,%n是换行符 -->
            <pattern> 
            	%d{yyyy-MM-dd HH:mm:ss} %contextName [%thread] %-5level %logger{36} %msg%n
            </pattern>
        </encoder>
    </appender>


	<!-- 按照每天生成日志文件 -->
    <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
       <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
           <level>INFO</level>
       </filter>
       <!-- 最新日志写入位置 -->
       <file>${log.path}/info.log</file>
       <!--配置日志文件切分, 基于时间-->
       <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
           <!--日志文件输出的文件名 -->
           <!--定义了日志的切分方式, 把每一天的日志归档到一个文件中-->
           <fileNamePattern>${log.path}/info.log.%d{yyyy-MM-dd}.log</fileNamePattern>
           <!--日志文件最多存在的数量。当超过此数量时就会删除旧的文档   -->
           <!--对于基于时间的rolling policy。日志的数量也就对应着日期 -->
           <maxHistory>30</maxHistory>
           <!-- 控制档文件的总大小,当超过总大小上限时,将异步删除最旧的存档 -->
           <!-- 
			totalSizeCap 属性需要maxHistory 
			maxHistory 的优先级高于 totalSizeCap
           -->
           <totalSizeCap>1GB</totalSizeCap>
       </rollingPolicy>
       <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
           <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
           <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
       </encoder>
    </appender>


    <!-- root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性,
        用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF -->
     <root level="info">
        <!-- 配置日志输出 -->
        <appender-ref ref="console" />
        <appender-ref ref="file" />
     </root>

	<!--    <logger>用来设置某一个包或者具体的某一个类的日志打印级别、以及指定<appender>。<logger>仅有一个name属性,一个可选的level和一个可选的addtivity属性。-->
	<!-- 
 	 name:用来指定受此logger约束的某一个包或者具体的某一个类。
 	 
     level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,还有一个特俗值INHERITED或者同义词NULL,
     代表强制执行上级的级别。如果未设置此属性,那么当前logger将会继承上级的级别。

     addtivity:是否继承父类的appender 。默认是true。-->
       
	 <!-- com.example 包下产生的WARN级别的日志,输出到控制台 -->
    <logger name="com.example" level="WARN" additivity="false">
        <appender-ref ref="console"/>
    </logger>

	<!--打印com.apache.ibatis 包下产生的DEBUG及以上级别的日志, 
	 没有配置 appender, 继承ROOT中定义的
	 输出到console、file  -->
   <logger name="com.apache.ibatis" level="DEBUG" />
</configuration>
结构

自定义变量。

 <property name="log.path" value="log" />

配置不同系统环境下,日志的目录

    <property name="OS_NAME" value="${os.name}"/>
    <if condition='property("OS_NAME").contains("Windows")'>
    <then>
        <property name="LOG_PATH" value="${LOG_PATH:-E:/logs}" />
    </then>
    <else>
        <property name="LOG_PATH" value="${LOG_PATH:-/log}" />
    </else>
    </if>
  <dependency>
       <groupId>org.codehaus.janino</groupId>
       <artifactId>janino</artifactId>
       <version>3.0.6</version>
   </dependency>
初始化

logback初始化过程:

  1. 在classpath路径下试图查找名称logback-test.xml 的配置文件
  2. 如果logback-test.xml 未找到,则试图查找名为 logback.groovy的配置文件
  3. 如果还没没有找到,则查找名为 logback.xml的配置文件
  4. 如果没有找到这样的文件,则使用服务提供者加载工具(JDK 1.6中引入的)来解析com.qos.logback.classic.spi的实现。配置器接口,通过查找文件META-INF\services\ch. qm .logback.classic.spi。类路径中的配置器。它的内容应该指定所需配置器实现的完全限定类名。
  5. 如果以上方法都不成功,logback将使用BasicConfigurator自动配置自身,这将导致日志输出定向到控制台。

如果我们没有提供任何配置文件,那么logback将使用默认的配置(BasicConfigurator )。

  • 默认使用ConsoleAppender 输出日志到控制台。
  • 日志的输出使用PatternLayoutEncoder格式化,默认输出格式: %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
  • 日志输出级别DEBUG (root 配置最基础的日志输出级别)

效果等同于

<configuration>
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <!-- encoders are assigned the type
         ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
  </appender>

  <root level="debug">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>
logback 彩色日志

配置彩色日志最重要的步骤就是配置 pattern

logback 支持的颜色:

As of version 1.0.5, PatternLayout recognizes “%black”, “%red”, “%green”,“%yellow”,“%blue”, “%magenta”,“%cyan”, “%white”, “%gray”, “%boldRed”,“%boldGreen”, “%boldYellow”, “%boldBlue”, “%boldMagenta”“%boldCyan”, “%boldWhite” and “%highlight” as conversion words

 <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
       <encoder>
            <pattern> %red(%d{HH:mm:ss.SSS}) %green(%contextName [%thread]) %highlight(%-5level) %cyan(%logger{36}) - %msg%n</pattern>
        </encoder>
 </appender>

  <logger name="com.example" level="WARN" additivity="false">
        <appender-ref ref="console"/>
  </logger>

当然如果想要Pattern重用,可以将模式串定义为变量,然后再引用。

  1. 日志输出模式字符串

     <property name="COLOR_CONSOLE_PATTERN" value="%red(%d{HH:mm:ss.SSS}) %green(%contextName [%thread]) %highlight(%-5level) %cyan(%logger{36}) - %msg%n">
      </property>
    
  2. 引用pattern

    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
            <encoder>
               <!-- <pattern> %red(%d{HH:mm:ss.SSS}) %green(%contextName [%thread]) %highlight(%-5level) %cyan(%logger{36}) - %msg%n</pattern>-->
                <pattern >
                    ${COLOR_CONSOLE_PATTERN}
                </pattern>
            </encoder>
     </appender>
    

结构

一、Logger

如果一个logger的名称后跟一个点是 另一个logger名称的前缀,则该logger被称为另一个logger的祖先

名称为"java" 的logger 是名称为"java.util" logger的父亲, 是"java.util.List"的祖先

root 位于logger 层级结构的最顶部

The root logger resides at the top of the logger hierarchy.

二、Appender

Appender 负责最终输出日志记录。
在这里插入图片描述

OutputStreamAppender将日志信息输出到流(java.io.outputstream)中。

属性名类型说明
encoderEncoder确定将事件写入底层OutputStreamAppender的方式
immediateFlushboolean默认为true。输出流的立即刷新确保日志事件被立即写出来,并且在应用程序没有正确关闭附加程序而退出时不会丢失。这种方式更安全,如果为了显著提高日志吞吐量,可能需要将immediateFlush属性设置为false。如果immediateFlush设置为“false”,如果应用程序退出时未正确关闭appenders,则尚未写入磁盘的日志事件可能会丢失。

不会直接应用OutputStreamAppender, 因为不能方便的转化为字符串,且不能配置输出目的地。
通常配置的是它的子类: ConsoleAppender, FileAppenderRollingFileAppender

1、ConsoleAppender

ch.qos.logback.core.ConsoleAppender, 输出日志信息写到控制台

常用的子元素:

属性名类型说明
encoderEncoderSee OutputStreamAppender properties.
targetStringOne of the String values System.out or System.err. The default target is System.out.
withJansiboolean默认withJansi 属性设置为false。将Jansi设置为true将激活Jansi库(org.fusesource.jansi),该库支持Windows机器上的ANSI颜色代码 。
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="STDOUT" />
  </root>
2、FileAppender

FileAppender是OutputStreamAppender的子类,它将日志信息写到文件中。
目标文件由file 属性指定。如果文件已经存在,则根据append属性的值将其追加或截断。

Property NameTypeDescription
appendboolean该值默认为true。 如果为true,那么日志信息追加到已存在的文件中.
encoderEncoderSee OutputStreamAppender properties.
fileString日志要写入的文件。如果该文件不存在,则会连带父文件夹一起创建
bufferSizeFileSize缓冲大小,如果immediateFlush:false会用到。默认8192(字节)。 1024/10K/20M/1G
prudentboolean是否开启谨慎模式,默认为false。 谨慎模式下,多个jvm(不同的项目,引用同一个logback配置?)同时操作日志文件会串行写入。谨慎模式下,默认append=true
 <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>testFile.log</file>
    <append>true</append>
    <!-- 想要更高的日志吞吐量,可以设置 immediateFlush:false  -->
    <immediateFlush>true</immediateFlush>
    <!-- encoder 未指定class属性: 默认
         ch.qos.logback.classic.encoder.PatternLayoutEncoder-->
    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
    </encoder>
  </appender>
        
  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>

注意:

file: 在windows环境下,要记得转移反斜杠

c:\temp\test.log

因为\t 会被解析为制表符,所以上面的路径是错误的。 正确的路径:

  • c:/temp/test.log
  • c:\\temp\\test.log
3、RollingFileAppender

RollingFileAppender继承自FileAppender是具有动态变更日志文件的功能。

For example, RollingFileAppender can log to a file named log.txt file and, once a certain condition is met, change its logging target to another file.

Property NameTypeDescription
fileString文件名,可以包含路径,不存在时会自动创建
appendboolean日志信息是追加还是覆盖,默认为true
encoderEncoderSee OutputStreamAppender properties.
rollingPolicyRollingPolicy该属性是当rollover 发生时 指示 RollingFileAppender 行为
triggeringPolicyTriggeringPolicy它将告诉RollingFileAppender何时触发 rollover 过程。

rollover : 日志过渡, 从一个日志文件更改为另一个。triggeringPolicy 配置何时会发生过度行为、 rollingPolicy 配置发生过渡时触发的行为。

注意:
配置RollingFileAppender 时,需要同时配置rollingPolicy/triggeringPolicy。 如果一个RollingPolicy实现了TriggeringPolicy接口, 则只需要配置 rollingPolicy即可

3.1 RollingPolicy

RollingPolicy is responsible for the rollover procedure which involves file moving and renaming.

RollingPolicy 负责涉及文件移动和重命名的过渡过程 。

主要存在以下策略:

  • TimeBasedRollingPolicy
  • SizeAndTimeBasedRollingPolicy
  • FixedWindowRollingPolicy
3.1.1 TimeBasedRollingPolicy

基于时间的过渡策略。它根据时间(例如按天或按月)定义过渡策略。

public class TimeBasedRollingPolicy<E> extends RollingPolicyBase implements TriggeringPolicy<E> 

TimeBasedRollingPolicy 同时实现了 RollingPolicyTriggeringPolicy接口。所以具有触发 rollover 和 rollover后的更改的功能。

属性名类型描述
fileNamePatternString必填。 定义rollover (归档)日志文件的名称,rollover 周期是从fileNamePattern的值推断出来的
maxHistoryint控制要保留的最大存档文件数, 异步删除最旧的文档。默认0,表示不删除文档
totalSizeCapint该属性控制所有存档文件的总大小 。当超过总大小上限时,将异步删除最旧的存档。
cleanHistoryOnStartboolean默认为false。 如果设置为true,那么当appender 启动时会将文档移除。
  • maxHistory:
    1. 当旧的归档日志文件被删除时,为归档日志文件而创建的任何文件夹都将被适当地删除
  • totalSizeCap :
    1. 该属性需要设置maxHistory属性。
    2. 除此之外,maxHistory触发执行的优先级高于totalSizeCap 。
  • fileNamePattern:
    1. 该值应当包含文件名称,一个适合的%d 转化符。

    2. 这个%d转化符可以包含日期匹配模式(和SimpleDateFormat 的模式含义相同)

    3. 匹配模式没有设置则默认为yyyy-MM-dd。以天为周期进行日志的重写(每天晚上12点)。

    4. %d{datePattern} , 比如 %d{yyyy_MM} 每月生成新的文件

    5. 在fileNamePattern 属性内datePattern(格式化模式)内,任何地方的正斜杠/或反斜杠\字符将被解释为目录分隔符。

      /mybatis/%d{yyyy/MM}/info.log

      实际生成的文件: /mybatis/2006/10/info.log

fileNamePattern补充

  1. file
    RollingFileAppender 中可以通过file属性设置日志文件的文件名。

    • file属性缺省,那么根据fileNamePattern周期性的生成日志文件。 且不会触发 rollover

    • file 未缺省,当前日志文件名称一直使用 file 属性指定的文件名。 触发rollover 时会新建一个(file指定的名称路径)的文件,并将原文件修改为fileNamePattern指定的名称。

    1. 缺省file属性:
      比如当前时间为2019.10.11日,那么日志当天创建的日志名称为 mybatis.2019-10-11.log。午夜12点以后会新建一个日志文件mybatis.2019-10-12.log
    2. 存在file属性: file=info.log
      那么当天的日志名称就为info.log,午夜12点以后会将当前的日志文件重名为mybatis.2019-10-11.log,并新建一个info.log日志文件。
  2. Multiple %d specifiers
    可能存在需要设置多个%d,但只能选择其中的一个最主要的作为过渡周期,其他次要datePattern需要设置 参数aux

    /var/log/%d{yyyy/MM, aux}/myapplication.%d{yyyy-MM-dd}.log

  3. TimeZone
    在某些情况下,您可能希望根据不同于主机时区的时钟来滚动日志文件. 可以在datePattern 默认后追加 时区参数
    设置为东八区的时区

    test.%d{yyyy-MM-dd,GMT+8}

<configuration>
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>logFile.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <!-- 每天触发 rollover -->
      <fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>
      <!-- 文件最长保留30天(日志文件总数最大3G), 异步删除最旧的日志-->
      <maxHistory>30</maxHistory>
      <totalSizeCap>3GB</totalSizeCap>
    </rollingPolicy>

    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} -%kvp- %msg%n</pattern>
    </encoder>
  </appender> 

  <root level="DEBUG">
    <appender-ref ref="FILE" />
  </root>
</configuration>
3.1.2 SizeAndTimeBasedRollingPolicy

TimeBasedRollingPolicy 可以根据时间维度生成日志文件。

但是会存在某个系统的日志量特别多, 如果基于天。那么排错可能会比较麻烦。 需要打开一个几百M的日志文件。

SizeAndTimeBasedRollingPolicy, 提供了根据时间、日志大小拆分日志的功能。

public class SizeAndTimeBasedRollingPolicy<E> extends TimeBasedRollingPolicy<E> {

因为SizeAndTimeBasedRollingPolicy是TimeBasedRollingPolicy的子类,所以也具有 rollingPolicy triggeringPolicy 的功能

 <appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>mylog.txt</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
      <!-- rollover daily -->
      <fileNamePattern>mylog-%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
       <!--每一份日志文件最大 100M,保留时间60天(%d配置时间维度是天)。
       所有的日志文件总大小不能超过20GB,否则会删除最旧的日志文件-->    
       
       <!--如果当天的日志文件超出了100M,则会进行分裂。
				mylog-2019-01-12.0.txt  
				 mylog-2019-01-12.1.txt  -->
       <maxFileSize>100MB</maxFileSize>    
       <maxHistory>60</maxHistory>
       <totalSizeCap>20GB</totalSizeCap>
    </rollingPolicy>
    <encoder>
      <pattern>%msg%n</pattern>
    </encoder>
  </appender>

注意: 如果使用SizeAndTimeBasedRollingPolicy 需要配置 %d%i

Each time the current log file reaches maxFileSize before the current time period ends, it will be archived with an increasing index, starting at 0.

当mylog.txt 文件达到 maxFileSize 时,就会根据 fileNamePattern创建一个新文件(基于 %d%i)

比如mylog-2019-01-12.3.txt 。 具体的的索引值由%i 决定,该值是递增的。

3.2 TriggeringPolicy

只有当 RollingPolicy 没有实现 TriggeringPolicy时,才需要单独配置。

实际使用很少单独配置 triggeringPolicy属性

4、AsyncAppender

异步保存日志,

<configuration>
  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>myapp.log</file>
    <encoder>
      <pattern>%logger{35} -%kvp -%msg%n</pattern>
    </encoder>
  </appender>

  <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
    <appender-ref ref="FILE" />
  </appender>

  <root level="DEBUG">
    <appender-ref ref="ASYNC" />
  </root>
</configuration>

注意:

如果队列的剩余容量不足20% ,会丢弃TRACE, DEBUG and INFO 事件, 可以通过设置属性discardingThreshold(0),来更改这一行为

by default, when less than 20% of the queue capacity remains, will drop events of level TRACE, DEBUG and INFO keeping only events of level WARN and ERROR. This strategy ensures non-blocking handling of logging events (hence excellent performance) at the cost loosing events of level TRACE, DEBUG and INFO when the queue has less than 20% capacity. Event loss can be prevented by setting the discardingThreshold property to 0 (zero).

Encoders

编码器负责将事件信息转换为字节数组,并将字节数组写入OutputStream。在logback之前的版本(0.9.19)中,大多数附加程序都依赖于一个布局来将事件转换成字符串,并使用java.io.Writer将其写出来。

PatternLayoutEncoder

这是目前logback中提供的有效的编码器。

从logback版本0.9.19开始,无论何时使用FileAppender或者其子类配置PatternLayout 时,都应当使用PatternLayoutEncoder 来替代。

Layouts

Layout 是负责将传入日志事件转换为字符串的组件。

接口方法ch.qos.logback.core.Layout#doLayout, 接受一个日志事件,返回格式化后的字符串

PatternLayout

Logback- classic 包中存在一个十分灵活的布局–PatternLayout。与所有布局一样,PatternLayout接受一个日志事件并返回一个字符串。 通过调整PatternLayout的转换模式可以自定义这个字符串。

这个转化模式和C语言中的printf 相近

转换模式由文字文本和称为转换说明符的格式控制表达式组成

转化说明符的组成部分:

  • 每一个转义符以% 开头
  • 可选的格式修饰符( format modifiers)。控制字段宽度、填充和对齐方式。
  • 可选的转换词(Conversion Word)。 转换字控制要转换的数据字段,例如记录器名称、级别、日期或线程名称
  • 包含在大括号中的可选参数。

FileAppender和子类需要编码器,因此,当与FileAppender或其子类一起使用时,模式布局必须包装在编码器中。考虑到FileAppender/PatternLayout组合非常常见,logback附带了一个名为PatternLayoutEncoder的编码器。

转化词(Conversion Word)

logback 中提供了多种转化词,还有很多同含义的转化词,下面介绍常用的。

  1. lc{length}、 lo{length}、 logger{length}
    在日志事件的起点输出日志记录器的名称。

  2. d{pattern} 、date{pattern} 、d{pattern, timezone} 、date{pattern, timezone}
    用于输出日志事件的日期。
    第一个可选参数pattern。该模式和类java.text.SimpleDateFormat日期模式串中的含义相同

    Conversion PatternResult
    %d2006-10-20 14:06:49,812
    %date2006-10-20 14:06:49,812
    %date{ISO8601}2006-10-20 14:06:49,812
    %date{HH:mm:ss.SSS}14:06:49.812
    %date{dd MMM yyyy;HH:mm:ss.SSS}20 oct. 2006;14:06:49.812
    第二个可选参数 时区。
  3. m 、msg 、 message
    输出与日志事件关联的应用程序提供的消息。logger.warn(“messagexxxx”),该内容就是logger对象输出的日志消息(messagexxxx)。

  4. n
    输出平台相关的行分隔符字符。 “\n”, or “\r\n”.

  5. p 、 le 、 level
    输出日志事件的级别。

  6. t 、 thread
    输出生成日志事件的线程的名称。

  7. M 、method
    输出发出日志请求的方法名。

  8. L 、 line
    输出发出日志请求的行号。生成行号信息比较慢,因此,应该避免使用它。

  9. ex{depth} 、exception{depth} 、throwable{depth} 、ex{depth, evaluator-1, …, evaluator-n}
    输出与日志事件关联的异常的堆栈跟踪(如果有的话)。默认情况下,将输出完整的堆栈跟踪。
    第一个可选参数是控制输出异常堆栈的深度。

    • short:打印第一行堆栈异常消息。
    • full: 打印全部的堆栈异常消息。
    • Any integer: 打印指定行的堆栈异常信息
  10. property{key}
    输出与名为key的属性关联的值。如果key不是logger上下文的属性,那么将在系统属性中查找key。并且没有提供针对于key 默认value值。

 public static void main(String[] args) {
   Logger logger = LoggerFactory.getLogger(LogbackTest.class);
        try{
            int i = 1/0;
        }catch (Exception e){
            logger.error("error",e);
        }
    }

在这里插入图片描述
Logger 对象的输出日志的方法,第二个参数可以传递一个异常对象。而这个异常对象的堆栈信息就可以输出日志中。

 <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>
                %d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} %msg %ex{full} %n
            </pattern>
        </encoder>
    </appender>

这样以后,可以在控制台中看到。

14:07:47.762 logback [main] ERROR test.LogbackTest - error  java.lang.ArithmeticException: / by zero
	at test.LogbackTest.main(LogbackTest.java:11)
Format modifiers
Format modifier左对齐最小宽度最大宽度注释
%20loggerfalse20none如果日志记录器名称长度小于20,长度不足则左填充。
%-20loggertrue20none长度不足则左对齐,右填充。
%.30loggerNAnone30长度大于30则从头开始截取30个字符。
%20.30loggerfalse2030长度小于20则右对齐,长度大于30则从头进行截取
%-20.30loggertrue2030长度小于20左对齐,长度大于30则从头进行截取
%.-30loggerNAnone30长度大于30则从尾部开始截取
Color

输出的日志信息可以指定颜色,这样更容易辨识。

从版本 1.0.5 开始,PatternLayout 可以识别转化词:
“%black”, “%red”, “%green”,“%yellow”,“%blue”, “%magenta”,“%cyan”, “%white”, “%gray”, “%boldRed”,“%boldGreen”, “%boldYellow”, “%boldBlue”, “%boldMagenta”“%boldCyan”, “%boldWhite” and “%highlight”

Filters

Filter用于日志的过滤功能。

可以将多个Filter组成一个有序的列表添加到Appender中。 列表中的每个Filter都会执行decide(ILoggingEvent event) 方法

decide(ILoggingEvent event) 方法返回值FilterReply 是一个枚举类, 有以下三个取值

  • FilterReply.ACCEPT。 日志立即被处理
  • FilterReply.DENY : 日志立即被丢弃
  • FilterReply.NEUTRAL : 由下一个Filter决定日志的去留, 如果后面没有Filter则正常处理
自定义Filter

创建一个自定义的Filter是特别容易的, 继承 Filter, 并实现decide 方法即可

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.filter.Filter;
import ch.qos.logback.core.spi.FilterReply;

public class SampleFilter extends Filter<ILoggingEvent> {

  @Override
  public FilterReply decide(ILoggingEvent event) {    
    if (event.getMessage().contains("sample")) {
      return FilterReply.ACCEPT;
    } else {
      return FilterReply.NEUTRAL;
    }
  }
}

将自定义的Filter 关联到 Appender

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

    <filter class="chapters.filters.SampleFilter" />

    <encoder>
      <pattern>
        %-4relative [%thread] %-5level %logger -%kvp -%msg%n
      </pattern>
    </encoder>
  </appender>
LevelFilter

基于精确的Level匹配 过滤日志事件。

如果Level匹配,Filter根据配置中的onMatch/onMismatch 接受或者丢弃日志

<configuration>
  <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <filter class="ch.qos.logback.classic.filter.LevelFilter">
      <!-- 仅接受INFO级别的日志,其他级别日志丢弃 -->
      <level>INFO</level>
      <onMatch>ACCEPT</onMatch>
      <onMismatch>DENY</onMismatch>
    </filter>
    <encoder>
      <pattern>
        %-4relative [%thread] %-5level %logger{30} -%kvp -%msg%n
      </pattern>
    </encoder>
  </appender>
  <root level="DEBUG">
    <appender-ref ref="CONSOLE" />
  </root>
</configuration>
    public FilterReply decide(ILoggingEvent event) {
        if (!this.isStarted()) {
            return FilterReply.NEUTRAL;
        } else {
            return event.getLevel().equals(this.level) ? this.onMatch : this.onMismatch;
        }
    }
ThresholdFilter

基于指定的阈值过滤日志事件

如果日志level >= threshold, ThresholdFilter的decide方法返回NEUTRAL , 否则返回DENY

For events of level equal or above the threshold, ThresholdFilter will respond NEUTRAL when its decide() method is invoked. However, events with a level below the threshold will be denied.

<configuration>
  <appender name="CONSOLE"
    class="ch.qos.logback.core.ConsoleAppender">
    <!-- 层级低于INFO的日志会被过滤掉 (TRACE and DEBUG)  -->
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
      <level>INFO</level>
    </filter>
    <encoder>
      <pattern>
        %-4relative [%thread] %-5level %logger{30} -%kvp -%msg%n
      </pattern>
    </encoder>
  </appender>
  <root level="DEBUG">
    <appender-ref ref="CONSOLE" />
  </root>
</configuration>
    public FilterReply decide(ILoggingEvent event) {
        if (!this.isStarted()) {
            return FilterReply.NEUTRAL;
        } else {
            return event.getLevel().isGreaterOrEqual(this.level) ? 
                              FilterReply.NEUTRAL : FilterReply.DENY;
        }
    }
EvaluatorFilter

EvaluatorFilter 封装了一个 EventEvaluator, EventEvaluator 可以计算给定的事件是否匹配表达式。 通过属性onMatch or onMismatch 决定事件去留。

EventEvaluator 是一个抽象类, 可以自定义或者使用 JaninoEventEvaluator

JaninoEventEvaluator 可以接受任意返回boolean值的Java表达式。

见名知意,JaninoEventEvaluator依赖 Janino library

<dependency>
  <groupId>org.codehaus.janino</groupId>
  <artifactId>janino</artifactId>
  <version>3.0.6</version>
</dependency>
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <filter class="ch.qos.logback.core.filter.EvaluatorFilter">      
      <evaluator> <!-- defaults to type ch.qos.logback.classic.boolex.JaninoEventEvaluator -->
        <expression>return message.contains("billing");</expression>
      </evaluator>
      <OnMismatch>NEUTRAL</OnMismatch>
      <OnMatch>DENY</OnMatch>
    </filter>
    <encoder>
      <pattern>
        %-4relative [%thread] %-5level %logger -%kvp -%msg%n
      </pattern>
    </encoder>
  </appender>

计算表达式是基于当前日志事件, 日志表达式支持使用 日志事件(LoggingEvent)中的各个Filed

Logback-classic automatically exports various fields of the logging event as variables accessible from the evaluation expression

NameTypeDescription
eventLoggingEvent与日志记录请求关联的原始日志记录事件。 以下所有变量也可从事件中获得
messageString日志记录请求的原始消息. logger.info(“Hello {}”, name); message就是 "Hello {}"
formattedMessageString日志记录请求中的格式化消息. logger.info(“Hello {}”, name); name赋值 “张三” formattedMessage :"Hello 张三"
loggerStringThe name of the logger.
loggerContextLoggerContextVOA restricted (value object) view of the logger context to which the logging event belongs to.
levelint日志level级别
timeStamplong日志事件创建事件戳.
markerMarker与日志记录请求关联的maker对象. 注意:marker 可能null
mdcMap包含创建日志记录事件时的所有 MDC 值的映射。
throwablejava.lang.Throwable如果没有异常与事件关联,值为null。因为throwable 不会被序列化,所以在远程系统,这个值一直为null 。可以使用 throwableProxy
throwableProxyIThrowableProxy与日志记录事件关联的异常的代理。如果没有异常与事件关联,值为throwableProxy 为null 。 否则 远程服务器可以拿到值 (即使在序列化之后)

mdc

  • 可以通过get方法获取值。 比如mdc.get(“myKey”).
  • 从 logback-classic版本 0.9.30 开始,“mdc”变量永远不会为空。
  • Map 是非参数化的因为Janino 不支持泛型 mdc.get() 总是返回Object
    如果获取的是字符串值,需要强制转换 ((String) mdc.get(“k”)).contains(“val”).
错误

更多错误信息,请看官网 logback

Could not find Janino library on the class path. Skipping conditional processing.

Conditional processing in configuration files requires the library.

在logback 配置文件中使用 条件处理语句需要引入 Janino

<dependency>
  <groupId>org.codehaus.janino</groupId>
  <artifactId>janino</artifactId>
  <version>3.0.6</version>
</dependency>
This appender no longer admits a layout as a sub-component, set an encoder instead.

之前配置logback 的 appender 可能如下:

<appender name="FILE" class="ch.qos.logback.core.FileAppender">
  <file>testFile.log</file>
  ...
  <layout class="ch.qos.logback.classic.PatternLayout">
    <pattern>%msg%n</pattern>
  </layout>
</appender>   

官方已经不建议这么使用,而是推荐使用encoder

<appender name="FILE" class="ch.qos.logback.core.FileAppender">
  <file>testFile.log</file>
  <!-- encoders are assigned the type 
       ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
  <encoder>
    <pattern>%msg%n</pattern>
  </encoder>
</appender>  
Spring Boot 日志

现在比较流行使用spring boot 构建maven项目,Spring Boot支持Java Util Logging,Log4j2,Lockback作为日志框架。

对于spring boot 而言 ,我们不必单独引入那么多jar,只需要引入spring-boot-starter包就可以了。spring-boot-starter包中依赖了spring-boot-starter-logging。而在spring-boot-starter-logging中引入了slf4j 和 logback 。

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

日志框架配置文件
Logbacklogback-spring.xml, logback-spring.groovy, logback.xml, logback.groovy
Log4jlog4j-spring.properties, log4j-spring.xml, log4j.properties, log4j.xml
Log4j2log4j2-spring.xml, log4j2.xml
JDK (Java Util Logging)logging.properties

Spring Boot官方推荐优先使用带有-spring的文件名作为你的日志配置(如使用logback-spring.xml,而不是logback.xml),命名为logback-spring.xml的日志配置文件,spring boot可以为它添加一些spring boot特有的配置项

Spring Boot 配置文件配置日志
# 日志级别 ,针对对所有的日志
logging.level.root=DEBUG
# 针对某个包下的日志输出级别
logging.level.org.example=DEBUG

# LOGGING
## 日志的配置文件
logging.config= # Location of the logging configuration file. For instance `classpath:logback.xml` for Logback
# 日志文件
logging.file= # Log file name. For instance `myapp.log`
# 路径
logging.path= # Location of the log file. For instance `/var/log`
# 控制台日志输出 模式
logging.pattern.console= # Appender pattern for output to the console. Only supported with the default logback setup.
# 文件日志输出 模式
logging.pattern.file= # Appender pattern for output to the file. Only supported with the default logback setup.
# 模式的级别
logging.pattern.level= # Appender pattern for log level (default %5p). Only supported with the default logback setup.
logging.register-shutdown-hook=false # Register a shutdown hook for the logging system when it is initialized.

参考:
SpringBoot 日志
logback官网

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值