SpringBoot logback日志集成总结

原创
03/07 16:21
阅读数 411

参考资料:https://mp.weixin.qq.com/s/irefLUeUAb_5OVvPPHAWCA

参考公众号:享学课堂online

什么是日志门面和日志实现?

  • 日志门面:是日志实现的抽象层。
  • 日志实现:具体的日志功能的实现。
  • 常用日志门面 :JCL、SLF4j、jboss-logging
  • 常用日志实现:Log4j、 JUL(java.util.logging)、 Log4j2、 Logback

Springboot默认使用SLF4j+Logback,默认打印机info级别日志。

一般使用方式

一般使用方式,需要在需要在每个类中创建一个 Logger对象,并且使用当前类的类名来创建。使用类名创建的logger的作用就是方便我们找到异常是在哪个类中,进行锁定。 `

@SpringBootTest 
public class OlduseTest { private static Logger logger = LoggerFactory.getLogger(OlduseTest.class);
	@Test
	public void useLog() {
		logger.debug("=====debug====");
		logger.info("=====info====");
		logger.warn("=====warn====");
		logger.error("=====error====");
	}
} 








注解使用方式

安装lombok插件,并且添加lombok依赖

<dependency>  
<groupId>org.projectlombok</groupId>  
<artifactId>lombok</artifactId>  
</dependency>








直接使用log.XX打印日志,使用{}作为占位符,高性能拼接打印字符串

@SpringBootTest
@Slf4j
public class LombokuseTest {
	@Test
	public void lombokuseTest() {
		log.debug("=====debug====");
		log.info("=====info===={}","Lombok");
		log.warn("=====warn====");
		log.error("=====error====");
	}
}







日志配置

logback-spring.xml文件配置,Spring Boot官方推荐优先使用带有-spring的文件名作为你的日志配置(如使用logback-spring.xml,而不是logback.xml),如果我们想自定义名字,可以在 application.yml中通过logging.config=classpath:/xxx.xml等方式配置。

<?xml version="1.0" encoding="UTF-8"?>
<!--根节点configuration包含属性:
    scan:当此属性设置为 true 时,配置文件如果发生改变,将会被重新加载,默认true 。
    scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。
	当 scan 为 true 时,此属性生效。默认的时间间隔为1分钟。-->
<configuration debug="false">
    <!--子节点root,必选节点,用来指定最基础的日志输出级别,只有一个level属性。
		level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
		不能设置为INHERITED或者同义词NULL。默认是DEBUG。
		可以包含零个或多个元素,标识这个appender将会添加到这个loger。-->
    <root level="INFO">
        <appender-ref ref="STDOUT" />
        <appender-ref ref="FILE" />
    </root>
	<!--子节点contextName,每个logger都关联到logger上下文,默认上下文名称为“default”。
		但可以使用设置成其他名字,用于区分不同应用程序的记录。一旦设置,不能修改。
		可以通过 %contextName 来打印日志上下文名称,一般来说我们不用这个属性
	<contextName></contextName>-->
	<!--子节点property,用来定义变量值的标签, 有两个属性,name和value;
		其中name的值是变量的名称,value的值时变量定义的值。
		通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。
		此处定义的是日志的存储地址-->
    <property name="LOG_HOME" value="../logs" />
	<!--子节点appender,appender用来格式化日志输出节点,有俩个属性name和class,class用来指定哪种输出策略,
		常用就是控制台输出策略和文件输出策略。控制台输出ConsoleAppender,文件输出一般使用RollingFileAppender-->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <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>
    <!--子节点logger,loger 用来设置某一个包或者具体的某一个类的日志打印级别、以及指定appender。
		loger仅有一个name属性,一个可选的level和一个可选的 addtivity 属性。
		name :用来指定受此loger约束的某一个包或者具体的某一个类。
		level :用来设置打印级别,大小写无关
		addtivity :是否向上级loger传递打印信息。默认是true。-->
    <logger name="com.apache.ibatis" level="TRACE"/>
	<!--子节点springProperty 可引用spring配置文件中的变量-->
	<springProperty name="logHome" source="log.home" defaultValue=""/>
</configuration>






appender节点详解

<!-- 输出到文件:滚动(切割)策略 -->
<appender name="FILE"  class="ch.qos.logback.core.rolling.RollingFileAppender">
		 <!--日志名称,如果没有File 属性,那么只会使用FileNamePattern的文件路径规则 如果同时有<File>和<FileNamePattern>,那么当天日志是<File>,
				明天会自动把今天的日志改名为今天的日期。即,<File> 的日志都是当天的。 -->
        <File>${logHome}/logs/${logname}-info.log</File>
	    <!--定义过滤器,实现不同日志级别的输出,如下实现了DEBUG级别日志的过滤-->
	    <filter class="ch.qos.logback.classic.filter.LevelFilter">
			<!--过滤DEBUG级别日志-->
			<level>DEBUG</level>
			<!--如果匹配则允许-->
			<onMatch>ACCEPT</onMatch>
			<!--如果不匹配则禁止-->
			<onMismatch>DENY</onMismatch>
		</filter>
	     <!--根据时间进行滚动。可以指定每天,每周或每月进行一次滚动-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--文件名-->
            <FileNamePattern>${LOG_HOME}/test.log.%d{yyyy-MM-dd}.log</FileNamePattern>
			<!--单个文件大小-->
			<maxFileSize>500MB</maxFileSize>
			<!--保留的归档文件个数-->
			<maxHistory>10</maxHistory>
			<!--所有归档文件的总大小-->
			<totalSizeCap>5GB</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>
			<!--编码格式-->
			<charset>UTF-8</charset>
        </encoder>
</appender>






appender还可以输出日志到数据库"ch.qos.logback.classic.db.DBAppender",需参照ch.qos.logback.classic.db.scrip包下的相关建表脚本建立相关表

 <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
        <connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">
            <driverClass>com.mysql.cj.jdbc.Driver</driverClass>
            <url>jdbc:mysql://127.0.0.1:3306/log?serverTimezone=UTC</url>
            <user>xxx</user>
            <password>xxx</password>
        </connectionSource>
</appender>






输出到Logstash"net.logstash.logback.appender.LogstashTcpSocketAppender"

<appender name="logstash" class="net.logstash.logback.appender.LogstashTcpSocketAppender"> 
	<destination>127.0.0.1:4560</destination> 
	<encoder class="net.logstash.logback.encoder.LogstashEncoder"\> 
		<includeContext>false</includeContext> 
		<customFields>{"appname": "cs-elk", "server": "${HOSTNAME}"}</customFields> 
	</encoder> 
</appender>






多环境日志配置

<!--springProperty节点,引用springboot的配置文件变量,通过该变量控制日志打印级别-->
<springProperty name="loglevel" source="log.level"/>
<root level="${loglevel}">
        <appender-ref ref="STDOUT" />
        <appender-ref ref="FILE" />
</root>
<!--springProfile节点,获取到spingboot配置文件中的spring.profiles.active变量值,可以不同环境控制不同输出方式-->
<!--生产输出到文件-->
<springProfile name="prod">
	<root level="${loglevel}">
		<appender-ref ref="FILE" />
	</root>
</springProfile>
<!--开发输出到控制台和文件-->
<springProfile name="dev"/>
	<root level="${loglevel}">
        <appender-ref ref="STDOUT" >
        <appender-ref ref="FILE" />
	</root>
</springProfile>





Springboot统一日志处理原理

问题:springboot实际开发中我们会引入其他框架的starter,而不同的starter会有不同的日志框架,如log4j、logback,我们能不能做到在项目中仅引入一个统一的日志框架呢?

Slf4j说明

前面说过,要使用日志需要选择一个日志门面和一个日志实现,Springboot默认使用的日志门面是slf4j,slf4j输出的过程如下图: slf4j输出过程

从图中可以看到,应用程序调用了slf4j的api接口以后,具体的实现则是由slf4j日志门面找到对应的日志的系统来实现日志输出。

Slf4j如何解决多框架日志不统一

slf4j官方给的方案 slf4j官方多日志统一方案

从图中我们可以看出来,官方的方案是针对不同的日志框架,开发了一套适配兼容的框架与之对应,使用这些兼容jar来替代原来的日志框架即可,例如log4j日志框架,与之对应的就是log4j-over-slf4j.jar,并且常见的日志框架,slf4j团队都实现了一套与之对应的基于slf4j的兼容框架,关系如下

日志框架 slf4j兼容框架
log4j log4j-over-slf4j
commons logging jcl-over-slf4j
java.util.logging jui-to-slf4j

SpringBoot如何处理日志关系

在使用SpringBoot的时候,我们会发现官方默认使用的是 spring‐boot‐starter‐logging这个starter来引入日志系统的,我们展开该依赖的依赖图,如下: springboot日志处理关系图

可以看到spring‐boot‐starter‐logging这个starter中,引入了四个日志实例的依赖,分别是logback和我们前面提到的日志兼容jar的依赖,并且最终引入了slf4j的日志门面的依赖,实现了统一日志处理。

这些日志兼容包的包名与原来的日志框架的包名完全一样,并且完全按照slf4j的方式实现了一套和以前一样的API,这样依赖这些日志框架的开源框架在运行的时候查找对应包名下的class也不会报错,但熟悉java类加载机制的都知道,两个jar的包名以及使用的class都一样的话,加载会出现异常,我们进入spring‐boot‐starter‐logging的pom依赖中一探究竟,最后在maven依赖中发现了端倪,如Spring框架使用的是commons-logging,而在spring-boot-starter-logging中,将spring的日志依赖排除

这样spring框架在运行时使用的时候,使用的就是兼容jar中的日志实例了,SpringBoot成功的完成了一次日志系统统一的偷天换日操作。

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部