为了账号安全,请及时绑定邮箱和手机立即绑定

SpringBoot查询日志:添加日志跟踪id

标签:
SpringBoot

1.起源:

(1)业务需求:

代码的功能是写一个api接口,完成与mysql的crud操作。
后台使用SpringBoot+JdbcTemplate实现,并在controller层添加了一些请求、响应、异常处理的日志;

(2)问题产生:

由于该api接口是多方调用的,当高并发场景调用这个api时,从controller层一路下来,日志的记录将会非常混乱,所有业务日志都掺杂在一起。比如像下面这样:

webp

(3)一种解决方法:

当产生异常日志时,特别是高并发的情况下,作为服务端,你并不知道某条error日志报的错对应的是哪条请求,除非将请求信息打印在日志中,但是仔细想想,这就需要所有需要添加日志的类都带着请求信息,显然这太难做到了,同时日志文件也将不堪重负。

2.更好的解决方案

有没有想到过日志跟踪呢?如果不管是谁调用接口,在其每次调用的时候,代码都自动加上一个唯一的id该多好,不管这次请求是到了service层、dao层、甚至bean层,只要是调用controller里面的接口,所有这条请求的日志流都加上了这个唯一的id,这样再查找日志的时候,将会很方便。

而怎么才能在不影响已经写好业务逻辑的情况下,对日志流做统一处理呢?当然是要想到AOP了~!

具体操作如下:

(1)先配上aop的maven依赖(已经有aop就不用再加了),这里要注意spring-aop的版本对应上spring-core的版本:
     <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>4.3.10.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.8.13</version>
    </dependency>
(2)再添加AOP处理类~!这里只针对controller层。(不太了解aop配置的需要补习一下基本的配置方法)
package com.tools.pincollect.common;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.AfterReturning;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.annotation.Pointcut;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.slf4j.MDC;import org.springframework.stereotype.Component;import java.util.Arrays;import java.util.UUID; 
@Aspect@Configurationpublic class SpringAOP { 
    private static final Logger logger = LoggerFactory.getLogger(SpringAOP.class); 
    /**
     * 定义切点Pointcut
     * 第一个*号:表示返回类型, *号表示所有的类型
     * 第二个*号:表示类名,*号表示所有的类
     * 第三个*号:表示方法名,*号表示所有的方法
     * 后面括弧里面表示方法的参数,两个句点表示任何参数
     */
    @Pointcut("execution(*  com.tools.pincollect.controller.*.*(..))")    public void executionService() {} 
    /**
     * 方法调用之前调用
     * @param joinPoint
     */
    @Before(value = "executionService()")    public void doBefore(JoinPoint joinPoint){
        String requestId = String.valueOf(UUID.randomUUID());
        MDC.put("requestId",requestId);
        logger.info("=====>@Before:请求参数为:{}",Arrays.toString(joinPoint.getArgs()));
    } 
    /**
     * 方法之后调用
     * @param joinPoint
     * @param returnValue 方法返回值
     */
    @AfterReturning(pointcut = "executionService()",returning="returnValue")    public void  doAfterReturning(JoinPoint joinPoint,Object returnValue){
        logger.info("=====>@AfterReturning:响应参数为:{}",returnValue);        // 处理完请求,返回内容
        MDC.clear();
    }
}
(3)在项目resources目录下的logback-spring.xml中修改日志pattern(不了解的话,这里需要补充下日志配置的知识),添加[%X{requestId}],requestId就是在切面类中的MCD.put()方法中的key,如下图所示:
   <pattern>
        [ %-5level] [%date{yyyy-MM-dd HH:mm:ss}] [%X{requestId}] %logger{96} [%line] - %msg%n    </pattern>

webp

添加了跟踪id后的日志.png



作者:师傅的米糕
链接:https://www.jianshu.com/p/08f5231c3d32


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消