日志的作用:用来追踪和记录程序运行中的信息
常见的日志框架:logback、log4j、log4j2、jul
简介
logback是在log4j的基础上重新开发的一套日志框架,完全实现了slf4j(日志门面)
的接口API
共有三个模块:
- logback-core:核心组件
- logback-classic:原生实现了
slf4j API
- logback-access:与tomcat、jetty等servlet容器集成,提供HTTP访问日志功能
集成
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.3.7</version>
</dependency>
测试
public class LogbackTest {
//创建记录器
static Logger logger = LoggerFactory.getLogger(LogbackTest.class);
//日志级别(从低到高):trace < debug < info < warn < error
public static void main(String[] args) {
//根记录器,默认不会打印这个级别的日志
logger.trace("test trace");
//根记录器默认日志打印级别
logger.debug("test debug");
logger.info("test info");
logger.warn("test warn");
logger.error("test error");
}
}
记录器(logger)
控制要输出哪些日志记录语句,对日志级别进行限制
创建记录器
final static Logger logger = LoggerFactory.getLogger("记录器名称");
记录器存在父子关系,是通过记录器的名称来确定的
结构
- 1、执行
Logger logger = LoggerFactory.getLogger("com.tzcxyh.logback.LogbackTest");
时,记录器如下:
- 2、然后执行
Logger logger = LoggerFactory.getLogger("com.tzcxyh.logback.LogbackTest2");
时,记录器如下:
第一次创建时,会创建各级的Logger记录器,之后创建,如果父级已经存在,不会重复创建
属性
- name:记录器的名称,会根据名称,创建具有父子关系的记录器
- **level(可选):**记录器级别,允许的级别(从低到高:
trace < debug < info < warn < error
) - additivity(可选): 是否允许叠加打印日志,true(默认) / false
设置记录器级别测试
public class LoggerCodeTest {
@Test
public void testSetLevel(){
//需要强转为 ch.qos.logback.classic.Logger
Logger logger = (Logger) LoggerFactory.getLogger("com.tzcxyh.logback");
System.out.println("=====================输出设置前级别============");
System.out.println("设置前日志级别: " + logger.getEffectiveLevel());
//设置为Info级别
logger.setLevel(Level.INFO);
System.out.println("=====================输出设置后级别============");
System.out.println("设置后日志级别: " + logger.getEffectiveLevel());
//测试日志输出--只会打印大于设置级别的日志
System.out.println("=====================设置后日志输出情况============");
logger.trace("test trace");
logger.debug("test debug");
logger.info("test info");
logger.warn("test warn");
logger.error("test error");
}
}
setLevel(Level.INFO)
效果和在xml中配置一致
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%date{hh:mm:ss.SSS} %thread %level %class -- %msg%n</pattern>
</encoder>
</appender>
<logger name="com.tzcxyh.logback.LoggerCodeTest" level="INFO">
<appender-ref ref="CONSOLE"/>
</logger>
</configuration>
日志可加性设置测试
additivity
默认为true,即向上传递
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%date{hh:mm:ss.SSS} %thread %level %class -- %msg%n</pattern>
</encoder>
</appender>
<logger name="com.tzcxyh.logback.LoggerCodeTest">
<appender-ref ref="CONSOLE"/>
</logger>
<logger name="com.tzcxyh.logback">
<appender-ref ref="CONSOLE"/>
</logger>
<logger name="com.tzcxyh">
<appender-ref ref="CONSOLE"/>
</logger>
</configuration>
public class LoggerCodeTest {
@Test
public void testAdditivity(){
Logger logger = (Logger) LoggerFactory.getLogger("com.tzcxyh.logback.LoggerCodeTest");
System.out.println("=====================设置前日志输出情况============");
logger.debug("test debug ");
System.out.println("=====================设置后日志输出情况============");
logger.setAdditive(false);
logger.debug("test debug");
}
}
附加器(appender)
记录器(logger)
会将输出日志的任务交给附加器来完成,不同的附加器会将日志输出到不同的地方。如:控制台、文件、网络
pattern标签
由文字文本+转换说明符的格式来控制表达式的组成。
转换说明符 = %+(格式转换符、转换字、大括号之间的可选参数)
转换字 | 描述 | 例子 |
---|---|---|
logger{length} | 输出记录器的名称 | %logger{5} |
class{length} | 调用者全类名 | %class |
line | 行号 | %line |
date{}/date{} | 时间 | %date{yyyy-MM-dd} |
level | 日志级别 | %level |
thread | 日志所在线程 | %thread |
msg | 日志信息 | %msg |
控制台附加器
ch.qos.logback.core.ConsoleAppender
,日志输出到控制台
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--设置日志的附加器-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!--设置日志格式-->
<pattern>%date{hh:mm:ss.SSS} %thread %level %class -- %msg%n</pattern>
</encoder>
</appender>
<!--记录器,将日志传递到附加器中-->
<logger name="com.tzcxyh.logback.LoggerCodeTest">
<appender-ref ref="CONSOLE"/>
</logger>
</configuration>
文件附加器
ch.qos.logback.core.FileAppender
,日志输出到文件中
- : 设置文件输出位置和文件名称
- :设置日志是否追加到文件中。true(追加)/false(覆盖)
<?xml version="1.0" encoding="UTF-8"?>
<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="logback.xsd">
<appender name="FILE-LOG" class="ch.qos.logback.core.FileAppender">
<encoder>
<pattern>%date{hh:mm:ss.SSS} %thread %level %class -- %msg%n</pattern>
</encoder>
<!--指定文件输出位置和名称-->
<file>./file-log/logback</file>
<!--是否追加:true 追加,false 覆盖-->
<append>false</append>
</appender>
<!--配置三个logger-->
<logger name="com.tzcxyh.logback.LoggerCodeTest">
<appender-ref ref="FILE-LOG"/>
</logger>
</configuration>
public class LoggerCodeTest {
@Test
public void testFileAppender(){
Logger logger = (Logger) LoggerFactory.getLogger("com.tzcxyh.logback.LoggerCodeTest");
logger.debug("test debug ");
}
}
滚动文件附加器
ch.qos.logback.core.rolling.RollingFileAppender
,日志滚动输出到文件中。相比于文件附加器
,避免了日志文件过大
- :设置滚动策略,可以设置
基于时间(ch.qos.logback.core.rolling.TimeBasedRollingPolicy)/基于大小和时间(ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy)
- :配置文件格式,
%d{归档条件}
,文件会按归档条件切割 - :按规范条件切割日志后,最多保留多少个日志文件
- :所有日志文件占用最大内存容量
基于时间的滚动策略
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="FILE-LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<pattern>%date{hh:mm:ss.SSS} %thread %level %class -- %msg%n</pattern>
</encoder>
<!--指定文件输出位置和名称-->
<file>./file-log/logback.log</file>
<append>true</append>
<!--指定滚动策略-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--配置文件名称 %d{归档条件}-->
<fileNamePattern>./file-log/%d{HH-mm-ss}.log</fileNamePattern>
<!--最多保留多少个日志文件-->
<maxHistory>30</maxHistory>
<!--占用最大内存容量-->
<totalSizeCap>1MB</totalSizeCap>
</rollingPolicy>
</appender>
<!--配置logger-->
<logger name="com.tzcxyh.logback.LoggerCodeTest">
<appender-ref ref="FILE-LOG"/>
</logger>
</configuration>
public class LoggerCodeTest {
@Test
public void testRollingFileAppender() throws InterruptedException {
Logger logger = (Logger) LoggerFactory.getLogger("com.tzcxyh.logback.LoggerCodeTest");
int i = 0;
while (true){
Thread.sleep(500);
logger.debug("test debug " + i++);
}
}
}
基于大小和时间的滚动策略
- : 相比与
按时间的滚动策略
,需要多配置一个%i
,在同一个归档条件中,按<maxFileSize>
近一步切割日志是,i
会递增 - : 每个日志文件最大内存
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="FILE-LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<pattern>%date{hh:mm:ss.SSS} %thread %level %class -- %msg%n</pattern>
</encoder>
<!--指定文件输出位置和名称-->
<file>./file-log/logback.log</file>
<append>true</append>
<!--指定滚动策略-->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--配置文件名称 %d{归档条件} %i 同一个归档时间内,如果有多个文件,i累加-->
<fileNamePattern>./file-log/%d{HH-mm}.%i.log</fileNamePattern>
<!--最多保留多少个日志文件-->
<maxHistory>30</maxHistory>
<!--每个日志文件最大内存,与%d的配置看哪个先满足-->
<maxFileSize>2KB</maxFileSize>
<!--占用最大内存容量-->
<totalSizeCap>1MB</totalSizeCap>
</rollingPolicy>
</appender>
<!--配置三个logger-->
<logger name="com.tzcxyh.logback.LoggerCodeTest">
<appender-ref ref="FILE-LOG"/>
</logger>
</configuration>
过滤器(filter)
过滤器是附加器中的一个组件,用于决定附加器是否输出日志。可以配置一个或者多个。
枚举值:DENY(不输出)、ACCEPT(输出)、NEUTRAL(中立,由下一个过滤器觉得)
级别过滤器
ch.qos.logback.classic.filter.LevelFilter
,判断日志级别是否与配置级别相等。
如果当前日志级别 = 配置级别
,返回<onMatch>
配置的值;否则返回<onMismatch>
配置的值
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%date{hh:mm:ss.SSS} %thread %level %class -- %msg%n</pattern>
</encoder>
<!--配置级别过滤器-->
<filter class = "ch.qos.logback.classic.filter.LevelFilter">
<!--配置INFO级别-->
<level>INFO</level>
<!--onMatch ACCEPT(输出) -->
<onMatch>ACCEPT</onMatch>
<!--onMismatch DENY(不输出) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!--配置三个logger-->
<logger name="com.tzcxyh.logback.LoggerCodeTest">
<appender-ref ref="CONSOLE"/>
</logger>
</configuration>
public class LoggerCodeTest {
@Test
public void testLevelFilter(){
Logger logger = (Logger) LoggerFactory.getLogger("com.tzcxyh.logback.LoggerCodeTest");
logger.trace("test trace");
logger.debug("test debug");
logger.info("test info");
logger.warn("test warn");
logger.error("test error");
}
}
阈值过滤器
ch.qos.logback.classic.filter.ThresholdFilter
,判断日志级别是否大于等于配置级别。
如果当前日志级别 >= 配置级别
,返回NEUTRAL
;否则返回DENY
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%date{hh:mm:ss.SSS} %thread %level %class -- %msg%n</pattern>
</encoder>
<!--配置级别过滤器-->
<filter class = "ch.qos.logback.classic.filter.ThresholdFilter">
<!--配置INFO级别-->
<level>INFO</level>
</filter>
</appender>
<!--配置三个logger-->
<logger name="com.tzcxyh.logback.LoggerCodeTest">
<appender-ref ref="CONSOLE"/>
</logger>
</configuration>
public class LoggerCodeTest {
@Test
public void testThresholdFilter(){
Logger logger = (Logger) LoggerFactory.getLogger("com.tzcxyh.logback.LoggerCodeTest");
logger.trace("test trace");
logger.debug("test debug");
logger.info("test info");
logger.warn("test warn");
logger.error("test error");
}
}