本文最后更新于:2024年9月8日 晚上
Spring 日志
Slf4j
Slf4j是一个日志框架,它是对所有日志框架制定的一种规范,标准,接口,并不是一个框架的具体的实现,因为接口并不能独立使用,它需要和具体的日志框架来配合使用。
在Java中具体的日志实现有Log4j,Log4j2,Slf4j,JDKLog,Logback等等。
Logback
日志级别
日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL
Trace:是追踪,程序每推进一步就可以写个trace输出,所以trace应该会很多。
Debug:指出细粒度信息事件对调试应用程序是非常有帮助的。
Info:消息在粗粒度级别上突出强调应用程序的运行过程。
Warn:输出警告及warn以下级别的日志。
Error:输出错误信息日志。
Fatal:输出每个严重的错误事件将会导致应用程序的退出的日志。
程序会打印高于或等于所设置级别的日志,设置的日志等级越高,打印出来的日志就越少
配置
1 2 3 4 5 6 7 8 logging: level: root: info com.example.mapper: debug file: my.log pattern: console: d{yyyy/MM/dd-HH:mm:ss} [%thread ] %-5level %logger-%msg%n file: d{yyyy/MM/dd-HH:mm:ss} [%thread ] %-5level %logger-%msg%n
logging.level
:日志级别。
logging.file
:设置文件,可以是绝对路径,也可以是相对路径,如:logging.file=my.log
,默认情况下,日志文件的大小达到10MB时会切分一次,产生新的日志文件,默认级别为:ERROR,WARN,INFO
logging.file.max-size
:最大日志文件大小。
logging.file.max-history
:最大归档文件数量。
logging.path
:设置目录,会在该目录下创建spring.log文件,并写入日志内容,如:logging.path=/var/log
logging.pattern
:设置日志格式。
logging.pattern.console
:控制台输出的日志模式。
logging.pattern.file
:文件输出的日志模式。
logging.pattern.dateformat
:日志的日期格式。
配置文件
Spring Boot 中的 logback 默认使用 src/main/resources
文件夹下的 logback.xml
或 logback-spring.xml
,也可以通过logging.config
指定配置文件。
application.properities
1 2 3 logging: config: classpath:logback-spring.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 <?xml version="1.0" encoding="UTF-8"?> <configuration scan ="true" scanPeriod ="60 seconds" debug ="false" > <property name ="app_name" value ="tally" /> <property name ="log_home" value ="logs/${app_name}" /> <property name ="log_file_upload_count" value ="3" /> <property name ="log_file_count" value ="15" /> <property name ="log_size" value ="20MB" /> <property name ="upload_log_size" value ="5MB" /> <property name ="patternLayout" value ="[%X{traceID}]$$%d{yyyy-MM-dd HH:mm:ss.SSS}$$%level{}$$[${HOSTNAME}]$$[%class]$$[%line]$$[%method]$$[%thread]$$%msg%n" /> <property name ="patternLayoutUpload" value ="%date{yyyy-MM-dd HH:mm:ss} ** %m%n" /> <property name ="encoding" value ="UTF-8" /> <appender name ="CONSOLE" class ="ch.qos.logback.core.ConsoleAppender" > <encoder > <pattern > ${patternLayout}</pattern > <charset > ${encoding}</charset > </encoder > </appender > <appender name ="noSpecify" class ="ch.qos.logback.core.rolling.RollingFileAppender" > <file > ${log_home}/noSpecify.log</file > <rollingPolicy class ="ch.qos.logback.core.rolling.TimeBasedRollingPolicy" > <fileNamePattern > ${log_home}/%d{yyyy-MM-dd}/noSpecify-%d{yyyyMMdd}-%i.log.gz </fileNamePattern > <maxHistory > ${log_file_count}</maxHistory > <timeBasedFileNamingAndTriggeringPolicy class ="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP" > <maxFileSize > ${log_size}</maxFileSize > </timeBasedFileNamingAndTriggeringPolicy > </rollingPolicy > <encoder > <pattern > ${patternLayout}</pattern > <charset > ${encoding}</charset > </encoder > </appender > <appender name ="business" class ="ch.qos.logback.core.rolling.RollingFileAppender" > <file > ${log_home}/business.log</file > <rollingPolicy class ="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy" > <fileNamePattern > ${log_home}/%d{yyyy-MM-dd}/business-%d{yyyyMMdd}-%i.log.gz </fileNamePattern > <maxHistory > ${log_file_count}</maxHistory > <maxFileSize > ${log_size}</maxFileSize > </rollingPolicy > <encoder > <pattern > ${patternLayout}</pattern > <charset > ${encoding}</charset > </encoder > </appender > <appender name ="sql" class ="ch.qos.logback.core.rolling.RollingFileAppender" > <file > ${log_home}/sql.log</file > <rollingPolicy class ="ch.qos.logback.core.rolling.TimeBasedRollingPolicy" > <fileNamePattern > ${log_home}/%d{yyyy-MM-dd}/sql-%d{yyyyMMdd}-%i.log.gz </fileNamePattern > <maxHistory > ${log_file_count}</maxHistory > <timeBasedFileNamingAndTriggeringPolicy class ="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP" > <maxFileSize > ${log_size}</maxFileSize > </timeBasedFileNamingAndTriggeringPolicy > </rollingPolicy > <encoder > <pattern > ${patternLayout}</pattern > <charset > ${encoding}</charset > </encoder > </appender > <root level ="INFO" > <appender-ref ref ="CONSOLE" /> <appender-ref ref ="noSpecify" /> </root > <logger name ="com.lushan.tally.mapper" level ="DEBUG" > <appender-ref ref ="sql" /> </logger > <logger name ="com.lushan.tally.service" level ="INFO" > <appender-ref ref ="business" /> </logger > </configuration >
Pattern
%d
表示时间,用 %d{yyyy-MM-dd HH:mm:ss.SSS}
定义了格式化时间,也可以使用 %date
%-5level
表示显示日志级别,并且用 5 个字符靠左对齐,也可以用 %p
表示日志级别。
%thread
表示显示日志进程名字。
%logger{80}
表示日志输出者的名字最长80个字符,否则按照句点分割,常常是类名。
%msg
日志消息。
%n
平台的换行符。
%c
用来在日志上输出类的全名。
%L
表示行号。
charset
设置日志编码格式为 UTF-8,避免中文乱码。
root
标签内设置日志级别 level
,等同于在配置文件中设置 logging.pattern.level
Appender :Appender 是一个日志打印的组件,定义了打印过滤的条件,打印输出方式,滚动策略,编码方式,打印格式等等,但是它仅仅是一个打印组件,如果不使用一个 logger 或者 root 的 appender-ref 指定某个具体的 appender 时,它就没有什么意义。
ConsoleAppender
:需要设置这样的一个 apppender,否则日志不会打印到控制台。
RollingFileAppender
:滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件。
rollingPolicy
设置滚动切分的规则。
fileNamePattern
:滚动时产生的文件的存放位置及文件名称。
%d{yyyy-MM-dd}:按天进行日志滚动。
%i:当文件大小超过maxFileSize时,按照i进行文件滚动。
totalSizeCap
用来指定日志文件的上限大小,这个设置在 maxFileSize
之后起效,也就是说,如果你文件上限设置的是 1MB,但是 maxFileSize
设置的是 10MB,那么,这个日志文件也会保存为 10MB,假设你 maxFileSize
设置的是 1MB,totalSizeCap
设置的是 2MB,那么你日志文件的个数最多也就 2 个。
MaxHistory
可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件,假设设置每天滚动,且maxHistory是365,则只保存最近365天的文件,我还是喜欢这个设置,比 totalSizeCap
意义更清晰。
maxFileSize
:当日志文件超过maxFileSize指定的大小是,根据上面提到的%i进行日志文件滚动。
Root与Logger :可以包含零个或多个<appender-ref>
元素,标识这个 appender 将会添加到这个 logger
level:日志打印级别,如果未设置此属性,那么当前 logger 会继承上级的级别,也就是 root 的级别。
name:用来指定受此 logger 约束的某一个包或者具体的某一个类,root没有该属性,默认是所有没有被其他logger约束的类。
addtivity:是否向上级 logger 传递打印信息,默认是 true,设置为 false 表示该日志打印设置(控制台打印还是文件打印等具体设置)不会向根 root 标签传递,也就是说该 logger 里怎么设置的那就会怎么打印,跟 root 无关。
Log4j2
日志级别
日志level共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF
All:最低等级的,用于打开所有日志记录。
Trace:是追踪,程序每推进一步就可以写个trace输出,所以trace应该会很多。
Debug:指出细粒度信息事件对调试应用程序是非常有帮助的。
Info:消息在粗粒度级别上突出强调应用程序的运行过程。
Warn:输出警告及warn以下级别的日志。
Error:输出错误信息日志。
Fatal:输出每个严重的错误事件将会导致应用程序的退出的日志。
OFF:最高等级的,用于关闭所有日志记录。
程序会打印高于或等于所设置级别的日志,设置的日志等级越高,打印出来的日志就越少
pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter</artifactId > <exclusions > <exclusion > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-logging</artifactId > </exclusion > </exclusions > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-log4j2</artifactId > </dependency > <dependency > <groupId > com.lmax</groupId > <artifactId > disruptor</artifactId > <version > 3.3.6</version > </dependency >
配置文件
在src/main/resources
中添加log4j2.xml
配置文件(Spring Boot 还会识别log4j2.json
和log4j2.yaml
)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 <?xml version="1.0" encoding="UTF-8"?> <configuration status ="WARN" monitorInterval ="30" > <appenders > <console name ="Console" target ="SYSTEM_OUT" > <PatternLayout pattern ="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n" /> </console > <File name ="log" fileName ="log/test.log" append ="false" > <PatternLayout pattern ="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n" /> </File > <RollingFile name ="RollingFileInfo" fileName ="${sys:user.home}/logs/info.log" filePattern ="${sys:user.home}/logs/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log" > <ThresholdFilter level ="info" onMatch ="ACCEPT" onMismatch ="DENY" /> <PatternLayout pattern ="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n" /> <Policies > <TimeBasedTriggeringPolicy /> <SizeBasedTriggeringPolicy size ="100 MB" /> </Policies > </RollingFile > <RollingFile name ="RollingFileWarn" fileName ="${sys:user.home}/logs/warn.log" filePattern ="${sys:user.home}/logs/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log" > <ThresholdFilter level ="warn" onMatch ="ACCEPT" onMismatch ="DENY" /> <PatternLayout pattern ="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n" /> <Policies > <TimeBasedTriggeringPolicy /> <SizeBasedTriggeringPolicy size ="100 MB" /> </Policies > <DefaultRolloverStrategy max ="20" /> </RollingFile > <RollingFile name ="RollingFileError" fileName ="${sys:user.home}/logs/error.log" filePattern ="${sys:user.home}/logs/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log" > <ThresholdFilter level ="error" onMatch ="ACCEPT" onMismatch ="DENY" /> <PatternLayout pattern ="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n" /> <Policies > <TimeBasedTriggeringPolicy /> <SizeBasedTriggeringPolicy size ="100 MB" /> </Policies > </RollingFile > </appenders > <loggers > <logger name ="org.springframework" level ="INFO" > </logger > <logger name ="org.mybatis" level ="INFO" > </logger > <root level ="all" > <appender-ref ref ="Console" /> <appender-ref ref ="RollingFileInfo" /> <appender-ref ref ="RollingFileWarn" /> <appender-ref ref ="RollingFileError" /> </root > </loggers > </configuration >
根节点Configuration有两个属性:status和monitorinterval,有两个子节点:Appenders和Loggers(表明可以定义多个Appender和Logger)
status用来指定log4j本身的打印日志的级别。
monitorinterval用于指定log4j自动重新配置的监测间隔时间,单位是s,最小是5s
Appenders节点,常见的有三种子节点:Console,RollingFile,File
Console 节点用来定义输出到控制台的Appender
name:指定Appender的名字。
target:SYSTEM_OUT 或 SYSTEM_ERR,一般只设置默认:SYSTEM_OUT
PatternLayout:输出格式,不设置默认为:%m%n
File 节点用来定义输出到指定位置的文件的Appender
name:指定Appender的名字。
fileName:指定输出日志的目的文件带全路径的文件名。
PatternLayout:输出格式,不设置默认为:%m%n
RollingFile 节点用来定义超过指定大小自动删除旧的创建新的的Appender
name:指定Appender的名字。
fileName:指定输出日志的目的文件带全路径的文件名。
PatternLayout:输出格式,不设置默认为:%m%n
filePattern:指定新建日志文件的名称格式。
Policies:指定滚动日志的策略,就是什么时候进行新建日志文件输出日志。
TimeBasedTriggeringPolicy:Policies子节点,基于时间的滚动策略,interval属性用来指定多久滚动一次,默认是1 hour,modulate=true用来调整时间:比如现在是早上3am,interval是4,那么第一次滚动是在4am,接着是8am,12am…而不是7am
SizeBasedTriggeringPolicy:Policies子节点,基于指定文件大小的滚动策略,size属性用来定义每个日志文件的大小。
DefaultRolloverStrategy:用来指定同一个文件夹下最多有几个日志文件时开始删除最旧的,创建新的(通过max属性)
Loggers节点,常见的有两种:Root和Logger
Root 节点用来指定项目的根日志,如果没有单独指定Logger,那么就会默认使用该Root日志输出。
level:日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF
AppenderRef:Root的子节点,用来指定该日志输出到哪个Appender
Logger 节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。
level:日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF
name:用来指定该Logger所适用的类或者类所在的包全路径,继承自Root节点。
AppenderRef:Logger的子节点,用来指定该日志输出到哪个Appender,如果没有指定,就会默认继承自Root.如果指定了,那么会在指定的这个Appender和Root的Appender中都会输出,此时我们可以设置Logger的additivity="false"只在自定义的Appender中进行输出。
使用日志
1 2 3 4 5 6 7 8 9 10 11 public class LoggerTest { private final Logger logger = LoggerFactory.getLogger(LoggerTest.class); @Test public void test () { logger.debug("debug" ); logger.info("info" ); logger.error("error" ); logger.warn("warn" ); } }
1 2 3 4 5 6 7 8 9 10 11 @Slf4j public class LoggerTest { @Test public void test () { log.debug("debug" ); log.info("info" ); log.error("error" ); log.warn("warn" ); } }
注意 :在JVM启动参数中增加-DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
开启异步日志。
问题解决
项目不打印日志
报错 :SLF4J: Class path contains multiple SLF4J bindings
原因 :项目中既存在slf4j-log4j12
的jar包又存在log4j-slf4j-impl
的jar包,导致出现了两个打印日志实现类,所以slf4j门面不知道具体应该使用哪一个进行输出日志,所以导致不打印日志,之前是log4j 1.x,并且在web.xml里面指定了log4j.properties
文件的位置,第一次运行项目,忘了修改其值为log4j2.xml,出现了Context [] startup failed due to previous errors
的错误,导致项目启动不起来。
解决方法 :修改web.xml
1 2 3 4 <context-param > <param-name > log4jConfiguration</param-name > <param-value > /WEB-INF/classes/log4j2.xml</param-value > </context-param >