Spring boot使用Commongs Logging进行多有内部日志记录,但保留底层日志实现。为Java Util Logging、Log4j2和Logback提供了默认配置。每种情况下,记录器都预先配置为使用控制台输出,并且提供可选的文件输出。
默认情况下,如果使用Starters,就使用Logback进行日志记录。还包括适当的Logback路由,以确保使用java Util Logging、Commons Logging、Log4j或SLF4J的依赖库都能正常工作。
Logback日志
在Spring boot框架中,默认使用的是Logback日志。
1.Logback简介
Logback的体系非常强大,提供了3个模块供使用:
- logback-core:属于Logback的基础模块,是其他两个模块的基础
- logback-classic:可以看作Log4j的改进版本,同时logback-classic自身实现了SLF4JAPI,使开发者可以在Logback框架与其他日志框架(如Log4j或java.util.logging)之间自由切换
- logback-access:与Servlet容器(如tomcat、jetty)集成,已提供HTTP访问日志功能
2.日志格式
Spring boot项目启动后,默认可以看到如下所示的日志:
从上图可以看出,Spring的logo部分是spring boot框架自带的,日志部分大致分为如下格式:
- 时间日期:显示日志的打印时间,精确到毫秒
- 日志级别:日志级别分为FATAL、ERROR、WARN、INFO、DEBUG、TRACE
- 进程ID:当前应用对应的PID
- 分隔符:用来区分实际日志消息的开始
- 线程名称:括在方括号中(可能会截断控制台输出)
- 记录器名称:一般使用类名
- 日志内容:日志输出的具体内容
3.控制台输出
在spring boot默认应用日志配置中,会将日志 默认输出到控制台中。在默认情况下,只会记录ERROR-level、WRAN-level和INFO-level级别的日志消息。也可以指定日志级别进行日志输出,如果指定了日志级别,那么只会对应输出高于指定级别的日志信息。Spring boot默认提供了调试模式,启动调试模式有两种方式:
- 启动JAR模式:在启动JAR的时候通过使用--debug标志启动应用程序调试模式
java -jar myapp.jar --debug
- 在配置文件中的配置:在application.properties或者application.yml中配置属性debug=true
同时,默认日志提供彩色日志输出,如果终端支持ANSI,那么在默认设置下,TRACE、DEBUGE和INFO级别为绿色,WARN级别为黄色,ERROR和FATAL级别为红色。
4.日志文件输出
默认情况下,Spring boot只会将日志消息打印到控制台,并不会将日志写入日志文件。在实际项目中,需要日志文件来分析程序。只需在application.properties文件或application.yml文件内设置logging.file或logging.path属性即可
- logging.file:设置日志文件,这里可以设置文件的绝对路径,也可以设置文件的相对路径,如:logging.file=test.log
- logging.path:设置日志目录,在设置好目录后,会设置目录文件夹下创建一个sprin.log,如设置logging.path=/User/log
上述两个属性中,如果只设置一个,那么spring boot应用会默认读取该配置;如果同时设置,就只有logging.file会生效。
Spring boot应用日志文件输出与控制台内容一致,在日志文件达到10MB的时候,会自动分隔日志文件,默认情况下会记录ERROR-level、WARN-level和INFO-level消息。日志文件可以通过设置logging.file.max-size属性更改大小限制。
5.日志级别
所有受支持的日志记录系统都可以通过使用TRACE、DEBUGE、INFO、WARN、ERROR、FATAL或OFF之一来在Spring中设置记录器级别,如下几种格式:
- logging.level.root=WARN:root日志以WARN级别输出消息。
- logging.level.com.spring=DEBUG:com.springboot包下的类以DEBUG级别输出
另外,也可以设置日志组来批量设置日志级别,比如设定com.springboot.controller和com.springboot.service为同一组(包与包之间用英文格式的逗号分隔),如下代码所示:
logging.group.springboot=com.springboot.cpmtroller,com.springboot.service
然后设置springboot组日志级别为TRACE,如下代码所示:
logging.level.springboot = TRACE
springboot默认的两个日志组:
logging.group.web = org.springframework.core.codec,org.springframework.http,org.springframework.web
logging.group.sql = org.springframework.jdbc.core,org.hibernate.SQL
6.日志配置
除了上面介绍的配置属性外,还有很多属性可以使用:
- logging.exception-conversion-word:记录异常时使用的转换字
- logging.file:设置日志文件
- logging.file.max-size:最大日志文件大小
- logging.config:日志配置
- logging.file.max-history:最大归档文件数量
- logging.path:日志文件目录
- logging.pattern.console:在控制台输出的日志模式
- logging.pattern.dateformat:日志格式内的日期格式
- logging.pattern.file:默认使用日志模式
- logging.pattern.level:日志级别
- PID:当前继承ID
7.基于XML配置日志
Spring boot默认支持通过XML配置自定义日志格式及输出,并且在ApplicationContext创建前就已经进行了初始化。在Spring boot默认使用的Logback中,可以通过在src/main/resources文件夹下定义logback.xml或logback-spring.xml作为日志配置
官方推荐优先使用带有-spring的文件名作为日志配置(如使用logback-spring.xml),因为如果命名为logback-spring.xml日志配置,就可以在日志输出的时候引入一些Spring boot特有的配置项。也可以支持自定义的日志配置,比如在application.properties或application.yml中配置logging.config=classpath:logback-config.xml,就会读取logback-config.xml配置对日志进行输出。
1.控制台输出日志
首先在src/main/resources目录下创建一个logback-spring.xml,输出到控制台,在配置文件中设置入下内容:
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%date %-5level [%thread] %logger{80} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- 控制台输出日志级别 -->
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
在上述pattern标签中的内容都对应日志相关的信息,分别如下:
- %date:日志输出时间,也可以用%d表示,同时可以用{yyyy-MM-dd HH:mm:ss.SSS}的形式对日志的输出时间进行格式优化
- %thread:输出日志的进程名字
- %-5level:日志级别,并且使用5个字符靠左对齐,也可以使用%p输出日志级别
- %logger{80}:日志输出者的名字
- %msg:日志消息
- %n:平台的换行符
- %c:用来在日志上输出类的全名
这里需要将编码格式设置为UTF-8,避免中文乱码
在root标签内设置日志级别,效果等同于在配置文件中设置logging.pattern.level
2.彩色日志输出
启动项目后,可以看得到日志对应输出,但是日志并没有颜色。修改配置文件:
<configuration>
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
<conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- 控制台输出日志级别 -->
<root level="debug">
<appender-ref ref="STDOUT" />
<appender-ref ref="DEBUG_FILE" />
</root>
</configuration>
3.日志文件输出
<configuration>
<property name="log.path" value="/Users/springboot/logs/testLog" />
<!-- 时间滚动输出 level为 DEBUG 日志 -->
<appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_debug.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志归档 -->
<fileNamePattern>${log.path}/debug/log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>50MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>30</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录debug级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>debug</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 控制台输出日志级别 -->
<root level="debug">
<appender-ref ref="DEBUG_FILE" />
</root>
</configuration>
- file:日志文件位置
- maxFileSize:设置最大日志文件大小
- maxHistory:只保留最近30天的日志,防止日志过多占用磁盘
- fileNamePattern:指定精确到分的日志切分方式
- filter:标签中的level设置日志级别
4.输出指定包文件日志
Logback可以指定输出某个包下的类的日志。
<configuration>
<property name="log.path" value="/Users/springboot/logs/testLog" />
<!-- 时间滚动输出 level为 DEBUG 日志 -->
<appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_debug.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志归档 -->
<fileNamePattern>${log.path}/debug/log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>50MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>30</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录debug级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>debug</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 控制台输出日志级别 -->
<root level="debug">
<appender-ref ref="DEBUG_FILE" />
</root>
</configuration>
<logger name="com.springboot" level="DEBUG">
<appender-ref ref="DEBUG_FILE" />
</logger>
Log4j 2 日志
1.Spring Boot使用Log4j 2
引入依赖:
这里额外引入了disruptor依赖,用于解决Log4j 2 日志版本较低报错的问题。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>3.4.2</version>
</dependency>
2.控制台输出
在src/main/resources文件夹下创建log4j2-spring.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Properties>
<Property name="LOG_PATTERN">%d{yyyy-MM-dd HH:mm:ss:SSS} - %-5level - %pid - %t - %c{1.}:%L - %m%n</Property>
</Properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT" follow="true">
<ThresholdFilter level="trace" onMatch="ACCEPT" onMismatch="DENY" />
<PatternLayout pattern="${LOG_PATTERN}"/>
</Console>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
其中:
- Property:用于配置自定义属性,name是属性名称
- Appenders:用于定义输出日志类型
- Concsole:用于配置输出到控制台的配置
- ThresholdFilter:定义输出的日志级别
- PatternLayout:输出日志的格式
- Loggers:在这里引入Appenders才能使对应Appenders生效
- AppenderRef:定义生效的Appenders
3.日志文件输出
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Properties>
<Property name="LOG_PATTERN">%d{yyyy-MM-dd HH:mm:ss:SSS} - %-5level - %pid - %t - %c{1.}:%L - %m%n</Property>
<Property name="FILE_PATH">/Users/springboot/logs/</Property>
</Properties>
<Appenders>
<File name="File" fileName="${FILE_PATH}sys.log">
<PatternLayout>
<pattern>${LOG_PATTERN}</pattern>
</PatternLayout>
</File>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="File" />
</Root>
</Loggers>
</Configuration>
4.异步日志
使用单独的线程打印日志,提高日志效率,避免由于打印日志而影响业务功能
1.AsyncAppender方式
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Properties>
<Property name="LOG_PATTERN">%d{yyyy-MM-dd HH:mm:ss:SSS} - %-5level - %pid - %t - %c{1.}:%L - %m%n</Property>
<Property name="FILE_PATH">/Users/springboot/logs/</Property>
</Properties>
<Appenders>
<File name="File" fileName="${FILE_PATH}sys.log">
<PatternLayout>
<pattern>${LOG_PATTERN}</pattern>
</PatternLayout>
</File>
<Async name="ASYNC">
<AppenderRef ref="File"/>
</Async>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="ASYNC"/>
</Root>
</Loggers>
</Configuration>
2.AsyncLogger方式
提供了两种方式使用异步日志,即全局异步和混合异步,全局异步是指所有的日志都进行异步的日志记录,而混合异步是指可以同时使用同步日志和异步日志
全局日志的方式:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Properties>
<Property name="LOG_PATTERN">%d{yyyy-MM-dd HH:mm:ss:SSS} - %-5level - %pid - %t - %c{1.}:%L - %m%n</Property>
<Property name="FILE_PATH">/Users/dalaoyang/logs/</Property>
</Properties>
<Appenders>
<RandomAccessFile name="RandomAccessFile" fileName="${FILE_PATH}async.log" immediateFlush="false" append="false">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m %ex%n</Pattern>
</PatternLayout>
</RandomAccessFile>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="RandomAccessFile"/>
</Root>
</Loggers>
</Configuration>
在系统初始化的时候需要增加全局配置
System.setProperty("log4j2.contextSelector,org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");
全局异步日志JVM启动参数配置
java -Dog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggercontextSelector
混合异步的模式:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Properties>
<Property name="LOG_PATTERN">%d{yyyy-MM-dd HH:mm:ss:SSS} - %-5level - %pid - %t - %c{1.}:%L - %m%n</Property>
<Property name="FILE_PATH">/Users/springboot/logs/</Property>
</Properties>
<Appenders>
<RandomAccessFile name="RandomAccessFile" fileName="${FILE_PATH}async.log" immediateFlush="false" append="false">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m %ex%n</Pattern>
</PatternLayout>
</RandomAccessFile>
</Appenders>
<Loggers>
<AsyncLogger name="com.springboot" level="info" includeLocation="true">
<AppenderRef ref="RandomAccessFile"/>
</AsyncLogger>
<Root level="info">
<AppenderRef ref="RandomAccessFile"/>
</Root>
</Loggers>
</Configuration>