- 一、log4j与logback的关系
- 二、为什么使用logback
- 三、SpringBoot项目对logback的使用
- 3.1、添加依赖
- 3.2、默认配置
- 四、logback-spring.xml详解
- 4.1、logback-spring.xml的概述
- 4.2、logback-spring.xml中的三个主要类
- 4.3、日志级别
- 4.4、< configuration>元素
- 4.5、< logger>元素
- 4.6、< root>元素
- 4.7、< appender>元素
- 4.7.1、ConsoleAppender
- 4.7.2、RollingFileAppender
- 4.7.3、滚动策略
- 4.8、< encoder>元素
- 4.9、< filter>元素
- 五、详细的logback-spring.xml示例
- 六、log日志输出代码注意事项
- log4j与logback两个框架的作者是同一个人,Logback旨在作为流行的log4j项目的后续版本,从而恢复log4j离开的位置。
- slf4j(Simple Logging Facade for Java) 则是一个日志门面框架,提供了日志系统中常用的接口,logback 和 log4j 则对slf4j 进行了实现。
- Logback 是log4j 框架的作者开发的新一代日志框架,它效率更高、能够适应诸多的运行环境,同时天然支持SLF4J。
- Logback的定制性更加灵活,同时也是spring boot的内置日志框架。
-
maven依赖中添加spring-boot-starter-logging依赖包。
org.springframework.boot spring-boot-starter-logging
-
但是实际开发中我们不需要直接添加spring-boot-starter-logging依赖,因为spring-boot-starter中包含了 spring-boot-starter-logging,该依赖内容就是 Spring Boot 默认的日志框架 Logback+SLF4J。而 spring-boot-starter-web 包含了spring-boot-starter,所以我们只需要引入web组件即可:
org.springframework.boot spring-boot-starter-web
-
默认情况下Spring Boot将日志输出到控制台,不会写到日志文件。如下图所示:
-
如果要编写除控制台输出之外的日志文件,则需在application.yml中设置logging.file.path或logging.path.name属性
- Spring Boot官方推荐优先使用带有-spring的文件名作为你的日志配置(如使用logback-spring.xml,而不是logback.xml),命名为logback-spring.xml的日志配置文件,将xml放至 src/main/resource下面。
- 也可以使用自定义的名称,比如logback-config.xml,只需要在application.yml文件中使用logging.config=classpath:logback-config.xml指定即可。
-
Logback基于三个主要类:Logger,Appender和Layout。这三种类型的组件协同工作,使开发人员能够根据消息类型和级别记录消息,并在运行时控制这些消息的格式以及报告的位置。
-
如下配置是一个最基本的xml配置:
%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
- 日志级别依次为【从高到低】:FATAL > ERROR > WARN > INFO > DEBUG > TRACE
-
logback-spring.xml配置文件的基本结构可以描述为元素,包含零个或多个< appender>元素、零个或多个< logger>元素、最多一个< root>元素(也可以没有)。
-
基本结构图解如下:
- < logger>元素只接受一个必需的name属性,一个可选的level属性和一个可选的additivity属性,允许值为true或false。level属性的值允许一个不区分大小写的字符串值TRACE、DEBUG、INFO、WARN、ERROR、ALL或OFF。
- 元素可以包含零个或多个< appender-ref>元素,这样引用的每个appender都被添加到指定的logger中。
- < root>元素配置根记录器。它支持单个属性,即level属性。它不允许任何其他属性,因为additivity标志不适用于根记录器。此外,由于根记录器已被命名为“ROOT”,因此它也不允许使用name属性。
- level属性的值可以是不区分大小写的字符串TRACE、DEBUG、INFO、WARN、ERROR、ALL或OFF之一,< root>元素可以包含零个或多个< appender-ref>元素; 这样引用的每个appender都被添加到根记录器中。
-
appender使用< appender>元素配置,该元素采用两个必需属性name和class。name属性指定appender的名称,而class属性指定要实例化的appender类的完全限定名称。
-
< appender>元素可以包含零个或一个< layout>元素,零个或多个< encoder>元素以及零个或多个< filter>元素.
-
在logback中,输出目标称为appender,addAppender方法将appender添加到给定的记录器logger。给定记录器的每个启用的日志记录请求都将转发到该记录器中的所有appender以及层次结构中较高的appender。换句话说,appender是从记录器层次结构中附加地继承的。具体如下图所示:
-
Appender是一个接口,它有许多子接口和实现类,具体如下图所示:
-
其中最重要的两个Appender为:ConsoleAppender 、RollingFileAppender。
- ConsoleAppender,如名称所示,将日志输出到控制台上。
- RollingFileAppende是FileAppender的一个子类,扩展了FileAppender,具有翻转日志文件的功能。例如,RollingFileAppender 可以记录到名为log.txt文件的文件,并且一旦满足某个条件,就将其日志记录目标更改为另一个文件。
- TimeBasedRollingPolicy:可能是最受欢迎的滚动策略。它根据时间定义翻转策略,例如按天或按月。实际上,TimeBasedTriggeringPolicy实现了RollingPolicy和TriggeringPolicy接口。
- SizeAndTimeBasedRollingPolicy:按日期归档文件同时限制每个日志文件的大小,logback 提供了 SizeAndTimeBasedRollingPolicy ,它是TimeBasedRollingPolicy的一个子类,实现了基于时间和日志文件大小的翻滚策略。
-
encoder中最重要就是pattern属性,它负责控制输出日志的格式,这里给出一个我自己写的示例:
-
词语解释
语法解释%d{yyyy-MM-dd HH:mm:ss.SSS}日期%-5level日志级别%highlight()颜色,info为蓝色,warn为浅红,error为加粗红,debug为黑色%thread打印日志的线程%15.15()如果记录的线程字符长度小于15(第一个)则用空格在左侧补齐,如果字符长度大于15(第二个),则从开头开始截断多余的字符%logger日志输出的类名%-40.40()如果记录的logger字符长度小于40(第一个)则用空格在右侧补齐,如果字符长度大于40(第二个),则从开头开始截断多余的字符%cyan颜色%msg日志输出内容%n换行符
-
filter中最重要的两个过滤器为:LevelFilter、ThresholdFilter。
-
LevelFilter 根据精确的级别匹配过滤事件。如果事件的级别等于配置的级别,则筛选器接受或拒绝该事件,具体取决于onMatch和onMismatch属性的配置。例如下面配置将只打印INFO级别的日志,其余的全部禁止打印输出:
INFO ACCEPT DENY %-4relative [%thread] %-5level %logger{30} - %msg%n
-
ThresholdFilter 过滤低于指定阈值的事件。对于等于或高于阈值的事件,ThresholdFilter将在调用其decision()方法时响应NEUTRAL,例如下面的配置将拒绝所有低于INFO级别的日志,只输出INFO以及以上级别的日志:
INFO %-4relative [%thread] %-5level %logger{30} - %msg%n
-
logback-spring.xml配置文件完整实例代码,具体如下所示:
%d{yyyy-MM-dd HH:mm:ss.SSS} %highlight(%-5level) --- [%15.15(%thread)] %cyan(%-40.40(%logger{40})) : %msg%n UTF-8 logs/project_info.log true ERROR DENY ACCEPT logs/project_info.%d.%i.log 30 20GB 10MB %d{yyyy-MM-dd HH:mm:ss.SSS} %-5level --- [%15.15(%thread)] %-40.40(%logger{40}) : %msg%n UTF-8 logs/project_error.log true ERROR logs/project_error.%d.%i.log 30 20GB 10MB %d{yyyy-MM-dd HH:mm:ss.SSS} %-5level --- [%15.15(%thread)] %-40.40(%logger{40}) : %msg%n UTF-8 ERROR > WARN > INFO > DEBUG > TRACE -->
-
第一种方式日志输出
Object obj= new Object(); logger.debug("The obj is " + obj);
-
第一种方式日志输出会存在构造消息参数的成本,即将obj转换成字符串相加。 并且无论是否记录消息,都是如此。下面是优化后的第二种方式:
if(logger.isDebugEnabled()) { Object obj= new Object(); logger.debug("The obj is " + obj); }
-
第二种方式中,首先对设置的日志级别进行了判断,如果为debug模式,才进行参数的构造,对第一种写法进行了改善。不过还有最好的写法,使用占位符,下面是优化后的第三种方式:
Object obj= new Object(); logger.debug("The objis {}.", obj);
-
logback作者进行测试得出:第一种和第三种写法将产生完全相同的输出。但是,在禁用日志记录语句的情况下,第三个变体将比第一个变体优于至少30倍。
//如果有多个参数,写法如下: logger.debug("The new obj is {}. It replaces {}.", obj, oldObj);