文章目录
概述
日志记录是现代应用程序开发中的重要组成部分。然而,在实际开发中,我们经常面临一些痛点:
- 重复打印出入参:在开发中经常需要在每个方法中手动编写日志代码,这样的工作不仅重复,而且使代码显得冗余和杂乱。
- 统一的追踪标识: 在排查问题时,我们经常通过接口请求信息去查日志,这个时候我们一般需要一个traceId将所有请求串起来,这几乎是每个方法都必须实现的功能:打印traceId。
- 接口requestId的返回: 为了方便上下游查问题,一般在接口设计时,响应体都包含一个requestId字段,这个 requestId 字段,一般就是我们打印的traceId。如果我们每次都手动设置,需要对各种返回情况(如204、500)等进行判断,显得代码杂乱和臃肿。
- 接口耗时打印:我们需要记录每个功能耗时的情况,方便性能问题排查。
使用 Spring AOP和Logback
来封装日志打印组件
1. 引入相关依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
2. 创建Aop切面
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gis.components.dto.Response;
import com.gis.components.dto.StatusCode;
import com.gis.components.exception.BizException;
import com.gis.components.exception.SysException;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.MDC;
import org.springframework.core.annotation.AnnotationUtils;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.UUID;
import java.util.function.Function;
@Slf4j
@Aspect
public class LogAspect {
private static ObjectMapper objectMapper = new ObjectMapper();
public static final String REQUEST_TRACE_ID = "REQUEST_TRACE_ID";
/**
* @LogTag 注解拦截器
* 在方法执行前后记录日志,并在出现异常时抛出RuntimeException。
* @param proceedingJoinPoint 切入点对象,提供了对目标方法的控制权。
* @return 目标方法的执行结果。
*/
@Pointcut("execution(* com.yourpackage..*(..))")
public Object logExecution(ProceedingJoinPoint proceedingJoinPoint) {
return logExecutionInner(proceedingJoinPoint,e -> {
throw new