springboot的日志框架slf4j (使用logback输出日志以及使用)

时间:2021-09-29 15:57:45

1、为什么使用logback?

——在开发中不建议使用System.out因为大量的使用会增加资源的消耗。因为使用System.out是在当前线程执行的,写入文件也是写入完毕之后才继续执行下面的程序。而使用Log工具不但可以控制日志是否输出,怎么输出,它的处理机制也是通知写日志,继续执行后面的代码不必等日志写完。

——个人推荐使用SLF4J(Simple Logging Façade For Java)的logback来输出日志,其比log4j效率高。

    ——Spring Boot 提供了一套日志系统,logback是最优先的选择。

2、logback,slf4j,log4j之间的关系

Slf4j是The Simple Logging Facade for Java的简称,是一个简单日志门面抽象框架,它本身只提供了日志Facade API和一个简单的日志类实现,一般常配合Log4j,LogBack,java.util.logging使用。Slf4j作为应用层的Log接入时,程序可以根据实际应用场景动态调整底层的日志实现框架(Log4j/LogBack/JdkLog...);

LogBack和Log4j都是开源日记工具库,LogBack是Log4j的改良版本,比Log4j拥有更多的特性,同时也带来很大性能提升。

3、Logback的结构

LogBack被分为3个组件,logback-core, logback-classic 和 logback-access.

其中logback-core提供了LogBack的核心功能,是另外两个组件的基础。

logback-classic则实现了Slf4j的API,所以当想配合Slf4j使用时,需要将logback-classic加入classpath。

logback-access是为了集成Servlet环境而准备的,可提供HTTP-access的日志接口;

spring-boot默认支持logback,所以无需引用任何以来只需要,配置application.properties即可,如果要功能丰富些,则配置下logback.xml

4、为什么Spring Boot推荐使用logback-spring.xml来替代logback.xml来配置logback日志的问题分析

即,logback.xml加载早于application.properties,所以如果你在logback.xml使用了变量时,而恰好这个变量是写在application.properties时,那么就会获取不到,只要改成logback-spring.xml就可以解决。

5、具体的配置

在application.yml中的配置:

springboot的日志框架slf4j (使用logback输出日志以及使用)

在logback-spring.xml中的配置;
多环境的配置:

多环境日志输出

根据不同环境(prod:生产环境,test:测试环境,dev:开发环境)来定义不同的日志输出,在 logback-spring.xml 中使用 springProfile 节点来定义,方法如下:

【注意文件名称不是logback.xml,想使用spring扩展profile支持,要以logback-spring.xml命名】

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml" />
<logger name="org.springframework.web" level="INFO"/>
<logger name="org.springboot.sample" level="TRACE" /> <!-- 测试环境+开发环境. 多个使用逗号隔开. -->
<springProfile name="test,dev">
<logger name="org.springframework.web" level="INFO"/>
<logger name="org.springboot.sample" level="INFO" />
<logger name="com.kfit" level="info" />
</springProfile> <!-- 生产环境. -->
<springProfile name="prod">
<logger name="org.springframework.web" level="ERROR"/>
<logger name="org.springboot.sample" level="ERROR" />
<logger name="com.kfit" level="ERROR" />
</springProfile> </configuration>

  6、日志的级别

默认输出该等级之上的日志,顺序是由高到底,ERROR--WARN--INFO--DEBUG--TRACE

@RunWith就是一个运行器

@RunWith(JUnit4.class)就是指用JUnit4来运行

@RunWith(SpringJUnit4ClassRunner.class),让测试运行于Spring测试环境

@RunWith(Suite.class)的话就是一套测试集合,

@RunWith 翻译成中文就是 测试运行器,JUnit所有的测试方法都是由测试运行器负责执行。

JUnit为单元测试提供了一个默认的测试运行器BlockJUnit4ClassRunner,但是没有限制必须使用默认的运行器。

我们常用的有参数运行器

@RunWith(Suit.Class)

