• 【工具】方法日志打印+任务切片


    @

    方法日志打印

    最近开发遇到的一个问题是关于日志打印。日志非常重要,通过查看日志,我们可以快速排查问题。
    我们项目的整个系统内网关处做了拦截,能够看到前端传过来的日志,但是内部服务间调用,服务间的入参与出参看不到;还有,一些重要的方法如果要看到入参和出参,只能一个个去写log方法。
    这种重复的工作非常适合使用切面来写一些小工具。下面是我写的小工具,下面方法几乎是搬运一位老哥写的博客,老哥的博客找不见了,sorry。

    定义注释类

    /**
     * @Description 打印参数
     * @Author lkb
     * @CreateDate: 2021/3/25
     */
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    public @interface MethodLog {
    }
    

    AOP 打印输入输出参数

    /**
     * @Description
     * @Author lkb
     * @CreateDate: 2021/3/25
     */
    @Aspect
    @Component
    @Slf4j
    public class MethodLogAspect {
    
        @Pointcut("@annotation(com.....annotion.MethodLog)")
        public void pointCut(){}
    
        @Around(value = "pointCut()")
        public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
            try{
                MethodSignature signature = (MethodSignature) joinPoint.getSignature();
                Method method = signature.getMethod();
                MethodLog annotation = method.getAnnotation(MethodLog.class);
                if (Objects.isNull(annotation)){
                    try {
                        return joinPoint.proceed();
                    } catch (Throwable throwable) {
                        log.error("method proceed fail. e = {}", throwable.getMessage(), throwable);
                        throw throwable;
                    }
                }else{
                    String methodName = method.getDeclaringClass().getSimpleName() + "." + method.getName();
                    log.info("methodName: "+methodName);
                    Object[] args = joinPoint.getArgs();
                    log.info("param: " + JsonUtil.toJSON(args));
    
                    Instant start = Instant.now();
                    log.info("method start. methodName = {}", methodName);
                    Object result = null;
                    try {
                        // 这里的result记得return
                        result = joinPoint.proceed();
                    } catch (Throwable throwable) {
                        log.error("method proceed fail. e = {}", throwable.getMessage(), throwable);
                        throw throwable;
                    }
    
                    log.info("method end. methodName = {}, cost = {}", methodName, ChronoUnit.MILLIS.between(start, Instant.now()));
    
                    return result;
                }
            }catch (Exception e){
                log.error("MethodLogAspect around fail. e= {}", e.getMessage(), e);
                throw e;
            }
        }
    }
    

    任务切片

    遇到的第二个问题是,
    在一个调用中,需要多次调用外部系统的服务,本来应该使用MQ去解耦,但是因为多方面原因只能维持现状(我们服务多次调用外部系统的服务)。这样导致整个请求特别慢,上线多台设备的时候可能需要十几二十秒。
    与其他两个系统的交互互不影响,相互独立。因此,我想到使用任务切片的方式来加快执行速度。
    下面是我写的任务切片小工具。

    DTO

    /**
     * @Description
     * @Author lkb
     * @CreateDate: 2021/3/26
     */
    @Data
    public class AsynTaskDTO<T, R> {
    
        public T param;
    
        public Function<T, R> function;
    
        public R resultData;
    
        public Boolean result;
    
        public String key;
    
        public AsynTaskDTO(Function<T,R> function, T param){
            this.function = function;
            this.param = param;
            this.result = false;
            this.key = String.valueOf(param.hashCode());
        }
    
    }
    

    任务切片实现类

    /**
     * @Description
     * @Author lkb
     * @CreateDate: 2021/3/26
     */
    @Slf4j
    @Getter
    public class AsynTaskUtil {
    
        private static final ForkJoinPool ASYNC_IO_POOL = new ForkJoinPool((Runtime.getRuntime().availableProcessors() << 1) + 1);
    
        private List<AsynTaskDTO> taskDTOS;
    
        public AsynTaskUtil(List<AsynTaskDTO> taskDTOS){
            this.taskDTOS = taskDTOS;
        }
    
        public boolean doTask(){
            CompletableFuture[] futures = taskDTOS.stream().map(task -> CompletableFuture.runAsync(() -> {
                try{
                    task.setResultData(task.getFunction().apply(task.getParam()));
                    task.setResult(true);
                }catch (Exception e){
                    log.error("AsynTaskUtil doTask fail. e = {}" + e.getMessage(), e);
                    task.setResult(false);
                }
            }, ASYNC_IO_POOL)).toArray(CompletableFuture[]::new);
    
            CompletableFuture.allOf(futures).join();
    
            boolean f = taskDTOS.stream().anyMatch(t -> Objects.equals(false, t.getResult()));
            return !f;
        }
    }
    
    欢迎关注我的公众号 -- 大白和小倔
  • 相关阅读:
    Python selenium —— 一定要会用selenium的等待,三种等待方式解读
    python3 selenium 切换窗口的几种方法
    转:对UI自动化测试的一些感悟
    Docker
    【转】selenium之 定位以及切换frame
    selenium——键盘操作
    selenium——鼠标事件
    python 读取Excel表格方法
    springboot maven 更新jar包速度慢的问题
    Python3 读写utf-8文本文件
  • 原文地址:https://www.cnblogs.com/catlkb/p/14614204.html
Copyright © 2020-2023  润新知