• 猿创征文|Spring Boot日志


    在这里插入图片描述

    日志介绍

    记录日志的好处

    1. 记录应用系统曰志主要有三个原因:记录操作轨迹、监控系统运行状况、回溯系统故障。

    记录操作行为及操作轨迹数据,可以数据化地分析用户偏好,有助于优化业务逻辑,为用户提供个性化的服务。例如,通过 access.log 记录用户的操作频度和跳转链接,有助于分析用户的后续行为。

    2. 全面有效的日志系统有助于建立完善的应用监控体系,由此工程师可以实时监控系统运行状况,及时预警,避免故障发生。

    监控系统运行状况,是指对服务器使用状态,如内存、CPU 等使用情况,应用运行情况,如响应时间QPS等交互状态;应用错误信息,如空指针、SQL异常等的监控。例如,在CPU使用率大于60%,四核服务器中load 大于4时发出报警,提醒工程师及时处理,避免发生故障。

    3. 当系统发生线上问题时,完整的现场日志有助于工程师快速定位问题。

    例如当系统内存溢出时,如果日志系统记录了问题发生现场的堆信息,就可以通过这个曰志分析是什么对象在大量产生并且没有释放内存,回溯系统故障,从而定位问题。

    日志框架

    日志门面日志实现
    JCL(Jakarta Commons Logging)Java最早的一套日志标准 、SLF4j(Simple Logging Facade for Java)、 jboss-loggingLog4j 、JUL(java.util.logging)、 Log4j2 (兼容性不强)、 Logback

    日志门面

    门面设计模式是面向对象设计模式中的一种,日志框架采用的就是这种模式,类似JDBC的设计理念。它只提供一套接口规范,自身不负责日志功能的实现。目的是让使用者不需要关注底层具体是哪个日志库来负责日志打印及具体的使用细节等。目前用得最为广泛的是slf4j

    日志门面是一种门面设计模式,为了提高程序的扩展性给的一套类似于JDBC的接口,只需设定规则,具体的细节都留给对应实现

    日志库

    负责实现日志的相关功能,主流日志库有三个,分别是

    log4j、log-jdk (java.util.logging.Logger)、logback是最晚出现的,与log4j同一个作者,是log4j的升级版且本身实现了slf4j的接口。

    日志适配器

    老工程直接使用日志库API完成日志打印,要改成业界标准的门面模式(如slf4j+logback),但是老工程代码打印日志地方太多难以改动,这时就需要一个适配器来完成从旧日志库的API到slf4j的路由,这样在不改动原有代码的情况下也能使用slf4j来统一管理日志(如:log4j-over-slf4j),后续自由替换具体日志库也不成问题。

    日志体系

    在开发的时候不应该直接使用日志实现类,应该使用日志的抽象层。。具体参考SLF4J官方

    下图是SLF4J结合各种日志框架的官方示例,从图中可以清晰的看出SLF4J API永远作为日志的门面,直接应用与应用程序中。

    在这里插入图片描述

    spring boot的底层spring-boot-starter-logging可以看出,它依赖3个日志框架:slf4j、Logback和Log4j2。

    它们的区别是:

    • logback和log4j是日志实现框架,就是实现怎么记录日志的。
    • slf4j-api提供了java所有日志框架的简单规范和标准(日志的门面设计模式)说白了就是一个日志API(没有实现类),它不能单独使用;故必须结合logback和Log4j2日志框架

    注意:spring Boot采用了slf4j+logback的组合形式,Spring Boot也提供对JUL、log4j2.Logback提供了默认配置

    注意:由于每一个日志的实现框架都有自己的配置文件,所以在使用SLF4j之后,配置文件还是要使用实现日志框架的配置文件。

    日志的使用

    日志级别和格式

    从上面的分析,发现 Spring Boot默认已经使用了SLF4J+LogBack 。所以我们在不进行任何额外操作的情况下就可以使用SLF4J + Logback 进行日志输出。
    日志的级别分为6种:

    • TRACE:运行堆栈信息,使用率低
    • DEBUG:程序员调试代码使用
    • INFO:记录运维过程数据
    • WARN:记录运维过程报警数据
    • ERROR:记录错误堆栈信息
    • FATAL:灾难信息,合并计入ERROR

    编写测试类测试

    package com.example.springboot.controller;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class HelloController {
    
        //获取日志对象 Logger
        Logger logger = LoggerFactory.getLogger(HelloController.class);
    
        @GetMapping("/hello")
        public String hello(){
            logger.debug("debug...");
            logger.info("info...");
            logger.warn("warn...");
            logger.error("error...");
    
            return "Hello SpringBoot!";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    application.yml

    server:
      port: 80
    
    # 设置日志级别会给root根节点设置,代表整体应用的级别
    #logging:
    #  level:
    #    root: debug
    # 设置组的日志级别或包的日志级别
    logging:
      group:
        mygroup: com.example.springboot.controller
      level:
        root: warn
        # 给组设置日志级别
        mygroup: debug
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    获取日志对象

    • 导入Lombok依赖
    <dependency>
        <groupId>org.projectlombokgroupId>
        <artifactId>lombokartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 添加@Slf4j注解
    package com.example.springboot.controller;
    
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @Slf4j
    @RestController
    public class HelloController {
    
        @GetMapping("/hello")
        public String hello(){
        
            log.debug("debug...");
            log.info("info...");
            log.warn("warn...");
            log.error("error...");
    
            return "Hello SpringBoot!";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    哪里需要用到日志,那里添加注解即可

    日志格式

    Spring Boot默认输出的日志格式如下:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7WIc5PPR-1662713658756)(C:\Users\19737\AppData\Local\Temp\1662687149165.png)]

    • 日期和时间:毫秒精度,易于排序
    • 日志级别:ERRORWARNINFODEBUGTRACE
    • 进程标识
    • — :用于区分实际日志开始的分隔符
    • 线程名称:在方括号内
    • 记录器名称:通常为源类名称
    • 日志消息

    日志格式配置

    # 修改日志级别
    logging:
      # 设置日志格式
      pattern:
        #控制台输出格式
        #格式化输出: %d :表示日期   %thread:表示线程名  
        # %-5level:级别从左显示5个字符宽度   %msg :日志消息   %n :是换行符
        console: "[console]==%d{yyyy-MM-dd HH:mm:ss:SSS} [%thread] %-5level %logger - %msg%n"
        # 文件输出格式
        file: "[file]===%d{yyyy-MM-dd HH:mm:ss:SSS} [%thread] %-5level %logger - %msg%n"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    日志格式配置信息如下:

    • %d或者%date:指定日志的日期。默认是ISO8601的标准日期,相当于yyyy-MM-dd HH:mm:ss:SSS
    • %level:指定日志的级别: Trace > Debug > Info> Warn> Error
    • %logger:指定日志输出的包名+类名,{n}可以限定长度,比如: %logger{50}
    • %M:指定日志发生时的方法名
    • %L:指定日志调用时所在的行。线下运行的时候不建议使用此参数,因为获取代码的行号对性能有损耗
    • %m或者%msg:表示日志的输出的内容
    • %n :日志是否换行
    • %thread:打印线程的名字

    彩色编码输出

    如果您的终端支持ANSI,则使用颜色输出来提高可读性。您可以设置spring.output.ansi.enabled为支持的值以覆盖自动检测。
    使用%clr转换字配置颜色编码。在最简单的形式中,转换器根据日志级别为输出着色,如以下所示:
    %clr(%5p)
    下表描述了日志级别到颜色的映射:

    等级颜色
    FATAL红色
    ERROR红色
    WARN黄色
    INFO绿色
    DEBUG绿色
    TRACE绿色

    或者,您可以通过将其作为转换选项提供来指定应使用的颜色或样式。例如,要使文本变黄,请使用以下设置:

    %clr(%d{yyyy-MM-dd HH:mm:ss:SSS}){yello}

    支持的颜色有:blue cyan faint green magenta red yellow

    因此我们可以自己编写日志的输出格式如下:

    logging:
      pattern:
        console: "%d %clr(%p){green} ---[%16t] %m%n"
    
    • 1
    • 2
    • 3

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xGuFfC2h-1662713658756)(C:\Users\19737\AppData\Local\Temp\1662692874120.png)]

    自定义日志输出

    日志不能仅显示在控制台上,要把日志记录到文件中,方便后期维护查阅。

    对于日志文件的使用存在各种各样的策略,例如每日记录,分类记录,报警后记录等。这里主要研究日志文件如何记录。

    logging:
      file:
        name: tomcat.log
    
    • 1
    • 2
    • 3

    虽然使用上述格式可以将日志记录下来了,但是面对线上的复杂情况,一个文件记录肯定是不能够满足运维要求的,通常会每天记录日志文件,同时为了便于维护,还要限制每个日志文件的大小。下面给出日志文件的常用配置方式:

    logging:
      logback:
        rollingpolicy:
          max-file-size: 2MB
          file-name-pattern: server.%d{yyyy-MM-dd}.%i.log
    
    • 1
    • 2
    • 3
    • 4
    • 5

    以上格式是基于logback日志技术设置每日日志文件的设置格式,要求容量到达2MB以后就转存信息到第二个文件中。文件命名规则中的%d标识日期,%i是一个递增变量,用于区分日志文件。

    替换日志框架

    查看官方文档,可以看到我们可以在 Log4j 和 logging 之间二选一。

    官方是这样描述Log4j的:An alternative to spring-boot-starter-logging

    翻译过来就是:spring-boot-starter-logging的替代方案。

    在这里插入图片描述

    所以下面来展示如何将 logging 替换为 Log4j

    • 第一步:排除spring-boot-starter-logging依赖
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-logging</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 第二步:添加spring-boot-starter-Log4j2依赖
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-log4j2</artifactId>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4
  • 相关阅读:
    Redis设置失效时间
    java装饰器模式
    食品行业申请ISO22000认证条件、流程、资料及意义有哪些
    手撕单链表(C语言)
    centos7安装adb工具(拒绝抄袭)
    我用低代码平台,简单搭建了一套管理系统
    【SSL 1589】汉明距离(NTT)
    毕设选题推荐基于python的django框架医院预约挂号系统
    Three.js 入门(一)— 开发环境搭建
    CentOS断电丢失数据修复问题
  • 原文地址:https://blog.csdn.net/weixin_52986315/article/details/126786154