| | |
| | | //package com.xiaopeng.trafficControl.config.log; |
| | | // |
| | | //import com.alibaba.fastjson2.JSON; |
| | | //import com.xiaopeng.common.log.config.LogHeaderProperties; |
| | | //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.beans.factory.annotation.Autowired; |
| | | //import org.springframework.stereotype.Component; |
| | | //import org.springframework.web.context.request.RequestContextHolder; |
| | | //import org.springframework.web.context.request.ServletRequestAttributes; |
| | | // |
| | | //import javax.servlet.http.HttpServletRequest; |
| | | //import java.lang.reflect.Method; |
| | | //import java.util.Arrays; |
| | | //import java.util.Enumeration; |
| | | //import java.util.List; |
| | | // |
| | | ///** |
| | | // * Feign 调用日志切面 |
| | | // * |
| | | // * <p>拦截所有带 @FeignClient 注解的接口方法,记录: |
| | | // * <ul> |
| | | // * <li>调用的接口类名 + 方法名</li> |
| | | // * <li>入参(JSON 序列化)</li> |
| | | // * <li>出参(JSON 序列化)</li> |
| | | // * <li>耗时(ms)</li> |
| | | // * <li>异常信息(含完整堆栈)</li> |
| | | // * </ul> |
| | | // */ |
| | | //@Slf4j |
| | | //@Aspect |
| | | //@Component |
| | | //public class FeignLoggingAspect { |
| | | // |
| | | // @Autowired |
| | | // private LogHeaderProperties logHeaderProperties; |
| | | // |
| | | // /** |
| | | // * 拦截所有带 @FeignClient 注解的接口的所有方法 |
| | | // */ |
| | | // @Around("within(@org.springframework.cloud.openfeign.FeignClient *)") |
| | | // public Object logFeignCall(ProceedingJoinPoint pjp) throws Throwable { |
| | | // return doLog(pjp); |
| | | // } |
| | | // |
| | | // private Object doLog(ProceedingJoinPoint pjp) throws Throwable { |
| | | // MethodSignature signature = (MethodSignature) pjp.getSignature(); |
| | | // Method method = signature.getMethod(); |
| | | // // 使用接口声明类名,避免打印动态代理类名(如 $Proxy270) |
| | | // String className = signature.getDeclaringType().getSimpleName(); |
| | | // String methodName = method.getName(); |
| | | // String fullMethod = className + "#" + methodName; |
| | | // |
| | | // Object[] args = pjp.getArgs(); |
| | | // String argsJson = safeToJson(args); |
| | | // String headerStr = extractCurrentHeaders(); |
| | | // |
| | | // if (headerStr != null) { |
| | | // log.info("[Feign] >>> 调用开始 | method={} | headers={} | args={}", fullMethod, headerStr, argsJson); |
| | | // } else { |
| | | // 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() + "]"; |
| | | // } |
| | | // } |
| | | // |
| | | // /** |
| | | // * 从当前请求上下文中提取请求头信息 |
| | | // */ |
| | | // private String extractCurrentHeaders() { |
| | | // if (!logHeaderProperties.isEnabled()) { |
| | | // return null; |
| | | // } |
| | | // try { |
| | | // ServletRequestAttributes attrs = (ServletRequestAttributes) |
| | | // RequestContextHolder.getRequestAttributes(); |
| | | // if (attrs == null) return "{}"; |
| | | // HttpServletRequest request = attrs.getRequest(); |
| | | // List<String> names = logHeaderProperties.getNames(); |
| | | // StringBuilder sb = new StringBuilder("{"); |
| | | // boolean first = true; |
| | | // if (names != null && !names.isEmpty()) { |
| | | // for (String name : names) { |
| | | // String value = request.getHeader(name); |
| | | // if (value != null) { |
| | | // if (!first) sb.append(", "); |
| | | // first = false; |
| | | // sb.append(name).append("=").append(value); |
| | | // } |
| | | // } |
| | | // } else { |
| | | // Enumeration<String> headerNames = request.getHeaderNames(); |
| | | // while (headerNames != null && headerNames.hasMoreElements()) { |
| | | // String name = headerNames.nextElement(); |
| | | // String value = request.getHeader(name); |
| | | // if (!first) sb.append(", "); |
| | | // first = false; |
| | | // sb.append(name).append("=").append(value); |
| | | // } |
| | | // } |
| | | // return sb.append("}").toString(); |
| | | // } catch (Exception e) { |
| | | // return "{error: " + e.getMessage() + "}"; |
| | | // } |
| | | // } |
| | | //} |
| | | package com.xiaopeng.trafficControl.config.log; |
| | | |
| | | import com.alibaba.fastjson2.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>拦截所有带 @FeignClient 注解的接口方法,记录: |
| | | * <ul> |
| | | * <li>调用的接口类名 + 方法名</li> |
| | | * <li>入参(JSON 序列化)</li> |
| | | * <li>出参(JSON 序列化)</li> |
| | | * <li>耗时(ms)</li> |
| | | * <li>异常信息(含完整堆栈)</li> |
| | | * </ul> |
| | | */ |
| | | @Slf4j |
| | | @Aspect |
| | | @Component |
| | | public class FeignLoggingAspect { |
| | | |
| | | /** |
| | | * 拦截所有带 @FeignClient 注解的接口的所有方法 |
| | | */ |
| | | @Around("within(@org.springframework.cloud.openfeign.FeignClient *)") |
| | | public Object logFeignCall(ProceedingJoinPoint pjp) throws Throwable { |
| | | return doLog(pjp); |
| | | } |
| | | |
| | | private Object doLog(ProceedingJoinPoint pjp) throws Throwable { |
| | | MethodSignature signature = (MethodSignature) pjp.getSignature(); |
| | | Method method = signature.getMethod(); |
| | | // 使用接口声明类名,避免打印动态代理类名(如 $Proxy270) |
| | | String className = signature.getDeclaringType().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() + "]"; |
| | | } |
| | | } |
| | | } |