一、maven依赖
在pom文件增加slf4j+logback依赖
<!-- 版本配置 -->
<properties>
<slf4j.version>1.7.21</slf4j.version>
<logback.version>1.1.7</logback.version>
</properties>
<dependencies>
<!-- slf4j依赖包 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- logback-classic桥接器 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<!-- logback实现 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
</dependencies>
二、logback配置文件
在类路径下建logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<property name="APP_NAME" value="MY_APP_NAME" />
<property name="LOG_DIR" value="logs" />
<property name="FILE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{15} - %msg%n" />
<!-- 彩色日志格式 -->
<property name="CONSOLE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %highlight(%-5level) %boldYellow([%thread]) %cyan(%logger{15}) %msg%n"/>
<contextName>${APP_NAME}</contextName>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${LOG_DIR}/logFile.log</file>
<append>true</append>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_DIR}/dayLogFile.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<!-- 使用root的appender-ref -->
<logger name="com.example.Logger1" level="DEBUG" additivity="true">
</logger>
<!-- 不使用root的appender-ref -->
<logger name="com.example.Logger2" level="DEBUG" additivity="false">
</logger>
<logger name="com.example.Logger3" level="DEBUG" additivity="false">
<appender-ref ref="STDOUT"/>
</logger>
<root level="DEBUG">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
<appender-ref ref="RollingFile" />
</root>
</configuration>
三、测试
1.java类
Loggor1.java
package com.example;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Logger1 {
private static Logger LOGGER = LoggerFactory.getLogger(Logger1.class);
static {
LOGGER.info("This is logger1");
}
}
Loggor2.java
package com.example;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Logger2 {
private static Logger LOGGER = LoggerFactory.getLogger(Logger2.class);
static {
LOGGER.info("This is logger2");
}
}
Loggor3.java
package com.example;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Logger3 {
private static Logger LOGGER = LoggerFactory.getLogger(Logger3.class);
static {
LOGGER.info("This is logger3");
}
}
Main.java
package com.example;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static Logger LOGGER = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
new Logger1();
new Logger2();
new Logger3();
LOGGER.debug("this is debug");
LOGGER.info("this is info");
LOGGER.warn("this is warn");
LOGGER.error("this is error");
}
}
2.结果
四、logback日志配置及使用
logback日志需要的依赖
<!-- 日志实现 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
日志级别从低到高
TRACE < DEBUG < INFO < WARN < ERROR < FATAL
只能展示大于或等于设置的日志级别的日志
日志配置文件名
- Logback:logback.xml, logback-spring.xml, logback-spring.groovy, logback.groovy
- Log4j:log4j.properties, log4j.xml,log4j-spring.properties, log4j-spring.xml,
- Log4j2:log4j2.xml,log4j2-spring.xml
- JDK (Java Util Logging):logging.properties
Spring Boot官方推荐优先使用带有 -spring 的文件名作为你的日志配置(如使用 logback-spring.xml ,而不是logback.xml),命名为logback-spring.xml的日志配置文件,spring boot可以为它添加一些spring boot特有的配置项(下面会提到)。
默认的命名规则,并且放在 src/main/resources 下如果你即想完全掌控日志配置,但又不想用logback.xml作为Logback配置的名字,application.yml可以通过logging.config属性指定自定义的名字:
logging.config=classpath:logging-config.xml
节点介绍
子节点root
root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,不能设置为INHERITED或者同义词NULL。
默认是DEBUG。
可以包含零个或多个元素,标识这个appender将会添加到这个loger。
<root level="debug">
<appender-ref ref="console" />
<appender-ref ref="file" />
</root>
子节点appender
appender用来格式化日志输出节点,有俩个属性name和class,class用来指定哪种输出策略,常用就是控制台输出策略和文件输出策略
控制台输出ConsoleAppender
- 示例
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<contextName>logback-demo</contextName>
<!--输出到控制台 ConsoleAppender-->
<appender name="consoleLog1" class="ch.qos.logback.core.ConsoleAppender">
<!--展示格式 layout-->
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>
<pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
</pattern>
</layout>
<!--
1. %d{HH:mm:ss.SSS} 显示的时间
2. [%thread]打印线程号,log4j2使用%t]也可以
3. %-5level日志级别,并且使用5个字符靠左对齐
4. %logger{36}——日志输出者的名字,即类的类名
5. %msg——日志消息
6. %n——平台的换行符-->
<!--
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
ThresholdFilter为系统定义的拦截器,例如我们用ThresholdFilter来过滤掉ERROR级别以下的日志不输出到文件中。如果不用记得注释掉,不然你控制台会发现没日志~
-->
</appender>
<!--指定最基础的日志输出级别-->
<root level="INFO">
<!--appender将会添加到这个loger-->
<appender-ref ref="consoleLog1"/>
<appender-ref ref="consoleLog2"/>
</root>
</configuration>
输出到文件 RollingFileAppender
另一种常见的日志输出到文件,随着应用的运行时间越来越长,日志也会增长的越来越多,将他们输出到同一个文件并非一个好办法。RollingFileAppender用于切分文件日志:
logger节点
<logger>用来设置某一个包或者具体的某一个类的日志打印级别、以及指定。仅有一个name属性,一个可选的level和一个可选的addtivity属性。
name:用来指定受此loger约束的某一个包或者具体的某一个类。
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。如果未设置此属性,那么当前loger将会继承上级的级别。
addtivity:是否向上级loger传递打印信息。默认是true。
如果addtivity为true,则如下配置就会打印两次相同日志,因为root节点的记录器是根记录器,logger节点的是子目录器,addtivity为true时会向上传递
<logger name="com.test.cms" level="info">
<appender-ref ref="console"/>
</logger>
<root level="info">
<appender-ref ref="console"/>
</root>
public class Main {
private static final Logger log = LoggerFactory.getLogger("com.test.cms");
public static void main(String[] args) {
log.info("测试");
}
}
示例
我们一般针对DAO的包进行DEBUG日志设置:
<logger name="com.moerlong.hfw.dao" level="DEBUG" />
此为logback的配置,log4j和log4j2同理,都是扫描dao包,日志级别设置成debug
子节点property
用来定义变量值的标签, 有两个属性,name和value;其中name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。
pattern打印日志规则
pattern由文字文本和转换说明符组成,您可以在其中插入任何文字文本
常用的转换说明符
转换字 | 描述 | 例子 | 打印结果 |
---|---|---|---|
logger{length} | 输出记录器的名称,参数length为输出的长度,非必填,记录器会自动简记录器的名称 | %logger | |
class{length} | 日志的请求的调用者的完全限定类名 | %class | |
line | 输出发出记录请求的行号 | %line | |
date{pattern} | 输出日志记录事件的日期,pattern为日期格式,非必填 | %date | 精确到毫秒 |
level | 输出日志的级别 | %level | |
thread | 输出日志所在的线程 | %thread | |
msg | 输出用户的日志信息 | %msg | |
-{length} 转换字 | 转换字的输出长度,如果不够则空格补凑 | %-5level | info,info前面会有一个空格 |
自定义转换字 | 将自定义的转换字输出值 | %X{自定义转换字} | 打印保存的自定义的值,可以使用import org.slf4j.MDC;的MDC.put(key, valye);,key为自定义的转换字 |
springProfile节点配置环境
将root节点包含在springProfile节点中,可以根据配置环境
<springProfile name="dev,test">
<!--指定最基础的日志输出级别-->
<root level="info">
<appender-ref ref="STDOUT" />
</root>
</springProfile>
<!--prod生产环境-->
<springProfile name="prod">
<root level="info">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
</springProfile>
完整日志配置介绍
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!--
1. scan:程序运行时配置文件被修改,是否重新加载。true=重新加载;false=不重新加载;默认为true;
2. scanPeriod:监测配置文件被修改的时间间隔,scan属性必须设置为true才可生效;默认为1分钟,默认单位是毫秒;
3. debug:是否打印logback程序运行的日志信息。true=打印;false=不打印;默认为false;
-->
<contextName>logback</contextName>
<!-- 路径变量 -->
<property name="log.path" value="E:\\test\\logback.log" />
<!-- 日志格式变量 -->
<property name="logPattern" value="%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} %file:%line - %msg%n" />
<!--
1. %d{HH:mm:ss.SSS} 显示的时间
2. [%thread]打印线程号,log4j2使用%t]也可以
3. %-5level日志级别,并且使用5个字符靠左对齐
4. %logger{36}——日志输出者的名字,即类的类名
5. %file 打印类名,也可用%class,打印的全限定类名
6. %line 打印日志所在代码行数
7. %msg——日志消息
8. %n——平台的换行符-->
<!--输出到控制台-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<!-- <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>-->
<encoder>
<pattern>${logPattern}</pattern>
</encoder>
</appender>
<!--输出到文件-->
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}</file>
<!--输出到文件路径一种滚动策略:根据时间制定日志文件的滚动策略,如:按天、按小时、按分钟生成日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 文件路径,定义了日志的切分方式——把每一天的日志归档到一个文件中,以防止日志填满整个磁盘空间 -->
<fileNamePattern>${log.path}/%d{yyyy-MM-dd}.log.gz</fileNamePattern>
<!-- 日志在磁盘上保留天数 -->
<maxHistory>30</maxHistory>
</rollingPolicy>
<!-- 另一种滚动策略:表示根据日志文件大小,超过制定大小会触发日志滚动; -->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>5MB</maxFileSize>
</triggeringPolicy>
<encoder>
<pattern>${logPattern}</pattern>
<!--
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
ThresholdFilter为系统定义的拦截器,例如我们用ThresholdFilter来过滤掉ERROR级别以下的日志不输出到文件中。如果不用记得注释掉,不然你控制台会发现没日志~
-->
<!-- 设置字符集 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- 把日志异步输出到磁盘文件中,避免每次都进行磁盘IO操作 -->
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0</discardingThreshold>
<queueSize>10000</queueSize>
<appender-ref ref="file" />
</appender>
<root level="info">
<appender-ref ref="console" />
<appender-ref ref="ASYNC" />
</root>
<!-- logback为java中的包 -->
<logger name="com.dudu.controller"/>
<!--logback.LogbackDemo:类的全路径 -->
<logger name="com.dudu.controller.LearnController" level="WARN" additivity="false">
<appender-ref ref="console"/>
</logger>
</configuration>
有的版本不支持<logger name="com.dudu.controller"/>
,必须使用
<logger name="com.dudu.controller.LearnController" level="WARN" additivity="false">
<appender-ref ref="console"/>
<appender-ref ref="log文件的变量名"/>
</logger>
格式,
记录器Logger
生成记录器:private final static Logger logger = LoggerFactory.getLogger(“名称”);
名称可以是类的全路径如:com.example.App,也可以是类的class,如App.class,记录器的构造器会自动获取App.class.getName();和直接写全路径一个效果。当生成com.example.App记录器时,还会生成com.example记录器和com记录器,com.example为com.example.App的父记录器,com记录器是com.example的父记录器,下图中的根记录器是系统自动生成的,子记录器会继承父记录器的属性,父记录器也会默认打印子记录器的日志,所以可能会打印重复的日志的,可以通过设置addtivity为false不向上传递。
获取根记录器的方法:LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
记录器Logger的层级结构
附加器Appender
记录器会将输出日志的任务交给附加器完成,不同的附加器会将日志输出到不同的地方,比如控制台附加器、文件附加器、网络附加器等。
常用附加器
控制台附加器:ch.qos.logback.core.ConsoleAppender
文件附加器:ch.qos.logback.core.FileAppender
滚动文件附加器:ch.qos.logback.core.rolling.RollingFileAppender
基于滚动文件附加器的滚动策略:
1、基于时间的滚动策略
ch.qos.logback.core.rolling.TimeBasedRollingPolicy
2、基于大小和时间的滚动策略
ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy
基于时间的滚动策略的附加器的配置
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--日志名称,如果没有File 属性,那么只会使用FileNamePattern的文件路径规则
如果同时有<File>和<FileNamePattern>,那么当天日志是<File>,明天会自动把今天
的日志改名为今天的日期。即,<File> 的日志都是当天的。-->
<File>${LOG_PATH}/${LOG_NAME}.log</File>
<!--滚动策略,按照时间滚动 TimeBasedRollingPolicy-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--归档文件的路径和文件名的生成规则-->
<FileNamePattern>${LOG_PATH}/${LOG_NAME}.%d{yyyy-MM-dd}.log</FileNamePattern>
<!--保留归档的文件的个数,如果归档文件是按天,则保留的是180天的日志历史记录-->
<maxHistory>180</maxHistory>
<!--用来指定日志文件的上限大小,那么到了这个值,就会删除旧的日志-->
<totalSizeCap>20GB</totalSizeCap>
</rollingPolicy>
<!--日志输出编码格式化-->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<charset>UTF-8</charset>
<!--格式化输出-->
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
基于大小和时间的滚动策略的附加器的配置
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_PATH}/api-error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 日志文件名格式 %i会自动生成每天的多个归档文件序列号-->
<fileNamePattern>${LOG_PATH}/api-error.%d{yyyy-MM-dd}-%i.log</fileNamePattern>
<!-- 日志最大的历史文件为60个,基于此种策略的会保留60天,而不是60个文件 -->
<maxHistory>60</maxHistory>
<!--用来指定日志文件的上限大小,那么到了这个值,就会删除旧的日志-->
<totalSizeCap>20GB</totalSizeCap>
<!--单个文件的最大容量,如果超过此值,会归档并生产新文件-->
<maxFileSize>50GB</maxFileSize>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
使用介绍
代码里使用日志
- 在类里使用日志打印信息时不用判断日志级别是否可用,不会影响性能。
在每个类创建日志对象去打印信息
private static final Logger logger = LoggerFactory.getLogger(YjServiceImpl.class);
logger.error("xxx");
也可以直接在类上通过 @Slf4j 标签去声明式注解日志对象
<!--@Slf4j自动化日志对象-log-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.16</version>
</dependency>
// 然后就直接可以使用了:
@Slf4j
@RestController
public class HfwController {
log.info("");
}