package com.xiaopeng.automaticPilot.config.log;
|
|
import com.alibaba.fastjson.JSON;
|
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.reflect.MethodSignature;
|
import org.springframework.stereotype.Component;
|
|
import java.lang.reflect.Method;
|
import java.util.Arrays;
|
|
/**
|
* Feign 调用日志切面
|
*
|
* <p>拦截 com.ros.feign 包下所有 Feign 接口方法,记录:
|
* <ul>
|
* <li>调用的接口类名 + 方法名</li>
|
* <li>入参(JSON 序列化)</li>
|
* <li>出参(JSON 序列化)</li>
|
* <li>耗时(ms)</li>
|
* <li>异常信息(含完整堆栈)</li>
|
* </ul>
|
*
|
* <p>同时覆盖任何实现了 Feign 接口的 bean(包括 SecureGatewayFeignService 等外部引入的客户端),
|
* 通过第二个切点 {@code feignBeanMethods()} 拦截。
|
*/
|
@Slf4j
|
@Aspect
|
@Component
|
public class FeignLoggingAspect {
|
|
/**
|
* 切点1:com.ros.feign 包下所有类的所有方法
|
* 覆盖 UserCenterFeign、RobotFeign、MappingServiceFeign、VmpRobotFeign 等
|
*/
|
@Around("execution(* com.ros.feign..*(..))")
|
public Object logRosFeignCall(ProceedingJoinPoint pjp) throws Throwable {
|
return doLog(pjp);
|
}
|
|
/**
|
* 切点2:所有带 @FeignClient 注解的接口的实现 bean 的所有方法
|
* 覆盖 SecureGatewayFeignService 等外部包引入的 Feign 客户端
|
*/
|
@Around("within(@org.springframework.cloud.openfeign.FeignClient *)")
|
public Object logExternalFeignCall(ProceedingJoinPoint pjp) throws Throwable {
|
return doLog(pjp);
|
}
|
|
private Object doLog(ProceedingJoinPoint pjp) throws Throwable {
|
MethodSignature signature = (MethodSignature) pjp.getSignature();
|
Method method = signature.getMethod();
|
String className = pjp.getTarget().getClass().getSimpleName();
|
String methodName = method.getName();
|
String fullMethod = className + "#" + methodName;
|
|
Object[] args = pjp.getArgs();
|
String argsJson = safeToJson(args);
|
|
log.info("[Feign] >>> 调用开始 | method={} | args={}", fullMethod, argsJson);
|
|
long start = System.currentTimeMillis();
|
try {
|
Object result = pjp.proceed();
|
long elapsed = System.currentTimeMillis() - start;
|
String resultJson = safeToJson(result);
|
log.info("[Feign] <<< 调用成功 | method={} | elapsed={}ms | result={}", fullMethod, elapsed, resultJson);
|
return result;
|
} catch (Throwable ex) {
|
long elapsed = System.currentTimeMillis() - start;
|
log.error("[Feign] <<< 调用异常 | method={} | elapsed={}ms | error={} | args={}",
|
fullMethod, elapsed, ex.getMessage(), argsJson, ex);
|
throw ex;
|
}
|
}
|
|
/**
|
* 安全序列化为 JSON,避免序列化失败导致日志切面本身抛异常
|
*/
|
private String safeToJson(Object obj) {
|
if (obj == null) {
|
return "null";
|
}
|
try {
|
if (obj instanceof Object[]) {
|
return JSON.toJSONString(Arrays.asList((Object[]) obj));
|
}
|
return JSON.toJSONString(obj);
|
} catch (Exception e) {
|
return "[序列化失败: " + obj.getClass().getSimpleName() + "]";
|
}
|
}
|
}
|