@SuitClasses(MyTest.Class,MyTest2.Class)

这个是打包测试功能,多个class 可以一起执行测试,不需要一个一个执行,这样节省时间,提高效率

@RunWith(Parameteried.Class)

模拟不同的参数方法进行测试,如果为每个类型参数创建一个方法,那是很耗时,傻瓜式的。

@RunWith(SpringJUnit4ClassRunner.class)

这个是用springmvc的容器

@RunWith(Parameterized.class)

  

springboot的日志框架slf4j (使用logback输出日志以及使用)

7、在java类中如何使用呢,springboot是约定大于配置,所以我们使用注解的方式来配置

springboot的日志框架slf4j (使用logback输出日志以及使用)

springboot的日志框架slf4j (使用logback输出日志以及使用)

在日志中输出变量的方式:

springboot的日志框架slf4j (使用logback输出日志以及使用)

8、logback-spring.xml的具体的配置我们可以参考如下博客

https://blog.csdn.net/qianyiyiding/article/details/76565810

http://412887952-qq-com.iteye.com/blog/2307244

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true">
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
<property name="LOG_NAME" value="/home"></property>
<!-- %m输出的信息,%p日志级别,%t线程名,%d日期,%c类的全名,,,, -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!--<pattern>%d %p (%file:%line\)- %m%n</pattern>-->
<!--格式化输出:%d:表示日期 %thread:表示线程名 %-5level:级别从左显示5个字符宽度 %msg:日志消息 %n:是换行符-->
<pattern>1-%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger - %msg%n</pattern>
<charset>GBK</charset>
</encoder>
</appender>
<!--<include resource="org/springframework/boot/logging/logback/base.xml"/>-->
<contextName>RestAPI</contextName>
<property name="LOG_PATH" value=".logs"/>
<!--设置系统日志目录-->
<property name="APPDIR" value="app"/>
<!--
说明:
1、日志级别及文件
日志记录采用分级记录,级别与日志文件名相对应,不同级别的日志信息记录到不同的日志文件中
例如:error级别记录到log_error_xxx.log或log_error.log(该文件为当前记录的日志文件),而log_error_xxx.log为归档日志,
日志文件按日期记录,同一天内,若日志文件大小等于或大于2M,则按0、1、2...顺序分别命名
例如log-level-2013-12-21.0.log
其它级别的日志也是如此。
2、文件路径
若开发、测试用,在Eclipse中运行项目,则到Eclipse的安装路径查找logs文件夹,以相对路径../logs。
若部署到Tomcat下,则在Tomcat下的logs文件中
3、Appender
FILEERROR对应error级别,文件名以log-error-xxx.log形式命名
FILEWARN对应warn级别,文件名以log-warn-xxx.log形式命名
FILEINFO对应info级别,文件名以log-info-xxx.log形式命名
FILEDEBUG对应debug级别,文件名以log-debug-xxx.log形式命名
CONSOLE将日志信息输出到控制上,为方便开发测试使用
-->
<!-- 日志记录器,日期滚动记录 -->
<appender name="FILEERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/${APPDIR}/log_error.log</file>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 归档的日志文件的路径,例如今天是2013-12-21日志,当前写的日志文件路径为file节点指定,可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。
而2013-12-21的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
<fileNamePattern>${LOG_PATH}/${APPDIR}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
命名日志文件,例如log-error-2013-12-21.0.log -->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>2MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!-- 追加方式记录日志 -->
<append>true</append>
<!-- 日志文件的格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>===%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger Line:%-3L - %msg%n</pattern>
<charset>utf-8</charset>
</encoder>
<!-- 此日志文件只记录info级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>error</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender> <!-- 日志记录器,日期滚动记录 -->
<appender name="FILEWARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/${APPDIR}/log_warn.log</file>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 归档的日志文件的路径,例如今天是2013-12-21日志,当前写的日志文件路径为file节点指定,可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。
而2013-12-21的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
<fileNamePattern>${LOG_PATH}/${APPDIR}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
命名日志文件,例如log-error-2013-12-21.0.log -->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>2MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!-- 追加方式记录日志 -->
<append>true</append>
<!-- 日志文件的格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>===%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger Line:%-3L - %msg%n</pattern>
<charset>utf-8</charset>
</encoder>
<!-- 此日志文件只记录info级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>warn</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender> <!-- 日志记录器,日期滚动记录 -->
<appender name="FILEINFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${LOG_PATH}/${APPDIR}/log_info.log</file>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 归档的日志文件的路径,例如今天是2013-12-21日志,当前写的日志文件路径为file节点指定,可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。
而2013-12-21的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
<fileNamePattern>${LOG_PATH}/${APPDIR}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
命名日志文件,例如log-error-2013-12-21.0.log -->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>2MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!-- 追加方式记录日志 -->
<append>true</append>
<!-- 日志文件的格式 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>===%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger Line:%-3L - %msg%n</pattern>
<charset>utf-8</charset>
</encoder>
<!-- 此日志文件只记录info级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>info</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!--日志异步到数据库 -->
<!--<appender name="DBAPPENDER" class="ch.qos.logback.classic.db.DBAppender">-->
<!--<connectionSource class="ch.qos.logback.core.db.DataSourceConnectionSource">-->
<!--<dataSource class="com.zaxxer.hikari.HikariDataSource">-->
<!--<driverClassName>com.mysql.jdbc.Driver</driverClassName>-->
<!--<jdbcUrl>jdbc:mysql://localhost:3306/albedo-new?useUnicode=true&characterEncoding=utf8&useSSL=false</jdbcUrl>-->
<!--<username>root</username>-->
<!--<password>123456</password>-->
<!--<poolName>HikariPool-logback</poolName>-->
<!--</dataSource>-->
<!--</connectionSource>-->
<!--<!– 此日志文件只记录info级别的 –>-->
<!--<filter class="ch.qos.logback.classic.filter.LevelFilter">-->
<!--<level>warn</level>-->
<!--<onMatch>ACCEPT</onMatch>-->
<!--<onMismatch>DENY</onMismatch>-->
<!--</filter>-->
<!--<!– 此日志文件只记录info级别的 –>-->
<!--<filter class="ch.qos.logback.classic.filter.LevelFilter">-->
<!--<level>error</level>-->
<!--<onMatch>ACCEPT</onMatch>-->
<!--<onMismatch>DENY</onMismatch>-->
<!--</filter>-->
<!--</appender>-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger Line:%-3L - %msg%n</pattern>
<!--<charset>GBK</charset>-->
</encoder>
</appender>
<logger name="com.minlia" level="DEBUG"/>
<logger name="org.springframework.data.mybatis" level="DEBUG"/>
<logger name="org.springframework.aop.aspectj" level="ERROR"/> <logger name="javax.activation" level="WARN"/>
<logger name="javax.mail" level="WARN"/>
<logger name="javax.xml.bind" level="WARN"/>
<logger name="ch.qos.logback" level="INFO"/>
<logger name="com.codahale.metrics" level="WARN"/>
<logger name="com.ryantenney" level="WARN"/>
<logger name="com.sun" level="WARN"/>
<logger name="com.zaxxer" level="WARN"/>
<logger name="io.undertow" level="WARN"/>
<logger name="net.sf.ehcache" level="WARN"/>
<logger name="org.apache" level="WARN"/>
<logger name="org.apache.catalina.startup.DigesterFactory" level="OFF"/>
<logger name="org.bson" level="WARN"/>
<logger name="org.hibernate.validator" level="WARN"/>
<logger name="org.hibernate" level="WARN"/>
<logger name="org.hibernate.ejb.HibernatePersistence" level="OFF"/>
<logger name="org.springframework.web" level="INFO"/>
<logger name="org.springframework.security" level="WARN"/>
<logger name="org.springframework.cache" level="WARN"/>
<logger name="org.thymeleaf" level="WARN"/>
<logger name="org.xnio" level="WARN"/>
<logger name="springfox" level="WARN"/>
<logger name="sun.rmi" level="WARN"/>
<logger name="liquibase" level="WARN"/>
<logger name="sun.rmi.transport" level="WARN"/> <logger name="jdbc.connection" level="ERROR"/>
<logger name="jdbc.resultset" level="ERROR"/>
<logger name="jdbc.resultsettable" level="INFO"/>
<logger name="jdbc.audit" level="ERROR"/>
<logger name="jdbc.sqltiming" level="ERROR"/>
<logger name="jdbc.sqlonly" level="INFO"/> <!--<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">-->
<!--<resetJUL>true</resetJUL>-->
<!--</contextListener>--> <springProfile name="production">
<root level="DEBUG">
<!--<appender-ref ref="FILEERROR"/>-->
<!--<appender-ref ref="FILEWARN"/>-->
<!--<appender-ref ref="FILEINFO"/>-->
<!--<appender-ref ref="DBAPPENDER"/>-->
<appender-ref ref="STDOUT"/> </root>
</springProfile> <springProfile name="dev">
<root level="DEBUG">
<!--<appender-ref ref="FILEERROR"/>-->
<!--<appender-ref ref="FILEWARN"/>-->
<!--<appender-ref ref="FILEINFO"/>-->
<!--<appender-ref ref="DBAPPENDER"/>-->
<appender-ref ref="CONSOLE"/> </root>
</springProfile> </configuration>

  

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- %m输出的信息,%p日志级别,%t线程名,%d日期,%c类的全名,%i索引【从数字0开始递增】,,, -->
<!-- appender是configuration的子节点,是负责写日志的组件。 -->
<!-- ConsoleAppender:把日志输出到控制台 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d %p (%file:%line\)- %m%n</pattern>
<!-- 控制台也要使用UTF-8,不要使用GBK,否则会中文乱码 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- RollingFileAppender:滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 -->
<!-- 以下的大概意思是:1.先按日期存日志,日期变了,将前一天的日志文件名重命名为XXX%日期%索引,新的日志仍然是demo.log -->
<!-- 2.如果日期没有发生变化,但是当前日志的文件大小超过1KB时,对当前日志进行分割 重命名-->
<appender name="demolog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>log/demo.log</File>
<!-- rollingPolicy:当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名。 -->
<!-- TimeBasedRollingPolicy: 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 活动文件的名字会根据fileNamePattern的值,每隔一段时间改变一次 -->
<!-- 文件名:log/demo.2017-12-05.0.log -->
<fileNamePattern>log/demo.%d.%i.log</fileNamePattern>
<!-- 每产生一个日志文件,该日志文件的保存期限为30天 -->
<maxHistory>30</maxHistory>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- maxFileSize:这是活动文件的大小,默认值是10MB,测试时可改成1KB看效果 -->
<maxFileSize>1KB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<!-- pattern节点,用来设置日志的输入格式 -->
<pattern>
%d %p (%file:%line\)- %m%n
</pattern>
<!-- 记录日志的编码:此处设置字符集 - -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- 控制台输出日志级别 -->
<root level="info">
<appender-ref ref="STDOUT" />
</root>
<!-- 指定项目中某个包,当有日志操作行为时的日志记录级别 -->
<!-- com.liyan为根包,也就是只要是发生在这个根包下面的所有日志操作行为的权限都是DEBUG -->
<!-- 级别依次为【从高到低】:FATAL > ERROR > WARN > INFO > DEBUG > TRACE -->
<logger name="com.liyan" level="DEBUG">
<appender-ref ref="demolog" />
</logger>
</configuration>

  关于配置log日志的输出路径的问题:配置一个property,然后filenamePattern添加上去就行了。

springboot的日志框架slf4j (使用logback输出日志以及使用)