searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

Springboot 方法级别调用链路追踪

2024-05-27 06:48:20
5
0

1、定时一个注解

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Trace {

    boolean signature() default true;

    boolean printParams() default true;

    boolean printResult() default false;

    int maxLength() default -1;

}

2、定时一个切面类

@Component
@Aspect
public class TracerAspect {

        @Pointcut("@annotation(xxx.xxx.Trace)")
        public void around() {
        }

        @Around("around() && @annotation(trace)")
        public Object aroundTaskLock(ProceedingJoinPoint joinPoint, Trace trace) throws Throwable {
            if (trace.signature()) {
                log.info("signature: {}", signature(joinPoint, trace.printParams(), trace.plainText(), trace.maxLength()));
            }
            try {
                Object object = joinPoint.proceed();
                try {
                    traceReturn(joinPoint, object, trace);
                } catch (Exception e) {
                    log.info("exception thrown traceReturn: [{}]", object.getClass().getName());
                }
                return object;
            } catch (Throwable e) {
                log.info("exception thrown: {}", e.getMessage(), e);
                throw e;
            }
        }


        private String signature(JoinPoint joinPoint, boolean printParams, boolean plainText, int maxLength) {
            try {
                Class<?> targetClass = joinPoint.getTarget().getClass();
                CodeSignature signature = (CodeSignature) joinPoint.getSignature();
                List<String> params = new ArrayList<>();
                if (printParams) {
                    String[] parameterNames = signature.getParameterNames();
                    Object[] args = joinPoint.getArgs();
                    IntStream.range(0, parameterNames.length).forEach(index -> {
                        Object arg = args[index];
                        if (!(arg instanceof HttpServletRequest || arg instanceof HttpServletResponse || arg instanceof BindingResult)) {
                            if (null == arg) {
                                params.add(parameterNames[index] + "=null");
                            } else if (arg instanceof MultipartFile) {
                                params.add(parameterNames[index] = "=multipartFile");
                            } else if (arg instanceof MultipartFile[]) {
                                params.add(parameterNames[index] + "=" + ((MultipartFile[]) arg).length + "multipartFiles");
                            } else if (arg instanceof InputStream) {
                                params.add(parameterNames[index] + "=inputStream");
                            } else if (arg instanceof InputStream[]) {
                                params.add(parameterNames[index] + "=inputStream[]");
                            } else if (arg instanceof OutputStream) {
                                params.add(parameterNames[index] + "=outputStream");
                            } else if (arg instanceof OutputStream[]) {
                                params.add(parameterNames[index] + "=outputStream]");
                            } else if (arg instanceof Closeable) {
                                params.add(parameterNames[index] + "=stream");
                            } else if (arg instanceof Closeable[]) {
                                params.add(parameterNames[index] + "=stream[]");
                            } else {
                                params.add(parameterNames[index] + "=" + JSONObject.toJSONString(arg));
                            }
                        }
                    });
                }
                final String paramsStr = printParams ? params.stream().map(param -> {
                    String p = (maxLength != -1 && maxLength > 0) ? param.substring(0, Math.min(param.length(), maxLength)) : param;
                    String msg = plainText ? p : stringToHex(p);
                    return msg;
                }).collect(Collectors.joining(", ")) : "";
                return FormatUtil.format(printParams ? "{}.{}({})" : "{}.{}", targetClass.getCanonicalName(), signature.getName(), paramsStr);
            } catch (Exception e) {
                // ignore
            }
            return "";
        }

        private void traceReturn(ProceedingJoinPoint joinPoint, Object object, Trace trace) {
            CommonUtil.isTrue(trace.printResult(), () -> {
                String msg = null == object ? "null" : object instanceof Closeable ? "closeable stream" : JSONObject.toJSONString(object);
                msg = trace.maxLength() == -1 ? msg : msg.length() <= trace.maxLength() ? msg : msg.substring(0, trace.maxLength());
                msg = trace.plainText() ? msg : stringToHex(msg);
                log.info("{} ret result: [{}]", signature(joinPoint, false, true, -1), msg);
            });
        }
    }

3、在需要追踪调用的方法上添加Trace注解

4、注解参数说明:

      signature: 是否需要打印方法签名

      printParams: 是否需要打印方法参数

      printResult:是否需要打印返回参数

      maxLength:最大打印长度

5、在参数打印上,如果是流则不会对其进行打印,避免后缀方法对流的使用造成影响。

 

0条评论
0 / 1000
洪****能
3文章数
0粉丝数
洪****能
3 文章 | 0 粉丝
洪****能
3文章数
0粉丝数
洪****能
3 文章 | 0 粉丝
原创

