目录
Logback是由log4j创始人设计的另一个开源日志组件,官方网站: http://logback.qos.ch。
logback的结构主要由三个模块组成:
SLF4J 是一个用于日志系统的简单Facade,允许最终用户在部署其应用时使用其所希望的日志系统。大概意思是指你只需要按统一的方式写记录日志的代码,而无需关心日志是通过哪个日志系统,以什么风格输出的,因为它们取决于部署项目时绑定的日志系统。
SLF4J最常用的日志实现框架是:log4j、logback。一般有slf4j+log4j、slf4j+log4j2、slf4j+logback三种日志组合。
本文选取logback做具体介绍
在工程resources目录下建立logback.xml
注:Spring Boot官方推荐优先使用带有-spring的文件名作为你的日志配置(如使用logback-spring.xml,而不是logback.xml),命名为logback-spring.xml的日志配置文件
- <dependency>
- <groupId>ch.qos.logbackgroupId>
- <artifactId>logback-classicartifactId>
- <version>1.2.3version>
- dependency>
-
注:在实际开发中我们不需要直接添加该依赖,spring-boot-starter其中包含了spring-boot-starter-logging,该依赖内容就是 Spring Boot 默认的日志框架就是logback。而spring-boot-starter-web包含了spring-boot-starter,可通过引入spring-boot-starter-web后的项目JAR依赖关系很快得出这个结论。
日志级别用来控制日志信息的输出,从高到低分为共分为七个等级:
Log4j建议只使用四个级别,优先级从高到低分别是 ERROR、WARN、INFO、DEBUG,优先级高的将被打印出来。(logback通用),通过定义级别,可以作为应用程序中相应级别的日志信息的开关。
- <configuration scan="true" scanPeriod="60 seconds" debug="false">
-
- configuration>
property有两个属性name和value:name变量的名称,value变量的值。
-
- <property name="appName" value="demoServer">property>
-
-
- <property name="logLevel" value="INFO">property>
-
-
- <property name="logPath" value="/data/project/logs">property>
-
-
- <property name="maxHistory" value="60"/>
-
-
- <property name="queueSize" value="512">property>
-
-
- <property name="logPattern" value="[ %-5level] [%date{yyyy-MM-dd HH:mm:ss.SSS}] %logger{36} [%line] [%thread]- %msg%n">property>
springProperty要配合配置文件来用。
- <springProperty scope="context" name="spring.application.name" source="spring.application.name"/>
- <springProperty scope="context" name="spring.profiles.active" source="spring.profiles.active"/>
也就是在配置文件中有对应配置。
spring:
application:
name: demoServer
profiles:
active: dev
logger节点,可选节点,作用是指明具体的包或类的日志输出级别,以及要使用的
- <logger name="com.github.demo" level value="INFO" >
-
- <appender-ref ref="ASYNC_LOG_INFO" />
- <appender-ref ref="STDOUT" />
- logger>
不过一般需要特殊检测的基础服务实际使用中additivity常常设置为false。如下:
- <logger name="com.alibaba.nacos.client" level="${log.level.nacos}" additivity="false">
- <appender-ref ref="ASYNC_THIRD_PARTY_APPENDER"/>
- logger>
-
- <logger name="com.alibaba.nacos.client.config" level="${log.level.nacos}" additivity="false">
- <appender-ref ref="ASYNC_THIRD_PARTY_APPENDER"/>
- logger>
-
- <logger name="com.alibaba.nacos.client.naming" level="${log.level.nacos}" additivity="false">
- <appender-ref ref="ASYNC_THIRD_PARTY_APPENDER"/>
- logger>
root节点,必选节点,用来指定最基础的日志输出级别并指定
-
- <root level="${logLevel}">
- <appender-ref ref="STDOUT"/>
- <appender-ref ref="ASYNC_LOG_DEBUG"/>
- <appender-ref ref="ASYNC_LOG_INFO"/>
- <appender-ref ref="ASYNC_LOG_WARN"/>
- <appender-ref ref="ASYNC_LOG_ERROR"/>
- root>
appender节点是非常关键的一个节点,它有两个必要属性name和class,name指定appender名称,class指定appender的全限定名。
另一个属性encoder:负责两件事,一是把日志信息转换成字节数组,二是把字节数组写入到输出流。
appender有三种类型:
最常用的滚动策略,根据时间再根据文件大小来滚动生成文件
-
- <appender name="FILE_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
- <file>${logPath}/info/${appName}_info.logfile>
-
- <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
-
- <fileNamePattern>${logPath}/info/${appName}_info-%d{yyyy-MM-dd}.%i.log.gzfileNamePattern>
- <maxFileSize>128MBmaxFileSize>
- <maxHistory>${maxHistory}maxHistory>
- <totalSizeCap>10GBtotalSizeCap>
- rollingPolicy>
- <encoder>
- <pattern>${logPattern}pattern>
- <charset>utf-8charset>
- encoder>
- <filter class="ch.qos.logback.classic.filter.LevelFilter">
- <level>INFOlevel>
- <onMatch>ACCEPTonMatch>
- <onMismatch>DENYonMismatch>
- filter>
- appender>
把日志输出到控制台
-
- <property name="logPattern" value="[ %-5level] [%date{yyyy-MM-dd HH:mm:ss.SSS}] %logger{36} [%line] [%thread]- %msg%n">property>
-
-
-
-
-
- <jmxConfigurator/>
-
-
- <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
- <encoder>
- <charset>UTF-8charset>
- <pattern>${logPattern}pattern>
- encoder>
- appender>
pattern定义了日志的输出格式解析:
-
- <appender name="ASYNC_LOG_INFO" class="ch.qos.logback.classic.AsyncAppender">
-
- <discardingThreshold>0discardingThreshold>
-
- <queueSize>${queueSize}queueSize>
-
- <neverBlock>trueneverBlock>
- <appender-ref ref="FILE_INFO"/>
- appender>
注意:
queueSize 过大
可能导致OOM
queueSize 较小
默认值256就已经算很小了,且discardingThreshold设置为大于0(或为默认值),队列剩余容量少于discardingThreshold的配置就会丢弃<=INFO日志。这里的坑点有两个:
因为discardingThreshold,所以设置queueSize时容易踩坑。
neverBlock 默认false
意味总可能会出现阻塞。
- 若discardingThreshold = 0,那么队列满时再有日志写入就会阻塞。
- 若discardingThreshold != 0,也只丢弃≤INFO级日志,出现大量错误日志时,还是会阻塞。
queueSize、discardingThreshold和neverBlock三参密不可分,务必按业务需求设置:
- 若优先绝对性能,设置neverBlock = true,永不阻塞。
- 若优先绝不丢数据,设置discardingThreshold = 0,即使≤INFO级日志也不会丢。但最好把queueSize设置大一点,毕竟默认的queueSize显然太小,太容易阻塞。
- 若兼顾,可丢弃不重要日志,把queueSize设置大点,再设置合理的discardingThreshold
Spring Boot项目的配置文件。
logging: file: path: '@logging.file.path@' name: ${logging.file.path}/${spring.application.name}/root.log config: classpath:logback-spring.xml
spring-boot-starter-web默认引入logback
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-webartifactId>
- dependency>
- "1.0" encoding="UTF-8"?>
- <configuration scan="true" scanPeriod="60 seconds" debug="false">
-
-
- <property name="appName" value="demoServer">property>
-
-
- <property name="logLevel" value="INFO">property>
-
-
- <property name="logPath" value="/data/project/logs">property>
-
-
- <property name="maxHistory" value="60"/>
-
-
- <property name="queueSize" value="512">property>
-
-
- <property name="logPattern" value="[ %-5level] [%date{yyyy-MM-dd HH:mm:ss.SSS}] %logger{36} [%line] [%thread]- %msg%n">property>
-
-
-
-
-
- <jmxConfigurator/>
-
-
- <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
- <encoder>
- <charset>UTF-8charset>
- <pattern>${logPattern}pattern>
- encoder>
- appender>
-
-
- <appender name="FILE_DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
- <file>${logPath}/debug/${appName}_debug.logfile>
-
- <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
-
- <fileNamePattern>${logPath}/debug/${appName}_debug-%d{yyyy-MM-dd}.%i.log.gzfileNamePattern>
- <maxFileSize>128MBmaxFileSize>
- <maxHistory>${maxHistory}maxHistory>
- <totalSizeCap>10GBtotalSizeCap>
- rollingPolicy>
- <encoder>
- <pattern>${logPattern}pattern>
- <charset>utf-8charset>
- encoder>
- <filter class="ch.qos.logback.classic.filter.LevelFilter">
- <level>DEBUGlevel>
- <onMatch>ACCEPTonMatch>
- <onMismatch>DENYonMismatch>
- filter>
- appender>
-
-
- <appender name="FILE_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
- <file>${logPath}/info/${appName}_info.logfile>
-
- <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
-
- <fileNamePattern>${logPath}/info/${appName}_info-%d{yyyy-MM-dd}.%i.log.gzfileNamePattern>
- <maxFileSize>128MBmaxFileSize>
- <maxHistory>${maxHistory}maxHistory>
- <totalSizeCap>10GBtotalSizeCap>
- rollingPolicy>
- <encoder>
- <pattern>${logPattern}pattern>
- <charset>utf-8charset>
- encoder>
- <filter class="ch.qos.logback.classic.filter.LevelFilter">
- <level>INFOlevel>
- <onMatch>ACCEPTonMatch>
- <onMismatch>DENYonMismatch>
- filter>
- appender>
-
-
- <appender name="FILE_WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
- <file>${logPath}/warn/${appName}_warn.logfile>
-
- <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
-
- <fileNamePattern>${logPath}/warn/${appName}_warn-%d{yyyy-MM-dd}.%i.log.gzfileNamePattern>
- <maxFileSize>128MBmaxFileSize>
- <maxHistory>${maxHistory}maxHistory>
- <totalSizeCap>10GBtotalSizeCap>
- rollingPolicy>
- <encoder>
- <pattern>${logPattern}pattern>
- <charset>utf-8charset>
- encoder>
- <filter class="ch.qos.logback.classic.filter.LevelFilter">
- <level>WARNlevel>
- <onMatch>ACCEPTonMatch>
- <onMismatch>DENYonMismatch>
- filter>
- appender>
-
-
- <appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
- <file>${logPath}/error/${appName}_error.logfile>
-
- <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
-
- <fileNamePattern>${logPath}/error/${appName}_error-%d{yyyy-MM-dd}.%i.log.gzfileNamePattern>
- <maxFileSize>128MBmaxFileSize>
- <maxHistory>${maxHistory}maxHistory>
- <totalSizeCap>10GBtotalSizeCap>
- rollingPolicy>
- <encoder>
- <pattern>${logPattern}pattern>
- <charset>utf-8charset>
- encoder>
- <filter class="ch.qos.logback.classic.filter.LevelFilter">
- <level>ERRORlevel>
- <onMatch>ACCEPTonMatch>
- <onMismatch>DENYonMismatch>
- filter>
- appender>
-
-
- <appender name="ASYNC_LOG_DEBUG" class="ch.qos.logback.classic.AsyncAppender">
-
- <discardingThreshold>0discardingThreshold>
-
- <queueSize>${queueSize}queueSize>
-
- <neverBlock>trueneverBlock>
- <appender-ref ref="FILE_DEBUG"/>
- appender>
-
-
- <appender name="ASYNC_LOG_INFO" class="ch.qos.logback.classic.AsyncAppender">
-
- <discardingThreshold>0discardingThreshold>
-
- <queueSize>${queueSize}queueSize>
-
- <neverBlock>trueneverBlock>
- <appender-ref ref="FILE_INFO"/>
- appender>
-
-
- <appender name="ASYNC_LOG_WARN" class="ch.qos.logback.classic.AsyncAppender">
-
- <discardingThreshold>0discardingThreshold>
-
- <queueSize>${queueSize}queueSize>
-
- <neverBlock>trueneverBlock>
- <appender-ref ref="FILE_WARN"/>
- appender>
-
-
- <appender name="ASYNC_LOG_ERROR" class="ch.qos.logback.classic.AsyncAppender">
-
- <discardingThreshold>0discardingThreshold>
-
- <queueSize>${queueSize}queueSize>
-
- <neverBlock>trueneverBlock>
- <appender-ref ref="FILE_ERROR"/>
- appender>
-
- <logger name="com.github.demo" level value="DEBUG" additivity="false">
-
- <appender-ref ref="STDOUT" />
- logger>
-
-
- <root level="${logLevel}">
- <appender-ref ref="ASYNC_LOG_DEBUG"/>
- <appender-ref ref="ASYNC_LOG_INFO"/>
- <appender-ref ref="ASYNC_LOG_WARN"/>
- <appender-ref ref="ASYNC_LOG_ERROR"/>
- root>
- configuration>