qqxx6661 / log-record

使用注解优雅记录系统日志,操作日志,后端埋点等,支持SpEL表达式,自定义上下文,自定义函数,实体类DIFF等其他高阶处理。
Apache License 2.0
894 stars 165 forks source link

SystemLogAspect 中 原方法执行异常时的logDTOList 添加数据有问题 #78

Closed fish-liu closed 1 year ago

fish-liu commented 1 year ago
    // 原方法执行异常
    catch (Throwable throwable) {
        // 方法异常执行后日志切面
        try {
            if (stopWatch != null) {
                stopWatch.stop();
                executionTime = stopWatch.getTotalTimeMillis();
            }
            // 在LogRecordContext中写入执行后信息
            LogRecordContext.putVariable(LogRecordContext.CONTEXT_KEY_NAME_ERROR_MSG, throwable.getMessage());
            for (OperationLog annotation : annotations) {
                if (!annotation.executeBeforeFunc()) {
                    logDtoMap.put(annotation, resolveExpress(annotation, pjp));
                }
            }
            // 写入异常执行后日志
            logDTOList = new ArrayList<>(logDtoMap.values());
            logDTOList.forEach(logDTO -> {                                      //  此处的是否有问题??
                logDTO.setSuccess(false);
                logDTO.setException(throwable.getMessage());
            });
        } catch (Throwable throwableAfterFuncFailure) {
            log.error("OperationLogAspect doAround after function failure, error:", throwableAfterFuncFailure);
        }
        // 抛出原方法异常
        throw throwable;
    } finally {
qqxx6661 commented 1 year ago

具体说说?没看出来。

fish-liu commented 1 year ago

@Data public class LogDTO {

private boolean success;

private String exception;

}

public class Test001 {

public static void main(String[] args) {

    List<LogDTO> logDTOList = new ArrayList<>(3);
    System.out.println("------000-------" + logDTOList.size());
    logDTOList.forEach(logDTO -> {                                      //  此处的是否有问题??
        logDTO.setSuccess(false);
        logDTO.setException("throwable.getMessage()");
        System.out.println("-------------");
    });
    System.out.println("------1111-------" + logDTOList.size());
    for(LogDTO logDTO : logDTOList){
        System.out.println("-------------"+logDTO.getException());
    }
}

}

我的运行结果: ------000-------0 ------1111-------0

Process finished with exit code 0

说明 logDTOList.forEach() 根本不会执行 是不是可以说finally 里面的 logDTOList.forEach() 也不会执行,也就是说原方法异常时,不会保存任何操作记录

qqxx6661 commented 1 year ago

你注解@OperationLog一行具体是怎么写的?

我看你上方的代码, new ArrayList<>(3); 然后也没塞值给数组,前后都是0没问题吧。

fish-liu commented 1 year ago

这个跟@OperationLog 注解没关系吧,

AOP中,原方法异常,进到catch模块,

// 写入异常执行后日志 logDTOList = new ArrayList<>(logDtoMap.values()); logDTOList.forEach(logDTO -> {
logDTO.setSuccess(false); logDTO.setException(throwable.getMessage()); });

这段代码跟我写的demo 功能一样吧,没有往logDTOList里塞任何数据,就forEach了

最后在执行finally 模块时,不启用线程,会执行 logDTOList.forEach(createLogFunction); 也就等于啥都没执行呗

所以原方法异常时,是不会记录失败日志的对吧

qqxx6661 commented 1 year ago

image

看了下,我是用的java.util.ArrayList#ArrayList(java.util.Collection<? extends E>)构造方法,所以是塞了Map的value数组构造进去的。 你可以用这个单测case试下cn.monitor4all.logRecord.test.OperationLogNormalTest#testMethodThrowException

fish-liu commented 1 year ago

第一眼 看成是 logDTOList = new ArrayList<>(logDtoMap.size()); 了,后面再看这段代码,惯性一直以为是logDtoMap.size() 哈哈哈😆