Springboot 方法级别调用链路追踪

2024-05-27 06:48:20
5
0

1、定时一个注解

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Trace {

    boolean signature() default true;

    boolean printParams() default true;

    boolean printResult() default false;

    int maxLength() default -1;

}

2、定时一个切面类

@Component
@Aspect
public class TracerAspect {

        @Pointcut("@annotation(xxx.xxx.Trace)")
        public void around() {
        }

        @Around("around() && @annotation(trace)")
        public Object aroundTaskLock(ProceedingJoinPoint joinPoint, Trace trace) throws Throwable {
            if (trace.signature()) {
                log.info("signature: {}", signature(joinPoint, trace.printParams(), trace.plainText(), trace.maxLength()));
            }
            try {
                Object object = joinPoint.proceed();
                try {
                    traceReturn(joinPoint, object, trace);
                } catch (Exception e) {
                    log.info("exception thrown traceReturn: [{}]", object.getClass().getName());
                }
                return object;
            } catch (Throwable e) {
                log.info("exception thrown: {}", e.getMessage(), e);
                throw e;
            }
        }


        private String signature(JoinPoint joinPoint, boolean printParams, boolean plainText, int maxLength) {
            try {
                Class<?> targetClass = joinPoint.getTarget().getClass();
                CodeSignature signature = (CodeSignature) joinPoint.getSignature();
                List<String> params = new ArrayList<>();
                if (printParams) {
                    String[] parameterNames = signature.getParameterNames();
                    Object[] args = joinPoint.getArgs();
                    IntStream.range(0, parameterNames.length).forEach(index -> {
                        Object arg = args[index];
                        if (!(arg instanceof HttpServletRequest || arg instanceof HttpServletResponse || arg instanceof BindingResult)) {
                            if (null == arg) {
                                params.add(parameterNames[index] + "=null");
                            } else if (arg instanceof MultipartFile) {
                                params.add(parameterNames[index] = "=multipartFile");
                            } else if (arg instanceof MultipartFile[]) {
                                params.add(parameterNames[index] + "=" + ((MultipartFile[]) arg).length + "multipartFiles");
                            } else if (arg instanceof InputStream) {
                                params.add(parameterNames[index] + "=inputStream");
                            } else if (arg instanceof InputStream[]) {
                                params.add(parameterNames[index] + "=inputStream[]");
                            } else if (arg instanceof OutputStream) {
                                params.add(parameterNames[index] + "=outputStream");
                            } else if (arg instanceof OutputStream[]) {
                                params.add(parameterNames[index] + "=outputStream]");
                            } else if (arg instanceof Closeable) {
                                params.add(parameterNames[index] + "=stream");
                            } else if (arg instanceof Closeable[]) {
                                params.add(parameterNames[index] + "=stream[]");
                            } else {
                                params.add(parameterNames[index] + "=" + JSONObject.toJSONString(arg));
                            }
                        }
                    });
                }
                final String paramsStr = printParams ? params.stream().map(param -> {
                    String p = (maxLength != -1 && maxLength > 0) ? param.substring(0, Math.min(param.length(), maxLength)) : param;
                    String msg = plainText ? p : stringToHex(p);
                    return msg;
                }).collect(Collectors.joining(", ")) : "";
                return FormatUtil.format(printParams ? "{}.{}({})" : "{}.{}", targetClass.getCanonicalName(), signature.getName(), paramsStr);
            } catch (Exception e) {
                // ignore
            }
            return "";
        }

        private void traceReturn(ProceedingJoinPoint joinPoint, Object object, Trace trace) {
            CommonUtil.isTrue(trace.printResult(), () -> {
                String msg = null == object ? "null" : object instanceof Closeable ? "closeable stream" : JSONObject.toJSONString(object);
                msg = trace.maxLength() == -1 ? msg : msg.length() <= trace.maxLength() ? msg : msg.substring(0, trace.maxLength());
                msg = trace.plainText() ? msg : stringToHex(msg);
                log.info("{} ret result: [{}]", signature(joinPoint, false, true, -1), msg);
            });
        }
    }

3、在需要追踪调用的方法上添加Trace注解

4、注解参数说明:

      signature: 是否需要打印方法签名

      printParams: 是否需要打印方法参数

      printResult:是否需要打印返回参数

      maxLength:最大打印长度

5、在参数打印上,如果是流则不会对其进行打印,避免后缀方法对流的使用造成影响。

 

文章来自个人专栏
开发指引
3 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0