zoukankan      html  css  js  c++  java
  • 后端——框架——日志框架——logback——《官网》阅读笔记——第六章节(Layout和日志格式)

    第六章节介绍核心对象Layout,不同于Encoder,Appender等其他核心对象,它的核心不是类的职责和其类体系结构,而是它的格式化表达式,它是Layout的pattern属性。

    类似于正则表达式,其实无论是Java语言,JS语言,它的难度在于表达式本身,而不是与之关联的对象。

    本章的主要内容如下:

    1. 自定义Layout,并在其中添加自定义属性。
    2. Layout的日志格式。
    3. 其他Layout对象,HTMLLayout,XMLLayout,这些对象的使用频率很低。待完善
    4. Logback-access模块的格式化表达式。待完善

    1、自定义Layout

    1.1   类结构

      

      

    1.2  概念

    在编写自定义Layout之前,首先需要理解编写配置文件与Java对象之间的对象。

    在配置文件中配置encoder标签,本质是在配置Appender对象的encoder属性,其中该标签的class属性为Encoder的类型,当类型为PatternLayoutEncoder时,可以省略。

    在配置encoder子标签时,它本质是配置Encoder类的属性,所以根据不同的Encoder类型,它的子标签也是不一样的。

    假设class为PatternLayoutEncoder时

    • 配置pattern标签,相当于给对象的pattern属性赋值。
    • 配置layout标签,相当于给对象的layout属性赋值,其中标签的class属性为Layout的类型。

    自定义Layout就是编写自定义的Layout接口实现类。

    1.3   步骤

    在编写自定义Layout时,首先需要了解Layout的类结构和概念。它的具体步骤如下:

    1. 编写自定义MyLayout,它可以实现Layout接口,也可以继承抽象类LayoutBase。本例中选择继承LayoutBase,它提供了接口的默认实现。MtLayout只需要实现doAppend方法即可。
    2. 在MyLayout添加0..N个自定义属性,这些属性必须有set方法。
    3. 在配置文件中,设置encoder标签的class属性值为LayoutWrapperEncoder,这个是适配器类。
    4. 在配置文件中,设置encoder子标签layout,它的class属性值为MyLayout,如果存在自定义属性,可以将其配置为layout子标签。

      1.4   代码

      自定义Layout类MyLayout

    /**
     * 
     * @File Name: MyLayout.java
     * @Description: 自定义layout类
     * @version 1.0
     * @since JDK 1.8
     */
    public class MyLayout extends LayoutBase<ILoggingEvent> {
    	// 添加自定义属性prefix
    	private String prefix;
    	// 添加自定义属性suffix;
    	private String suffix;
    	//
    	private static final String DEFAULT_SPLIT_STR = "****";
    
    	public String doLayout(ILoggingEvent event) {
    		StringBuffer sbuf = new StringBuffer();
    		// 添加前缀
    		if (!StringUtils.isEmpty(prefix)) {
    			sbuf.append(prefix).append(DEFAULT_SPLIT_STR);
    		}
    		// 时间戳
    		sbuf.append(event.getTimeStamp()).append(DEFAULT_SPLIT_STR);
    		// 级别
    		sbuf.append(event.getLevel().levelStr).append(DEFAULT_SPLIT_STR);
    		// 线程
    		sbuf.append(event.getThreadName()).append(DEFAULT_SPLIT_STR);
    		// logger name
    		sbuf.append(event.getLoggerName()).append(DEFAULT_SPLIT_STR);
    		// line separator
    		sbuf.append(event.getFormattedMessage()).append(DEFAULT_SPLIT_STR);
    		// 添加后缀
    		if (!StringUtils.isEmpty(suffix)) {
    			sbuf.append(suffix).append(DEFAULT_SPLIT_STR);
    		}
    		// 分隔符
    		sbuf.append("
    ");
    		return sbuf.toString();
    	}
    	public void setPrefix(String prefix) {
    		this.prefix = prefix;
    	}
    	public void setSuffix(String suffix) {
    		this.suffix = suffix;
    	}
    }
    

       配置文件,只给出appender部分的内容

    <!-- 配置ConsoleAppender -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
    	<!-- 默认值,可以省略,此处只是为了学习 -->
    	<target>System.out</target>
    	<!-- 默认值,可以省略,它的作用是为了给不同级别的日志添加不同的颜色背景 -->
    	<withJansi>false</withJansi>
    	<!-- 配置encoder,大部分学习的都是logback-classic模块的内容 -->
    	<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
    		<!-- 添加自定义Layout,由于配置了Layout,不在需要配置pattern,它是PatternLayoutEncoder的一个属性 -->
    		<layout class="learn.logback.chapter6.MyLayout">
    			<!-- 配置自定义属性 -->
    			<prefix>[single log start]</prefix>
    			<suffix>[single log end]</suffix>
    		</layout>
    	</encoder>
    </appender>
    

      单条日志的效果如下:

    [single log start] ****1582122070664****DEBUG****main****learn.logback.chapter1.HelloWorld****Hello张三Welcome to our website**** [single log end]**** 

    2、日志格式

    当在配置日志格式时,此时它对应的类必须是PatternLayoutEncoder,表现在配置文件上为encoder标签中class属性值为默认值。配置日志格式本质是给PatternLayoutEncoder对象的pattern属性赋值。该属性的主要作用是控制日志信息的格式。

    日志格式由一个个小单元组成,每个小单元由三个部分组成,

    • Format modifier:它的作用是控制日志信息的长度。功能有补充空白字符,截取字符。其中符号”-”表示方向,它表示从末尾补充,或从末尾截取。
    • Conversion Name:它是日志表达式的核心,对应ILoggingEvent中的某一个具体信息,可以是线程,可以是时间,可以是日志内容等等,这部分是小单元的核心。它的格式通常为% + conversionName,conversion Name可以是全称,也可以是缩写
    • Optional parameters:可选参数,它与conversionName密切相关,例如当conversionName为时间时,参数为日期格式,当conversionName为logger名称时,参数为名称的最大长度。

    2.1   Conversion Name

    Conversion name很多,我将它分为五类。

    • 基本:date(时间),logger(名称),level(级别),thread(线程),message(日志信息),%n(换行符),这些是最基本的,也是必备的一些信息。
    • 变量:contextName(上下文名称),marker(标签),Mdc(MDC对象的key-value对),Property(property属性,环境变量等)。
    • 杂项:line(行号),replace(字符串的替换方法),class(类全名),file(类文件名)
    • 方法:method(方法名称),caller(方法调用层次),使用频率低,本文省略。
    • 异常:exception,nopexception,rootException,xException,使用默认值即可,本文省略。

    2.1.1    date

    描述

    date,缩写为d

    参数

    名称:pattern

          说明:日期的格式,

          值:yyyy-MM-dd HH:mm:ss SSS任意组合。

          是否必填:否,默认格式为yyyy-MM-dd HH:mm:ss SSS

     

    名称:timezone

          说明: 时区,

          值:任意合理的时区,例如Asia/shanghai。

          是否必填:否,默认为系统的时区。

    性能

    使用频率很高,不影响性能。

    示例

    %d{yyyy-MM-dd HH:mm:ss SSS},// 指定日期格式

    %date,// 使用默认的格式

    %date{yyyy-MM-dd HH:mm:ss SSS,Asia/shanghai},// 带有时区参数。

    2.1.2   logger & class & file

    描述

    Logger,缩写为c,lo。个人不建议使用缩写,缩写的语义不太明显

    参数

    名称:length

          说明:Logger名称的最大长度,当logger的name长度大于length时,会对name进行截取,它总是name开始处截取。

          值:任何整数。

          是否必填:否,

    性能

    使用频率很高,不影响性能。

    示例

    %logger{30}:logger名称的最大长度为30。

    关联的conversion name

    1. Class表示类名,缩写为C
    2. File表示Java文件,缩写为F

    它们基本不会用到,因为logger的名称一般都是类全名,而Java中类名和Java的文件名是一致的。所以class,file都可以从logger名称中推测出来,有点多余。

      示例如下:

      当pattern的格式为:%d{HH:mm:ss.SSS} [%logger] [%class] [%file] %n

      它对应的效果图为:

    15:43:51.438 [learn.logback.chapter1.HelloWorld] [learn.logback.chapter1.HelloWorld] [HelloWorld.java]
    

      三者的值基本都是相同的。

    2.1.3   Thread

    描述

    Thread,缩写为t,表示当前线程的名称

    参数

    性能

    使用频率很高,不影响性能。

    示例

    %thread

    2.1.4  Level

    描述

    Logger request的日志级别,它不是在logger标签对应的level,缩写为l

    参数

    性能

    使用频率很高,不影响性能。

    示例

    %level

    2.1.5   message

    描述

    Logging request的信息内容,缩写为m

    参数

    性能

    使用频率很高,不影响性能。

    示例

    %message,%msg

      默认的日志格式由上述5个部分组成,最后的%n表示换行符。%d  [%thread] %-5level %logger{36} - %msg%n

    2.1.6   ContextName

    描述

    日志框架上下文的名称,即LoggerContext对象的name属性,在使用时需要配置contextName标签。缩写为cn

    参数

    性能

    使用频率一般,不影响性能。

    示例

    %contextName,%cn

      示例如下:

      当配置<contextName>Learn_Logback</contextName>时

    // 日志格式:
    %d [%contextName] [%marker] %n
    // 日志
    2020-02-20 16:09:38,841 [Learn_Logback] []

    2.1.7   Marker

    描述

    日志请求的标记,在调用请求相关方法时,第一个参数为marker,第二个参数为message。使用MarkerFactory的getMarker创建Marker对象。

    参数

    性能

    使用频率一般,不影响性能。

    示例

    %Marker

      示例如下:

      当代码为:

    Marker test =MarkerFactory.getMarker("Marker test");
    logger.debug(test, "Hello World");
    

      它的效果如下:

    // 日志格式:
    %d [%contextName] [%marker] %n
    // 日志
    2020-02-20 16:16:40,901 [Learn_Logback] [Marker test]

    2.1.8   Mdc

    描述

    org.slf4j.MDC保存着key-value键值对,该标签根据key值,访问value值。使用时,需要在之前设置MDC.put(key,value)方法

    参数

    Key值

    性能

    使用频率一般,不影响性能。

    示例

    %mdc{key}

    示例如下:

    代码为:

    MDC.put("mdc_key", "mdc_value");
    Marker test =MarkerFactory.getMarker("Marker test");
    logger.debug(test, "Hello World");
    

      它的效果如下:

    // 日志格式:
    %d [%contextName] [%marker] [%mdc{mdc_key}] %n 
    // 日志
    2020-02-20 16:26:33,814 [Learn_Logback] [Marker test] [mdc_value]

      2.1.9   Property

    描述

    根据property中的key值获取value值。property它的值有四种,配置文件中的property标签,引入的properties文件,JVM变量,操作系统的环境变量。

    参数

    变量的Key值

    性能

    使用频率一般,不影响性能。

    示例

    %property{key}

    示例如下:

    此例中获取JVM中的os.name变量。

    它的效果如下:

    // 日志格式:
    %d [%mdc{mdc_key}] [%property{os.name}] %n// 日志
    2020-02-20 16:26:33,814  [mdc_value] [Windows 10]

    2.1.10  Line

    描述

    日志显示行号,缩写为L

    参数

    性能

    使用频率一般,不影响性能。

    示例

    %line,%L

    2.2  Formatting

    格式化指定日志中某个部分的长度。它有两种形式:

    格式一:%  +  num  +   conversionName

    1. %固定字符串。
    2. 当num为正整数时,当conversionName的长度小于num时,会在开头填充空格。大于时什么都不做,当num为负数时,在末尾填充空格。
    3. ConversionName:日志的任何组成部分,可以使用括号将一组conversionName括起来。

    示例:

    %20logger:当logger的长度小于20时,会在开头填充空格。

    %20(%logger %level %thread),将logger,level,thread当成一组,一个整体,当整体部分小于20时,会在开头填充空格。

    格式二:%  +  dot  + num  +  conversionName

    1. %固定字符串,dot表示点号(.)。
    2. 当num为正整数时,当conversionName的长度大于num时,会从开头截取字符串,小于时什么都不做。当num为负数时,会从末尾开始截取字符串。

    示例:

    %.1level:如果为INFO时,表示为O,被截取掉的字符串为INF。

    %.-1level:如果为INFO时,表示为I,被截取掉的字符串为NFO。

    2.3  Coloring

             Coloring的主要功能是为不同级别的日志配置不同的背景色。要实现此功能有很多种方式,例如在Eclipse中安装logViewer插件,Idea可以使用JansiColor的插件。本文省略。

    2.4  Evaluator

             TODO

    2.5   自定义conversionName

             TODO

    3、HtmlLayout

             TODO

    4、XMLLayout

             TODO

    5、Access模块

      TODO

  • 相关阅读:
    每日一题 为了工作 2020 0412 第四十一题
    每日一题 为了工作 2020 04011 第四十题
    每日一题 为了工作 2020 0410 第三十九题
    每日一题 为了工作 2020 0409 第三十八题
    每日一题 为了工作 2020 0408 第三十七题
    每日一题 为了工作 2020 0407 第三十六题
    每日一题 为了工作 2020 0406 第三十五题
    每日一题 为了工作 2020 0405 第三十四题
    学习总结(二十四)
    学习总结(二十三)
  • 原文地址:https://www.cnblogs.com/rain144576/p/12304478.html
Copyright © 2011-2022 走看看