Java SpringBoot logback
SpringBoot 默认采用 Logback 日志作为记录日志的框架。在项目中,一般分为 dev 环境(开发环境)、test环境(测试环境)和 prd 环境(生产环境)。而一般开发环境和测试环境可以把日志级别设置成 info 级别,方便在联调与测试中解决遇到的bug,但是生产环境因为存在大量的业务,如果采用 info 级别的日志, 那么每一笔交易或者业务都打印大量的日志。这样的花需要大量的磁盘空间来保存日志。如果日志需要保存一年半载,或者有些业务场景,例如财务数据的日志需要保存更久。将给公司造成很大的财务浪费。今天分享一个小方案,动态改变日志的级别,方便在生产环境也能方便快捷的从 warn 或者 error 级别切换到 debug 或者 info 级别。

1、pom.xml 引入依赖

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  3. <modelVersion>4.0.0</modelVersion>
  4. <groupId>com.olive</groupId>
  5. <artifactId>valid-demo</artifactId>
  6. <version>0.0.1-SNAPSHOT</version>
  7. <packaging>jar</packaging>
  8. <parent>
  9. <groupId>org.springframework.boot</groupId>
  10. <artifactId>spring-boot-starter-parent</artifactId>
  11. <version>2.1.8.RELEASE</version>
  12. <relativePath />
  13. </parent>
  14. <name>valid-demo</name>
  15. <url>http://maven.apache.org</url>
  16. <properties>
  17. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  18. </properties>
  19. <dependencies>
  20. <dependency>
  21. <groupId>org.springframework.boot</groupId>
  22. <artifactId>spring-boot-starter-web</artifactId>
  23. </dependency>
  24. </dependencies>
  25. </project>

2、logbak-spring.xml 配置

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!--
  3. scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
  4. scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒当scan为true时,此属性生效。默认的时间间隔为1分钟。
  5. debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
  6. -->
  7. <configuration scan="false" scanPeriod="60 seconds" debug="false">
  8. <!-- ch.qos.logback.core.ConsoleAppender 表示控制台输出 -->
  9. <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
  10. <!--
  11. 日志输出格式:
  12. %d表示日期时间,
  13. %thread表示线程名,
  14. %-5level:级别从左显示5个字符宽度
  15. %logger{50} 表示logger名字最长50个字符,否则按照句点分割。
  16. %msg:日志消息,
  17. %n是换行符
  18. -->
  19. <layout class="ch.qos.logback.classic.PatternLayout">
  20. <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
  21. </layout>
  22. </appender>
  23. <root level="info">
  24. <!-- 控制台输出日志-->
  25. <appender-ref ref="stdout" />
  26. </root>
  27. </configuration>

为了演示,这里只配置了一个 rootLogger

3、编写 Controller

该 Controller 主要包含以下三个API
主要框架

  1. import java.util.HashMap;
  2. import java.util.Iterator;
  3. import java.util.List;
  4. import java.util.Map;
  5. import org.slf4j.Logger;
  6. import org.slf4j.LoggerFactory;
  7. import org.slf4j.impl.StaticLoggerBinder;
  8. import org.springframework.web.bind.annotation.RequestMapping;
  9. import org.springframework.web.bind.annotation.RestController;
  10. import ch.qos.logback.classic.Level;
  11. import ch.qos.logback.classic.LoggerContext;
  12. @RestController
  13. public class LoggerController {
  14. private final static Logger logger = LoggerFactory.getLogger(LoggerController.class);
  15. // TODO
  16. }

