简介
Java 日志框架众多——常用的有 java.util.logging
、log4j
、logback
、commons-logging
。logback
是 Log4j 框架的作者开发的新一代日志框架,它效率更高、能够适应诸多的运行环境,同时天然支持 SLF4J。默认情况下,Spring Boot 默认使用logback 来记录日志,并用 INFO
级别输出到控制台。新建一个 Spring Boot 项目在不配置的情况下,已经可以看到许 INFO
级别的日志输出到控制台了。
从上图可以看到,日志输出内容元素具体如下:
- 时间日期:精确到毫秒
- 日志级别:
ERROR、 WARN、INFO、DEBUG、TRACE
- 进程 ID
- 分隔符:
---
标识实际日志的开始 - 线程名:方括号括起来(可能会截断控制台输出)
- Logger 名:通常使用源代码的类名
- 日志内容
默认属性配置支持
Spring Boot 为我们提供了很多默认的日志配置,所以,只要将 spring-boot-starter-logging 作为依赖加入到当前应用的classpath,则“开箱即用”。下面介绍几种在 application.properties 就可以配置的日志相关属性。
控制台输出
日志级别从低到高分为 TRACE < DEBUG < INFO < WARN < ERROR < FATAL
,如果设置为 WARN
,则低于 WARN
的信息都不会输出。
Spring Boot 中默认配置 ERROR
、WARN
和 INFO
级别的日志输出到控制台。您还可以通过启动您的应用程序 –debug 标志来启用“调试”模式(开发的时候推荐开启),以下两种方式皆可:
- 在运行命令后加入
--debug
标志,如:$ java -jar springTest.jar --debug
- 在
application.yml
中配置debug: true
,该属性置为true的时候,核心 Logger(包含嵌入式容器、hibernate、spring)会输出更多内容,但是你自己应用的日志并不会输出为DEBUG
级别。
文件输出
默认情况下,Spring Boot 将日志输出到控制台,不会写到日志文件。如果要编写除控制台输出之外的日志文件,则需在 application.properties 中设置 logging.file 或 logging.path 属性。
- logging.file,设置文件,可以是绝对路径,也可以是相对路径。如:
logging.file=info.log
- logging.path,设置目录,会在该目录下创建spring.log文件,并写入日志内容,如:
logging.path=/var/log
如果只配置 logging.file,会在项目的当前路径下生成一个 xxx.log 日志文件。
如果只配置 logging.path,在 /var/log 文件夹生成一个日志文件为 spring.log
注:二者不能同时使用,如若同时使用,则只有logging.file生效
*默认情况下,日志文件的大小达到 10 MB 时会切分一次,产生新的日志文件,默认级别为:ERROR、WARN、INFO
级别控制
所有支持的日志记录系统都可以在 Spring 环境中设置记录级别(例如在 application.properties 中)格式为:logging.level.* = LEVEL
- logging.level:日志级别控制前缀,
*
为包名或 Logger 名 - LEVEL:选项
TRACE、DEBUG、INFO、WARN、ERROR、FATAL、OFF
举例:
-
logging.level.com.dudu=DEBUG
:com.huang 包下所有 class 以DEBUG
级别输出 -
logging.level.root=WARN
:root 日志以WARN
级别输出
自定义日志配置
由于日志服务一般都在 ApplicationContext 创建前就初始化了,它并不是必须通过 Spring 的配置文件控制。因此通过系统属性和传统的 Spring Boot 外部配置文件依然可以很好的支持日志控制和管理。
根据不同的日志系统,你可以按如下规则组织配置文件名,就能被正确加载:
- 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 特有的配置项。**
上面是默认的命名规则,并且放在 src/main/resources
下面即可。
虽然有默认的命名规则,但是如果你想针对不同运行环境使用不同的日志配置文件,也可以通过 loggin.config 来指定 logback 的配置文件名:
logging.config: classpath:loggin-confi.xml
配置文件详解
下面以一个简单的 logback.xml 例子来讲解 logback 的各个配置的作用:
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<contextName>logback</contextName>
<property name="log.path" value="E:\\test\\logback.log" />
<!--输出到控制台-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<!-- <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>-->
<encoder>
<pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!--输出到文件-->
<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>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="console" />
<appender-ref ref="file" />
</root>
<!-- logback为java中的包 -->
<logger name="com.dudu.controller"/>
<!--logback.LogbackDemo:类的全路径 -->
<logger name="com.dudu.controller.LearnController" level="WARN" additivity="false">
<appender-ref ref="console"/>
</logger>
</configuration>
configuration
- scan:当此属性设置为 true 时,配置文件如果发生改变,将会被重新加载,默认值为 true。
- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当 scan 为 true 时,此属性生效。默认的时间间隔为 1 分钟。
- debug:当此属性设置为 true 时,将打印出 logback 内部日志信息,实时查看 logback 运行状态。默认值为 false。
appender
appender 用来格式化日志输出节点,有俩个属性 name 和 class,class 用来指定哪种输出策略,常用就是控制台输出策略和文件输出策略。
encoder
encoder 表示对日志进行编码
-
%d{yyyy-MM-dd HH:mm:ss.SSS}
: 日志输出时间(精确到毫秒) -
%thread
: 输出日志的进程名字,这在Web应用以及异步任务处理中很有用 -
%-5level
: 日志级别,并且使用5个字符靠左对齐 -
%logger{36}
: 日志输出者的名字 -
%msg
: 日志消息 -
%n
: 平台的换行符
ThresholdFilter 为系统定义的拦截器,例如我们用 ThresholdFilter 来过滤掉
ERROR
级别以下的日志不输出到文件中。如果不用记得注释掉,不然你控制台会发现没日志~
contextName
每个 logger 都关联到 logger 上下文,默认上下文名称为 default
。但可以使用设置成其他名字,用于区分不同应用程序的记录。一旦设置,不能修改,可以通过 %contextName
来打印日志上下文名称。
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<contextName>TestProject</contextName>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!--%contextName的值为"TestProject"-->
<pattern>%contextName%d{yyyy-MM-dd HH:mm:ss} [%class:%line] - %m%n</pattern>
<charset>utf8</charset>
</encoder>
<!--日志输出级别-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
</appender>
<root level="info">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
property
用来定义变量值的标签, 有两个属性,name 和 value;其中 name 的值是变量的名称,value 的值时变量定义的值。通过定义的值会被插入到 logger 上下文中。定义变量后,可以使 ${}
来使用变量。
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="CONSOLE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss} [%class:%line] - %m%n" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!--引用property的值-->
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>utf8</charset>
</encoder>
<!--日志输出级别-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
</appender>
<root level="info">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
rollingPolicy
<fileNamePattern>logback.%d{yyyy-MM-dd}.log</fileNamePattern>
定义了日志的切分方式——把每一天的日志归档到一个文件中,<maxHistory>30</maxHistory>
表示只保留最近30天的日志,以防止日志填满整个磁盘空间。同理,可以使用 %d{yyyy-MM-dd_HH-mm}
来定义精确到分的日志切分方式。<totalSizeCap>1GB</totalSizeCap>
用来指定日志文件的上限大小,例如设置为 1GB 的话,那么到了这个值,就会删除旧的日志。如果想保留旧日志,可以使用 TimeBasedRollingPolicy 策略,后面会用到。
root
root 节点是必选节点,用来指定最基础的日志输出级别,只有一个 level 属性。
- level:用来设置打印级别,大小写无关:
TRACE、DEBUG、INFO、WARN、ERROR、ALL
和OFF
,不能设置为INHERITED
或者同义词NULL
。默认是DEBUG
。可以包含零个或多个元素,标识这个 appender 将会添加到这个 loger。
logger
<loger>
用来设置某一个包或者具体的某一个类的日志打印级别、以及指定 <appender>
。<loger>
仅有一个 name 属性,一个可选的 level 和一个可选的 addtivity 属性。
-
name
:用来指定受此 loger 约束的某一个包或者具体的某一个类。 -
level:
用来设置打印级别,大小写无关:TRACE、DEBUG、INFO、WARN、ERROR、ALL
和OFF
,还有一个特俗值INHERITED
或者同义词NULL
,代表强制执行上级的级别。如果未设置此属性,那么当前 loger 将会继承上级的级别。 -
addtivity
:是否向上级 loger 传递打印信息。默认是 true。
多环境日志输出
据不同环境(prod:生产环境,test:测试环境,dev:开发环境)来定义不同的日志输出,在 logback-spring.xml
中使用 springProfile
节点来定义,方法如下:
<!-- 测试环境+开发环境. 多个使用逗号隔开. -->
<springProfile name="test,dev">
<logger name="com.dudu.controller" level="info" />
</springProfile>
<!-- 生产环境. -->
<springProfile name="prod">
<logger name="com.dudu.controller" level="ERROR" />
</springProfile>
可以在 yml 或 properties 文件中指定 profile,也可以启动服务的时候指定 profile (如不指定使用默认),如指定 prod 的方式为:
java -jar xxx.jar –spring.profiles.active=prod
指定日志颜色
用过 spring boot 的人都知道,spring boot 启动的时候的日志输出是有颜色的。这是由于 spring boot 默认的 logback 配置了日志的输出颜色。logback 提供了很多默认的颜色(black,red,green 等),如果想将日志设置成对应的颜色,只需将输出内容放到 %颜色名()
括号中就可以了,如:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--时间的输入颜色为红色-->
<property name="CONSOLE_LOG_PATTERN" value="%red(%d{yyyy-MM-dd HH:mm:ss}) [%class:%line] - %m%n" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!--引用 property 的值-->
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>utf8</charset>
</encoder>
<!--日志输出级别-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
</appender>
<root level="info">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
更多的颜色可以到 logback 中查看:https://logback.qos.ch/manual/layouts.html#coloring
完整配置示例
最后贴出一个我认为比较好的配置,大家只需要把该文件命名为 logback-spring.xml
然后放到 spring boot 工成的 resources 目录下就能用啦(因为做了多环境配置,记得指定 spring.profile.active 属性哦~)。该日志采用了与 spring boot 默认的配置一样的颜色搭配,info 为绿色,warn 为黄色,error 为红色。而且日志按天跟大小分割存放到指定目录下。
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<contextName>HuangXiaoyu</contextName>
<property name="log.home" value="F:\\logs"/>
<!-- 彩色日志 -->
<!-- 彩色日志依赖的渲染类 (INFO:绿色 WARN:黄色 ERROR:红色)-->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<!-- 彩色日志格式 -->
<property name="CONSOLE_LOG_PATTERN"
value="%d{yyyy-MM-dd HH:mm:ss.SSS} %clr(%5p) %magenta(${PID:- }) --- [%15.15thread] %cyan(%-40.40logger{39}) : %m%n"/>
<!-- Console 输出设置 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>utf8</charset>
</encoder>
<!--日志输出级别-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
</appender>
<springProfile name="prod">
<!-- 文件保存日志的相关配置 ERROR -->
<appender name="ERROR-OUT" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 保存日志文件的路径 -->
<file>${log.home}/error.log</file>
<!-- 日志格式 -->
<encoder>
<pattern>%d{HH:mm:ss} [%class:%line] : %m%n</pattern>
</encoder>
<!-- 日志级别过滤器 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.home}/error/%d{yyyy-MM-dd}-error.%i.log</fileNamePattern>
<!-- 最大保存时间:30天-->
<maxHistory>30</maxHistory>
<maxFileSize>10MB</maxFileSize>
</rollingPolicy>
</appender>
<!-- 文件保存日志的相关配置 INFO,按时间跟大小进行分割 -->
<appender name="INFO-OUT" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 保存日志文件的路径 -->
<file>${log.home}/info.log</file>
<!-- 日志格式 -->
<encoder>
<pattern>%d{HH:mm:ss} [%class:%line] : %m%n</pattern>
</encoder>
<!-- 日志级别过滤器 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
</filter>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.home}/info/%d{yyyy-MM-dd}-info.%i.log</fileNamePattern>
<!-- 最大保存时间:30天-->
<maxHistory>30</maxHistory>
<maxFileSize>10MB</maxFileSize>
</rollingPolicy>
</appender>
</springProfile>
<!-- 基于info处理日志:具体控制台或者文件对日志级别的处理还要看所在appender配置的filter,如果没有配置filter,则使用root配置 -->
<springProfile name="prod">
<root level="info">
<appender-ref ref="STDOUT"/>
<appender-ref ref="INFO-OUT"/>
<appender-ref ref="ERROR-OUT"/>
</root>
</springProfile>
<springProfile name="dev,test">
<!-- 输出mybatis的sql语句,没有这句就无法输出mybatis的sql语句,name属性指定到要输出日志的dao,即mybatis要代理的dao -->
<logger name="com.huang.mmall.dao" level="DEBUG"/>
<root level="info">
<appender-ref ref="STDOUT"/>
</root>
</springProfile>
</configuration>