springboot2.x以后默认采用了:slf4j+logback的日志搭配
在springboot的底层日志结构中对应:spring-boot-starter-logging
可以看出,它依赖了三个框架分别是:
- slf4j
- logback
- log4j
trace>debug>info>warn>error
springboot默认日志级别是:info(打印info,warn,error)
建议大家在开发的时候使用:debug日志,在生成环境中使用:error 。
默认生成的日志信息是再控制台中输出的,得修改配置才能存入日志文件.
slf4j、logback和log4j三者的关系
1、logback和log4j是日志实现框架,就是实现怎么记录日志的。
2、slf4j:提供了java所有的日志框架的简单抽象(使用了日志的门面设计模式),说白了就是一个日志API(没有实现类
), 它不能单独使用:必须要结logback和log4j日志框架来实现结合使用。
第一步:添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
spring-boot-starter-web里面集成了spring-boot-starter-logging
第二步:初始化一个日志对象
private static Logger log = LoggerFactory.getLogger(IndexController.class);
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @description:
* @author: xuke
* @time: 2021/6/1 19:58
*/
@RestController
public class LogController {
private static final Logger log = LoggerFactory.getLogger(LogController.class);
@GetMapping("/log")
public void console(){
log.trace("----------trace--------");
log.debug("----------debug--------");
log.info("----------info--------");
log.warn("----------warn--------");
log.error("----------error--------");
}
}
上面打印的结果是:
2021-06-21 20:49:58.686(日志时间) INFO(日志的级别) 16448(编号) --- [nio-9999-exec-1] (线程名称)c.kuangstudy.controller.IndexController(日志打印类) : ----------info--------(日志信息)
2021-06-21 20:49:58.686 WARN 16448 --- [nio-9999-exec-1] c.kuangstudy.controller.IndexController : ----------warn--------
2021-06-21 20:49:58.686 ERROR 16448 --- [nio-9999-exec-1] c.kuangstudy.controller.IndexController : ----------error--------
trace>debug>info>warn>error
上面为什么仅仅打印了: info > warn > error 告诉你springboot默认日志级别是:info,只会打印出等于低于这个级别的日志。
建议大家在开发的时候使用:debug日志,在生成环境中使用:error 。(为什么?)
在application.yml种修改日志级别
分为全局修改和局部修改
全局修改:
# 指定日志级别 把springboot的所有日志修改成为debug
logging:
level:
root: debug
局部修改:
# 指定日志级别 把自定路径的日志修改成为debug
logging:
level:
com:
kuangstudy: debug
日志存储进日志文件
日志输出文件:默认情况下关闭。默认是再控制台输出的
**建议大家在开发的时候使用:debug日志,在生成环境中使用:error **。
在开发中建议大家是打开,不打开也没有关闭,你可以项目发布制定日志输出的文件:(可以先不理会)
那如何指定生成日志文件呢?
有三种方式,使用其中一种就行了。建议使用方式二
方法一:在application.yml中使用logging:file:path路径来指定
默认会在项目的根目录下生成对应路径的文件夹,默认日志文件名为spring.log
方式二:在application.yml中使用logging:file:name路径来指定
方式三:发布部署的时候用命令, >>log.txt &指定日志文件
nohup java -jar xxxx.jar >>log.txt &
logging:
level:
root: info
file:
name: /usr/tomcat/apache-tomcat-9.0.53/webapps/console.log
pattern:
console: "%d{yyyy/MM/dd-HH:mm:ss} [%thread] %-5level %logger{50}- %msg%n"
file: "%d{yyyy/MM/dd-HH:mm:ss} ---- [%thread] %-5level %logger{50}- %msg%n"
遗留一个问题:假如日志文件很大,怎么办?
日志格式
下面是我们定义日志的配置,基本上都不会发生变化
会定义:日志级别、日志文件、日志格式
前两个我们上面讲了,那现在说一下日志格式:
上图中定义了console控制台的日志格式 以及 file日志文件的日志格式。
一些符号的说明:
%c 输出logger名称
%C 输出类名
%d{HH:mm:ss.SSS} 表示输出到毫秒的时间
%t 输出当前线程名称
%-5level 输出日志级别,-5表示左对齐并且固定输出5个字符,如果不足在右边补0
%logger 输出logger名称,因为Root Logger没有名称,所以没有输出
%msg 日志文本
%n 换行
其他常用的占位符有:
%F 输出所在的类文件名,如Log4j2Test.java
%L 输出行号
%M或%method 输出所在方法名
%l 输出完整的错误位置, 包括类名、方法名、文件名、行数
%p 该条日志的优先级
%replace{pattern}{regex}{substitution} 将pattern的输出结果pattern按照正则表达式regex替换成substitution
一般来说不建议大家去修改,除非有特殊场景,比如后续要讲的:elk 收集日志的时候,很方便的去定义格式
ELK的作用,由于生成环境的日志是很大的,可能有好几个G,所以就用elk取抓取你的操作时候产生的日志
开发中日志的运用(重点)
有两种方式,其实底层是一样的。
1.正常的日志使用
使用SLF4J包下的LoggerFactory和Logger创建除日志对象使用:
private static Logger log = LoggerFactory.getLogger(WeixinPayService.class);
@Service
public class WeixinPayService {
private static Logger log = LoggerFactory.getLogger(WeixinPayService.class);
@Autowired
private WeixinPayProperties weixinPayProperties;
public void testvalue2() {
System.out.println(weixinPayProperties.getAppid());
System.out.println(weixinPayProperties.getApisecret());
System.out.println(weixinPayProperties.getMcid());
System.out.println(weixinPayProperties.getCallbackurl());
}
public void paycourse(User user, Course course) {
try {
System.out.println(1/0);
log.info("当前支付的用户是:{},支付的课程是:{},金额是:{}", user.getId(), course.getTitle(), course.getPrice());
log.info("支付的appid是:{},回调地址是:{}";
weixinPayProperties.getAppid(),
weixinPayProperties.getCallbackurl());
} catch (Exception ex) {
log.error("支付出异常,异常信息是:{}", ex.getMessage());
}
}
}
2.集成lombok使用
在lombok中提供了两个日志注解的支持:@Slf4j
和@Log4j2
建议在开发过程中就默认选择:@Slf4j
前提:必须要安装lombok的插件和依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
@Service
@Slf4j // 相当于: private static Logger log = LoggerFactory.getLogger(WeixinPayService.class);
public class WeixinPayService {
@Autowired
private WeixinPayProperties weixinPayProperties;
public void testvalue2() {
System.out.println(weixinPayProperties.getAppid());
System.out.println(weixinPayProperties.getApisecret());
System.out.println(weixinPayProperties.getMcid());
System.out.println(weixinPayProperties.getCallbackurl());
}
public void paycourse(User user, Course course) {
try {
System.out.println(1/0);
log.info("当前支付的用户是:{},支付的课程是:{},金额是:{}", user.getId(), course.getTitle(), course.getPrice());
log.info("支付的appid是:{},回调地址是:{}", weixinPayProperties.getAppid(), weixinPayProperties.getCallbackurl());
} catch (Exception ex) {
log.error("支付出异常,异常信息是:{}", ex.getMessage());
}
}
}
查看编译以后的结果:
日志级别的环境隔离
因为在开发中,我们分为生成环境和开发环境。开发环境的级别一般建议大家使用:debug或者info 。但是在生产环境中建议大家使用:error
.所有我们可以使用起那么学习的环境隔离的机制,进行解决
其实也可以在发布项目的时候用命令,来指定日志文件。上面有讲到
application-dev.yml
开发环境:一般就在控制台打印即可,写文件着实没有任何意义。 日志级别是:debug
server:
port: 9999
#自定义属性
ksd:
weixin:
appid: 456453sdfsd52342
mcid: 48878787
callbackurl: https://www.kuangstudy.com/pay/callback
apisecret: SDFLKSDJFKLSJKLJ23423423
# 指定日志级别 把springboot的所有日志修改成为debug
logging:
level:
root: debug
pattern:
# console是控制台的日志的格式
console: "【KuangStudy-console】%d{yyyy/MM/dd-HH:mm:ss} [%thread] %-5level %logger{50} --%M- %msg%n"
application-prod.yml
开发环境:一般就在控制台打印即可,写文件着实没有任何意义。 日志级别是:error
server:
port: 80
# 指定日志级别 把springboot的所有日志修改成为debug
logging:
level:
root: error
file:
# 如果不想把日志存放在logging.file.path目录下,可以采用name来重新定义存储的位置和日志文件的名称
name: /www/logs/kuangstudypro.log
pattern:
# file 是指日志文件中日志的格式
file: "【KuangStudy-file】%d{yyyy/MM/dd-HH:mm:ss} -- [%thread] %-5level %logger{50} -- %M - %msg%n"
application.yml
# 环境激活,选择环境
spring:
profiles:
active: dev
扩展:logback.xml
这也是一种使用日志的方式,用这种方式就不需要再application.yml中配置日志文件和日志格式了,直接再这个xml文件(logback.xml (常叫这个名字)或者 logback-spring.xml)中定义就OK了
使用方式
可以配置日志格式和输出方式,甚至还能和第三发中间件日志输出
例子:定义一个带有颜色的日志控制台输出
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="LOG_PATH" value="logs" />
<property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] %-40.40logger{39} : %msg%n" />
<!-- 控制台输出 -->
<appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
<!-- 彩色日志 -->
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>
%d{yyyy-MM-dd HH:mm:ss} [%thread] %magenta(%-5level) %green([%-50.50class]) >>>TO>>> %cyan(%msg) %n
</pattern>
</layout>
</appender>
<!-- 按照每天生成日志文件 -->
<appender name="fileLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_PATH}/cms.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
<!--日志文件最大的大小-->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${LOG_PATTERN}</pattern>
</encoder>
</appender>
<!-- 日志输出级别 -->
<root level="info">
<appender-ref ref="consoleLog" />
<appender-ref ref="fileLog" />
</root>
</configuration>