打印各日志级别的日志

  1. @RequestMapping("/logger/print")
  2. public Map loggerPrint(){
  3. Map result = new HashMap();
  4. result.put("code", 200);
  5. result.put("msg", "success");
  6. logger.debug("loggerPrint debug>>>>");
  7. logger.info("loggerPrint info>>>>");
  8. logger.warn("loggerPrint warn>>>>");
  9. logger.error("loggerPrint error>>>>");
  10. return result;
  11. }
  • 打印日志对象 Logger

    1. @RequestMapping("/logger/printAllLogger")
    2. public Map printAllLogger(){
    3. Map result = new HashMap();
    4. result.put("code", 200);
    5. result.put("msg", "success");
    6. LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
    7. List<ch.qos.logback.classic.Logger> loggers = loggerContext.getLoggerList();
    8. Iterator<ch.qos.logback.classic.Logger> iter = loggers.iterator();
    9. System.out.println("printAllLogger begin>>>>>>>>");
    10. while(iter.hasNext()){
    11. System.out.println(iter.next().getName());
    12. }
    13. System.out.println("printAllLogger end>>>>>>>>");
    14. return result;
    15. }

    该方法打印所有存在的日志对象 Logger

    设置 ROOT 日志对象的日志级别

    1. @RequestMapping("/logger/level")
    2. public Map loggerLevelChange(String level){
    3. Map result = new HashMap();
    4. result.put("code", 200);
    5. result.put("msg", "success");
    6. String loggerFactoryClassStr = StaticLoggerBinder.getSingleton().getLoggerFactoryClassStr();
    7. System.out.println("loggerFactoryClassStr>>>>" + loggerFactoryClassStr);
    8. LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
    9. ch.qos.logback.classic.Logger logger = loggerContext.getLogger("ROOT");
    10. switch (level) {
    11. case "debug":
    12. logger.setLevel(Level.DEBUG);
    13. break;
    14. case "info":
    15. logger.setLevel(Level.INFO);
    16. break;
    17. case "warn":
    18. logger.setLevel(Level.WARN);
    19. break;
    20. case "error":
    21. logger.setLevel(Level.ERROR);
    22. break;
    23. default:
    24. break;
    25. }
    26. return result;
    27. }

    4、编写引导类与测试

    ```java import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication public class Application { public static void main( String[] args ) { SpringApplication.run(Application.class, args); } }

  1. 启动服务
  2. <a name="X9qbi"></a>
  3. ### 打印日志对象 Logger
  4. ![2021-05-13-09-09-20-357154.png](https://cdn.nlark.com/yuque/0/2021/png/396745/1620869197002-e377403a-6f3e-4b8d-b3b6-13c4a8b038a7.png#clientId=u89b1f52f-8a2b-4&from=ui&id=u17d6b43d&margin=%5Bobject%20Object%5D&name=2021-05-13-09-09-20-357154.png&originHeight=378&originWidth=1080&originalType=binary&size=38374&status=done&style=shadow&taskId=u2241a7a0-d852-4acb-abca-80e779fdc32)<br />可以在控制台看到如下日志

printAllLogger begin>>>>>>>> ROOT com.olive.Application com.olive.controller.LoggerController // 省略一万条记录 printAllLogger end>>>>>>>>

  1. <a name="wCeOd"></a>
  2. ### 打印各日志级别的日志
  3. 目前 logback-spring.xml 配置的 ROOT 的日志级别是 info 级别<br />![2021-05-13-09-09-20-590152.png](https://cdn.nlark.com/yuque/0/2021/png/396745/1620869214674-67938ebe-125c-45a7-a7d6-e34e21bd7277.png#clientId=u89b1f52f-8a2b-4&from=ui&id=u3eb822ff&margin=%5Bobject%20Object%5D&name=2021-05-13-09-09-20-590152.png&originHeight=366&originWidth=1080&originalType=binary&size=36958&status=done&style=shadow&taskId=u51baa85a-4766-4f5e-b816-c2b218f2b47)<br />可以看到控制台只打印 info 级别及 info 级别以上的日志
  4. ```sql
  5. 2021-05-12 22:10:27.959 [http-nio-8080-exec-3] INFO com.olive.controller.LoggerController - loggerPrint info>>>>
  6. 2021-05-12 22:10:27.959 [http-nio-8080-exec-3] WARN com.olive.controller.LoggerController - loggerPrint warn>>>>
  7. 2021-05-12 22:10:27.960 [http-nio-8080-exec-3] ERROR com.olive.controller.LoggerController - loggerPrint error>>>>

设置 ROOT 日志对象的日志级别

2021-05-13-09-09-20-796006.png
调用完以上接口后,再次调用 http://127.0.0.1:8080/logger/print 接口。可以看到控制台
2021-05-13-09-09-21-308044.png
打印了大量 debug 级别及 debug 级别以上的日志