后端——框架——日志框架——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

原文地址:https://www.cnblogs.com/rain144576/p/12304478.html