
日志系统是用于记录程序的运行过程中产生的运行信息、异常信息等,一般有8个级别,从低到高为All < Trace < Debug < Info < Warn < Error < Fatal < OFF
Logback和Log4j都是为Java应用程序提供的比较流行的开源日志框架,它们都由同一个开发者创建和维护,但在功能和性能上存在一些差异,Logback可以认为是log4j的改进版,在性能、配置应用上都要优于log4j,Logback主要由三个模块构成:logback-core,logback-classic和logback-access。其中,logback-core是其他两个模块的基础,提供了Logback的核心功能。logback-classic模块实现了简单日志门面SLF4J,而logback-access模块则主要作为一个与Servlet容器交互的模块,提供与HTTP访问相关的一些功能。
Spring Boot默认是使用Logback的,并且提供了自动配置,默认使用logback-spring.xml作为配置文件的名称,当然,也可以在application.properties或application.yml中配置。下面分享一下logback-spring.xml中常用的一些标签。
configuration为根节点,有scan、scanPeriod、debug三个属性;
- <configuration scan="true" scanPeriod="60 seconds" debug="false">
-
- configuration>
property是configuration的子标签,有两个属性name和value:name变量的名称,value变量的值。
- "1.0" encoding="UTF-8"?>
- <configuration scan="true" scanPeriod="60 seconds" debug="false">
-
- <property name="appName" value="logback-demo">property>
-
- <property name="logLevel" value="trace">property>
-
- <property name="logPath" value="/logs">property>
-
- <property name="maxHistory" value="60"/>
- configuration>
logger节点,可选节点,作用是指明具体的包或类的日志输出级别,以及要使用的;
root节点,必选节点,用来指定最基础的日志输出级别并指定,可以理解为根logger。
appender是configuration的子节点,也是非常关键的一个节点,它有两个必要属性name和class,name指定appender名称,class指定appender的全限定名。
appender有四种类型,如下(其中第四种比较特殊,后面再说):
appender内的有一个子标签encoder,有两个作用,一是把日志信息转换成字节数组,二是把字节数组写入到输出流,可以用于定义输出日志内容的编码格式、日志格式;其中endcoder内的子标签charset用于定义输出日志内容的编码格式,子标签pattern用于定义输出日志的具体格式;
- "1.0" encoding="UTF-8"?>
- <configuration scan="true" scanPeriod="60 seconds" debug="false">
-
- <property name="appName" value="logback-demo">property>
-
- <property name="logLevel" value="INFO">property>
-
- <property name="logPattern" value="[ %-5level] [%date{yyyy-MM-dd HH:mm:ss.SSS}] %logger{36} [%line] [%thread]- %msg%n">property>
-
- <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
- <encoder>
- <charset>UTF-8charset>
- <pattern>${logPattern}pattern>
- encoder>
- appender>
- <root level="${logLevel}">
- <appender-ref ref="console"/>
- root>
- configuration>
FileAppender与RollingFileAppender都是用于将日志写入文件的组件,配置属性基本相同,因此这里放在一起来说,但是需要注意的是二者在日志文件处理方式上有所不同,FileAppender将所有的日志信息写入一个指定的文件中,当文件达到一定大小或时间点时,它会被新的日志文件所替代。而RollingFileAppender则会在日志文件达到指定大小时,创建新的日志文件继续写入,并且保留一定数量的旧日志文件。
以下是RollingFileAppender和FileAppender的主要区别:
RollingFileAppender:
FileAppender:
另外这里着重说一下maxFileSize和maxHistory,以及filter标签,maxFileSize 是用来限制单个日志文件的最大大小。例如,如果你设置 maxFileSize 为 10MB,那么当日志文件达到 10MB 时,Logback 会开始创建新的日志文件(例如,app.log.1,app.log.2,等等)。旧的日志文件将被保留,直到达到配置的 maxHistory 天数。
而 totalSizeCap 是用来限制所有日志文件的总大小。例如,如果你设置 totalSizeCap 为 1GB,那么当所有日志文件的总大小达到 1GB 时,Logback 会开始删除旧的日志文件,以便为新的日志文件腾出空间。这个属性对于防止日志文件占用过多的磁盘空间非常有用。
注意,totalSizeCap 和 maxFileSize 不建议同时使用。如果同时设置,totalSizeCap 将优先于 maxFileSize。也就是说,当达到 totalSizeCap 时,将删除旧的日志文件,无论这些文件是否达到了 maxFileSize。
在Logback中,filter标签用于过滤日志消息。通过在filter标签中定义条件,可以实现对日志消息的筛选和拦截,实现根据指定的条件来控制哪些日志消息应该被记录。
在下面的示例中,我们使用了一个名为ThresholdFilter的过滤器,它根据日志级别进行过滤。我们将level属性设置为info,这意味着只有级别为info及以上的日志消息会被记录到文件中,其他级别的日志消息将被拦截。
- "1.0" encoding="UTF-8"?>
- <configuration scan="true" scanPeriod="60 seconds" debug="false">
-
- <property name="appName" value="logback-demo">property>
-
- <property name="logLevel" value="info">property>
-
- <property name="logPattern" value="[ %-5level] [%date{yyyy-MM-dd HH:mm:ss.SSS}] %logger{36} [%line] [%thread]- %msg%n">property>
-
- <property name="logPath" value="./logs">property>
-
- <property name="maxHistory" value="60"/>
-
- <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
- <encoder>
- <charset>UTF-8charset>
- <pattern>${logPattern}pattern>
- encoder>
- appender>
-
- <appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
- <file>${logPath}/${appName}_info.logfile>
-
- <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
- <fileNamePattern>${logPath}/${appName}_info-%d{yyyy-MM-dd}.%i.logfileNamePattern>
-
- <maxFileSize>10MBmaxFileSize>
-
- <maxHistory>${maxHistory}maxHistory>
-
- <totalSizeCap>1GBtotalSizeCap>
- 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>
-
- <root level="${logLevel}">
- <appender-ref ref="console"/>
- <appender-ref ref="file_info"/>
- root>
- configuration>
上面已经说了,四种类型的appender,AsyncAppender比较特殊,特殊就在于记录日志时从同步或异步的角度来看,前三者属于同步日志,后者属于异步日志。Logback的同步日志是立即写入磁盘的日志,而异步日志是通过线程池异步处理写入磁盘的日志。
Logback异步输出的原理是:先写入到缓冲区,当缓冲区满了或者达到一定时间,再把缓冲区的数据一次性写入磁盘,这样可以减少磁盘IO操作,提高性能。
Logback异步输出的配置是:配置一个,例如,然后在中配置一个,表示缓冲区的大小,再配置一个,表示缓冲区达到这个阈值时,会触发一个强制写入磁盘的操作。
在《基于Redis实现消息队列的实践》遇到的明明程序执行结果正常,就是看不到过程日志,最后的解决办法就使用了logback的异步日志,有兴趣的小伙伴可移步参考一下。
- "1.0" encoding="UTF-8"?>
- <configuration scan="true" scanPeriod="60 seconds" debug="false">
-
- <property name="appName" value="logback-demo">property>
-
- <property name="logLevel" value="info">property>
-
- <property name="logPattern" value="[ %-5level] [%date{yyyy-MM-dd HH:mm:ss.SSS}] %logger{36} [%line] [%thread]- %msg%n">property>
-
- <property name="logPath" value="./logs">property>
-
- <property name="maxHistory" value="60"/>
-
- <property name="queueSize" value="512">property>
-
-
- <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
- <encoder>
- <charset>UTF-8charset>
- <pattern>${logPattern}pattern>
- encoder>
- appender>
-
- <appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
- <file>${logPath}/${appName}_info.logfile>
-
- <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
- <fileNamePattern>${logPath}/${appName}_info-%d{yyyy-MM-dd}.%i.logfileNamePattern>
-
- <maxFileSize>10MBmaxFileSize>
-
- <maxHistory>${maxHistory}maxHistory>
-
- <totalSizeCap>1GBtotalSizeCap>
- 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="async_log_info" class="ch.qos.logback.classic.AsyncAppender">
-
- <discardingThreshold>0discardingThreshold>
-
- <queueSize>${queueSize}queueSize>
-
- <neverBlock>trueneverBlock>
- <appender-ref ref="file_info"/>
- appender>
- <root level="${logLevel}">
- <appender-ref ref="console"/>
- <appender-ref ref="file_info"/>
- <appender-ref ref="async_log_info"/>
- root>
- configuration>
如果项目是Springboot项目,默认已经引入,不需要额外引入依赖,如果确实需要,可参考:
- <dependency>
- <groupId>ch.qos.logbackgroupId>
- <artifactId>logback-classicartifactId>
- <version>1.2.11version>
- dependency>
在Springboot项目中,默认的配置文件名称是logback-spring.xml,官方也推荐使用这样的命名方式,logback本身默认的配置文件名称是logback.xml
在工程resources目录下建立logback.xml,配置文件的加载顺序是:
在程序中注入logger有两种方式:
- @Component
- public class DemoTask {
- private final static Logger logger= LoggerFactory.getLogger(DemoTask.class);
-
- @Scheduled(fixedDelay = 10, timeUnit = TimeUnit.SECONDS)
- public void test() {
- logger.info("-------------");
- logger.trace("trace");
- logger.debug("debug");
- logger.info("info");
- logger.warn("warn");
- logger.error("error");
- logger.info("-------------");
- }
- }
- <dependency>
- <groupId>org.projectlombokgroupId>
- <artifactId>lombokartifactId>
- <optional>trueoptional>
- dependency>
- @Component
- @Slf4jj
- public class DemoTask {
- @Scheduled(fixedDelay = 10, timeUnit = TimeUnit.SECONDS)
- public void test() {
- log.info("-------------");
- log.trace("trace");
- log.debug("debug");
- log.info("info");
- log.warn("warn");
- log.error("error");
- log.info("-------------");
- }
- }
文章中展示了关键性代码,示例全部代码地址:凡夫贩夫 / logback-demo · GitCode