一、日志框架简介
二、
- 如何引入日志?
- 日志输出格式以及输出方式如何配置?
- 代码中如何使用?
Spring Boot在所有内部日志中使用Commons Logging,但是默认配置也提供了对常用日志的支持,如:Java Util Logging,Log4J, Log4J2和Logback。每种Logger都可以通过配置使用控制台或者文件输出日志内容。
默认情况下,springboot用logback记录日志信息,并用info级别输出到控制台。
日志信息包含:
日期时间:精确到毫秒
日志输出级别:ERROR, WARN, INFO, DEBUG or TRACE
进程ID:
线程名:方括号汇中的内容
Logger名:通常使用源代码的类名
日志内容:
一、logback的应用
1.引入jar包或添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
若maven添加如上依赖,则springboot应用将自动使用logback作为当前应用日志框架。
但实际无需单独添加该依赖,在spring-boot-starter依赖中包含了该日志框架。
2.在项目application.properties文件中配置使用
日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出。
2.1控制台输出
2.1.1在运行命令后加入--debug标志,如:$ java -jar springTest.jar --debug
2.1.2在application.properties中配置debug=true,该属性置为true的时候,核心Logger(包含嵌入式容器、hibernate、spring)会输出更多内容,但是你自己应用的日志并不会输出为DEBUG级别。
debug=true
2.2文件输出
默认情况下,spring boot将日志输出到控制台,若要输出日志到文件,需要在配置文件application.properties中配置logging.file或logging.path。
- logging.file:指定日志文件,可以是相对路径(即项目根目录下),也可以是绝对路径,如:logging.file=my.log
- logging.path:设置目录,会在该目录(即生成日志文件在当前项目所在的磁盘的根目录下生成指定的文件夹)下创建spring.log文件,并写入日志内容,也可以是绝对路径。如:
logging.path=/var/log
如果只配置 logging.file,会在项目的当前路径下生成一个 xxx.log 日志文件。
如果只配置 logging.path,在 /var/log文件夹生成一个日志文件为 spring.log
注:二者不能同时使用,如若同时使用,则只有logging.file生效
2.3日志级别控制
格式为:’logging.level.* = LEVEL’
-
logging.level
:日志级别控制前缀,*
为包名或Logger名 -
LEVEL
:选项TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF
举例:
- logging.level.com.sxd=DEBUG com.sxd包下所有class以DEBUG级别输出,包括其优先级以上
- logging.level.root=WARN root日志以WARN级别输出,包括其优先级以上
3.完全控制和解析日志配置(自定义日志)
3.1提出问题:
在前面的学习中可以看到日志都是统一的格式,统一的级别,或一致的文件路径,若想自定义配置日志,如
- ①例如:我想在控制台输出的日志格式是这样的,但是在文件中能不能以另外一种格式输出?
- ②例如:我的日志文件输出,能不能自己控制文件的大小,文件名,日志文件总共多少就得清理?
- ③例如:能不能在不同的环境下,有不同的日志操作,比如在生产环境下,我的Service层的日志不会被打印,但是在开发环境下就要被打印出来
- 。。。。。。
3.2分析问题
由于日志服务一般都在ApplicationContext创建前就初始化了,它并不是必须通过Spring的配置文件控制。因此通过系统属性和传统的Spring Boot外部配置文件依然可以很好的支持日志控制和管理。
3.2.1默认命名规则(问题1:外部的日志配置文件应该叫什么名字呢?)
根据不同的日志系统,可以按如下规则组织配置文件名,就能被正确加载:
- Logback:logback-spring.xml, logback-spring.groovy, logback.xml, logback.groovy
- Log4j:log4j-spring.properties, log4j-spring.xml, log4j.properties, log4j.xml
- Log4j2:log4j2-spring.xml, log4j2.xml
- JDK (Java Util Logging):logging.properties
注意:Spring Boot官方推荐优先使用带有-spring的文件名作为日志配置(如使用logback-spring.xml,而不是logback.xml),命名为logback-spring.xml的日志配置文件,spring boot可以为它添加一些spring boot特有的配置项【特有的就是spring boot的profile多环境配置】
3.2.2存储路径(问题2:日志配置文件应该放在哪里呢?)
存放在src/main/resources下
3.2.3自定义日志文件名(问题3:那不使用logback-spring.xml名字,使用自己定义的日志配置文件名行不行?)
在application.properties配置文件中通过logging.config属性指定自定义的名字即可。
logging.config=classpath:logging-自定义.xml
虽然一般并不需要改变配置文件的名字,但是如果你想针对不同运行时Profile使用不同的日志配置,这个功能会很有用。
3.2.4多环境配置不同日志(问题4:那我想使用spring boot的profile多环境配置,日志配置文件应该用什么名字?使用流程是怎么样?)
①:日志配置文件名应该定义成logback-spring.xml。
②:在日志配置文件中,使用<springProfile name="dev"> </springProfile>标签来包住想要在这种环境下使用的配置。
③:最后application.properties配置文件中,选择激活哪一种或哪几种环境即可(spring.profiles.active)
注意:在没有设置profile的情况下,一般启动情况下,控制台打印出的日志都能看到这么一句话:
4.代码中使用
要在代码中使用日志的话,仅需要在类上添加
Logger logger = LoggerFactory.getLogger(this.getClass());
然后就可以在需要日志输出的地方通过logger.info()等方法输出。
二、基本的logback-spring.xml文件解析
<?xml version="1.0" encoding="UTF-8"?>
<!--
scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。
debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。-->
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 属性:设置上下文名称,每个logger都关联到logger上下文,默认上下文名称为“default”。-->
<contextName>logback</contextName>
<!--property定义变量值,通过该属性定义的值会被插入到logger上下文中。定义变量后,可以通过“${}”来使用变量。-->
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
<property name="log.path" value="D:\\test\\log\\logback.log" />
<!--appender用来格式化日志输出节点,有俩个属性name和class,
class用来指定哪种输出策略,常用就是控制台输出策略和文件输出策略。-->
<!--输出到控制台-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<!--ThresholdFilter为系统定义的拦截器,例如我们用ThresholdFilter来过滤掉ERROR级别以下的日志不输出到文件中。如果不用记得注释掉,不然你控制台会发现没日志~-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<encoder><!--<encoder>表示对日志进行编码-->
<!--<pattern>%d %p (%file:%line\)- %m%n</pattern>-->
<!--格式化输出:%d:表示日期 %thread:表示线程名 %-5level:级别从左显示5个字符宽度 %msg:日志消息 %n:是换行符-->
<pattern>控制台-%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger - %msg%n</pattern>
<charset>GBK</charset>
</encoder>
</appender>
<!--输出到文件,RollingFileAppender用于切分文件日志-->
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--定义了日志的切分方式——把每一天的日志归档到一个文件中-->
<fileNamePattern>logback.%d{yyyy-MM-dd}.log</fileNamePattern>
<!--表示只保留最近30天的日志,以防止日志填满整个磁盘空间-->
<maxHistory>30</maxHistory>
<!--用来指定日志文件的上限大小,例如设置为1GB的话,那么到了这个值,就会删除旧的日志-->
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
<encoder>
<!--格式化输出:%d:表示日期 %thread:表示线程名 %-5level:级别从左显示5个字符宽度 %msg:日志消息 %n:是换行符-->
<pattern>文件记录-%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
<charset>GBK</charset>
</encoder>
</appender>
<!--root节点是必选节点,用来指定最基础的日志输出级别-->
<root level="info">
<!--<root>可以包含零个或多个<appender-ref>元素,标识这个appender将会添加到这个logger-->
<appender-ref ref="console" />
<appender-ref ref="file" />
</root>
<!--<logger>用来设置某一个包或者具体的某一个类的日志打印级别、以及指定<appender>,
name用来指定此logger约束的包或类,其中additivity表示向上级传递打印消息,默认为true-->
<!--若不指定level和additivity,则继承root的级别和输出打印消息,反之,则按照自己的级别和输出打印消息-->
<logger name="com.bj.controller"/>
<!--若additivity为true,则会输出两次打印信息,本身一次,传递root一次-->
<logger name="com.bj.util.LogTestController" level="WARN" additivity="false">
<appender-ref ref="console" />
</logger>
</configuration>
测试:
@RestController
public class TestController {
Logger logger = LoggerFactory.getLogger(this.getClass());
@RequestMapping("/index")
public String index(){
System.out.println("进入TestController日志控制中心----》》》");
logger.trace("日志输出TestController:trace[所有痕迹]");
logger.debug("日志输出TestController:debug[debug调试]");
logger.info("日志输出TestController:info[信息级别]");
logger.warn("日志输出TestController:warn[警告级别]");
logger.error("日志输出TestController:error[错误级别]");
return "ddddd";
}
}
启动并访问后,控制台输出日志如下,根据logback-spring.xml配置文件中的配置,可知该信息并不是logger本身打印,而是root打印,文件中同时也有对应的打印信息。
进入TestController日志控制中心----》》》
����̨-2019-01-15 11:33:08 [http-nio-8080-exec-4] INFO com.bj.study.springboot.controller.TestController - ��־���TestController��info[��Ϣ����]
����̨-2019-01-15 11:33:08 [http-nio-8080-exec-4] WARN com.bj.study.springboot.controller.TestController - ��־���TestController��warn[���漶��]
����̨-2019-01-15 11:33:08 [http-nio-8080-exec-4] ERROR com.bj.study.springboot.controller.TestController - ��־���TestController��error[���?�]
@RestController
public class LogTestController {
Logger logger = LoggerFactory.getLogger(this.getClass());
@RequestMapping("/logtest")
public String logTest(){
System.out.println("进入LogTestController日志控制中心----》》》");
logger.trace("日志输出LogTestController:trace[所有痕迹]");
logger.debug("日志输出LogTestController:debug[debug调试]");
logger.info("日志输出LogTestController:info[信息级别]");
logger.warn("日志输出LogTestController:warn[警告级别]");
logger.error("日志输出LogTestController:error[错误级别]");
return "logTest";
}
}
访问该链接,控制台输出
进入LogTestController日志控制中心----》》》
����̨-2019-01-15 11:41:05 [http-nio-8080-exec-6] WARN com.bj.study.springboot.util.LogTestController - ��־���LogTestController��warn[���漶��]
����̨-2019-01-15 11:41:05 [http-nio-8080-exec-6] ERROR com.bj.study.springboot.util.LogTestController - ��־���LogTestController��error[���?�]
根据logback-spring.xml配置文件中的配置,该信息为logger本身打印,同时无需传递到上级root,该logger指定输出到了控制台,所以文件中并没有输出日志信息。
三、使用日志过程中发现的问题
1.日志乱码问题
从上一步中测试输出的日志信息中,可以看到有乱码现象,但查看文件中却没有乱码。
分析发现
- 1).打印的“进入Controller日志控制中心----》》》”字样可以看出,至少代码本身和IDE环境的编码方式没有任何的关系;
2).打印出来的日志是logback-spring.xml文件起作用之后,显示在控制台的,而日志文件打开后,看到 不同的文本编辑器打开是不一样的。
结论:
- 1).可以肯定,这个是logback-spring.xml自定义配置起作用之后导致的;
- 2).日志文件中并不是不乱码,而是不同的编辑软件的默认编码方式是不一样的。所以才会有的乱码,有的并不乱码。
解决方案:
将logback-spring.xml配置文件中的<encode>标签下的<charset>的值改为utf-8即可。
2.启动项目时,日志没有颜色区分
没有添加logback-spring.xml文件前
添加后日志输出
解决方案:
在配置文件中修改:
<!--输出到控制台-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<encoder>
<!--<pattern>控制台-%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger - %msg%n</pattern>-->
<pattern>%black(控制台-) %red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger) - %cyan(%msg%n)</pattern>
<charset>utf-8</charset>
</encoder>
</appender>
也可以通过定义一个变量,然后在该位置调用即可
则效果变为:
3.日志使用自定义的logback-spring.xml文件后,application.properties中关于日志的相关配置还会起作用么
在已有项目的基础上,在配置文件中新增如下信息
logging.file=d:/test/my.log
logging.level.root=trace
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} [%p][%c][%M][%L] ->%m%n
logging.pattern.file==%d{yyyy-MM-dd HH:mm:ss} [%p][%c][%M][%L] ->%m%n
然后启动项目,访问。
【发现,日志级别是按照自定义的logback-spring.xml文件中的配置进行的】
【发现并未在d盘下生成application.properties中定义的生成日志文件】,但logback-spring.xml中定义的文件中却是有对应的日志信息。同时增加了很多其他的日志信息。
结论:
日志使用自定义的logback-spring.xml文件后,application.properties中关于日志的相关配置一些硬性的配置,例如生成日志文件等不会被影响,但是如果随意配置的话,会影响到自定义日志配置文件中的配置。
所以,配置了自定义的日志配置文件logback-spring.xml之后,就不用在application.properties进行配置了,不然多此一举,产生不必要的影响。