当前位置: 首页 > 知识库问答 >
问题:

用Spring WebFlux在reactive应用程序中记录aop进行重复查询

百里默
2023-03-14
@Override
public Mono<UserDTO> findById(Long id) {
    
    return Mono.defer(() -> Mono.just(userRepository.findById(id))).flatMap(optional -> {
        if (optional.isPresent()) {
            return Mono.just(convertToDto(optional.get()));
        }
        
        return Mono.empty();
    }).subscribeOn(Schedulers.boundedElastic());
}
@Around("within(@org.springframework.stereotype.Controller *) || within(@org.springframework.stereotype.Service *) || execution(public !void org.springframework.data.repository.Repository+.*(..))")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
    if (LOGGER.isDebugEnabled()) {
        LOGGER.debug("Enter: {}.{}() with argument[s] = {}", joinPoint.getSignature().getDeclaringTypeName(),
                joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
    }
    try {
        Object result = joinPoint.proceed();
        
        LOGGER.debug("Exit: {}.{}() with result = {}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint
                .getSignature().getName(), result);
                
        return result;
    } catch (IllegalArgumentException e) {
        LOGGER.error("Illegal argument: {} in {}.{}()", Arrays.toString(joinPoint.getArgs()), joinPoint.getSignature()
                .getDeclaringTypeName(),
                joinPoint.getSignature().getName(), e);
        throw e;
    }
}
2020-11-14 22:35:25.394 DEBUG 31132 --- [ctor-http-nio-3] *.webflux.api.app.aop.LoggingAspect  : Exit: com.*.springboot.webflux.api.app.services.UserServiceImpl.findById() with result = MonoSubscribeOn
2020-11-14 22:35:25.396 DEBUG 31132 --- [ctor-http-nio-3] *.webflux.api.app.aop.LoggingAspect  : Exit: com.*.springboot.webflux.api.app.web.controllers.UserController.get() with result = MonoDefaultIfEmpty
2020-11-14 22:35:25.399 DEBUG 31132 --- [oundedElastic-3] *.webflux.api.app.aop.LoggingAspect  : Enter: org.springframework.data.repository.CrudRepository.findById() with argument[s] = [1]
Hibernate: 
    select
        user0_.id as id1_0_0_,
        user0_.birthdate as birthdat2_0_0_,
        user0_.email as email3_0_0_,
        user0_.name as name4_0_0_,
        user0_.surname as surname5_0_0_ 
    from
        users user0_ 
    where
        user0_.id=?
2020-11-14 22:35:25.417 DEBUG 31132 --- [oundedElastic-3] *.webflux.api.app.aop.LoggingAspect  : Exit: org.springframework.data.repository.CrudRepository.findById() with result = Optional[User(id=1, name=John, surname=Doe, email=john@mail.com, birthdate=2020-11-14 22:35:17.221)]
@Around("within(@org.springframework.stereotype.Controller *) || within(@org.springframework.stereotype.Service *) || execution(public !void org.springframework.data.repository.Repository+.*(..))")    
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
    if (LOGGER.isDebugEnabled()) {
        LOGGER.debug("Enter: {}.{}() with argument[s] = {}", joinPoint.getSignature().getDeclaringTypeName(),
                joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
    }
    try {
        Object result = joinPoint.proceed();
        
        if (LOGGER.isDebugEnabled()) {
            if (result instanceof Mono) {
                ((Mono<Object>)result).subscribe(monoResult -> {
                    LOGGER.debug("Exit Mono: {}.{}() with result = {}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint
                            .getSignature().getName(), monoResult);
                });

            } else {
                LOGGER.debug("Exit: {}.{}() with result = {}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint
                        .getSignature().getName(), result);
            }
        }
        return result;
    } catch (IllegalArgumentException e) {
        LOGGER.error("Illegal argument: {} in {}.{}()", Arrays.toString(joinPoint.getArgs()), joinPoint.getSignature()
                .getDeclaringTypeName(),
                joinPoint.getSignature().getName(), e);
        throw e;
    }
}

Log result:
2020-11-14 22:38:16.693 DEBUG 21424 --- [oundedElastic-1] *.webflux.api.app.aop.LoggingAspect  : Enter: org.springframework.data.repository.CrudRepository.findById() with argument[s] = [1]
2020-11-14 22:38:16.694 DEBUG 21424 --- [oundedElastic-4] *.webflux.api.app.aop.LoggingAspect  : Enter: org.springframework.data.repository.CrudRepository.findById() with argument[s] = [1]
2020-11-14 22:38:16.699 DEBUG 21424 --- [oundedElastic-8] *.webflux.api.app.aop.LoggingAspect  : Enter: org.springframework.data.repository.CrudRepository.findById() with argument[s] = [1]
Hibernate: 
    select
        user0_.id as id1_0_0_,
        user0_.birthdate as birthdat2_0_0_,
        user0_.email as email3_0_0_,
        user0_.name as name4_0_0_,
        user0_.surname as surname5_0_0_ 
    from
        users user0_ 
    where
        user0_.id=?
Hibernate: 
    select
        user0_.id as id1_0_0_,
        user0_.birthdate as birthdat2_0_0_,
        user0_.email as email3_0_0_,
        user0_.name as name4_0_0_,
        user0_.surname as surname5_0_0_ 
    from
        users user0_ 
    where
        user0_.id=?
Hibernate: 
    select
        user0_.id as id1_0_0_,
        user0_.birthdate as birthdat2_0_0_,
        user0_.email as email3_0_0_,
        user0_.name as name4_0_0_,
        user0_.surname as surname5_0_0_ 
    from
        users user0_ 
    where
        user0_.id=?
2020-11-14 22:38:16.713 DEBUG 21424 --- [oundedElastic-8] *.webflux.api.app.aop.LoggingAspect  : Exit: org.springframework.data.repository.CrudRepository.findById() with result = Optional[User(id=1, name=John, surname=Doe, email=john@mail.com, birthdate=2020-11-14 22:37:20.379)]
2020-11-14 22:38:16.713 DEBUG 21424 --- [oundedElastic-4] *.webflux.api.app.aop.LoggingAspect  : Exit: org.springframework.data.repository.CrudRepository.findById() with result = Optional[User(id=1, name=John, surname=Doe, email=john@mail.com, birthdate=2020-11-14 22:37:20.379)]
2020-11-14 22:38:16.713 DEBUG 21424 --- [oundedElastic-1] *.webflux.api.app.aop.LoggingAspect  : Exit: org.springframework.data.repository.CrudRepository.findById() with result = Optional[User(id=1, name=John, surname=Doe, email=john@mail.com, birthdate=2020-11-14 22:37:20.379)]
2020-11-14 22:38:16.713 DEBUG 21424 --- [oundedElastic-1] *.webflux.api.app.aop.LoggingAspect  : Exit Mono: com.*.springboot.webflux.api.app.services.UserServiceImpl.findById() with result = UserDTO(id=1, name=John, surname=Doe, email=john@mail.com, birthdate=2020-11-14 22:37:20.379)
2020-11-14 22:38:16.714 DEBUG 21424 --- [oundedElastic-4] *.webflux.api.app.aop.LoggingAspect  : Exit Mono: com.*.springboot.webflux.api.app.web.controllers.UserController.get() with result = <200 OK OK,UserDTO(id=1, name=John, surname=Doe, email=john@mail.com, birthdate=2020-11-14 22:37:20.379),[Content-Type:"application/json"]>

还有其他方法可以恢复流量的值吗?我不能用mono.bock因为它锁线程。

共有1个答案

卞琨
2023-03-14

我的最终解决方案:

当结果是每个元素打印日志行时,我添加了一个uuid,以便能够识别每个请求的跟踪。代码:

public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {

    String uuid = UUID.randomUUID().toString();
    
    try {
        
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug(LOG_ENTER_PATTERN, uuid, joinPoint.getSignature().getDeclaringTypeName(),
                    joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
        }
        
        Object result = joinPoint.proceed();

        if (LOGGER.isDebugEnabled()) {
            if (result instanceof Mono) {
                var monoResult = (Mono<?>) result;

                return monoResult.doOnSuccess(o -> {
                    var response = "";
                    if (Objects.nonNull(o)) {
                        response = o.toString();
                    }
                    LOGGER.debug(LOG_EXIT_PATTERN, uuid,
                            joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName(),
                            response);
                });
            }if (result instanceof Flux) {
                var fluxResult = (Flux<?>) result;
                return fluxResult.map(fluxItem -> {
                    LOGGER.debug(LOG_EXIT_PATTERN, uuid, joinPoint.getSignature().getDeclaringTypeName(),
                            joinPoint.getSignature().getName(), fluxItem);
                    return fluxItem;
                });
                
            } else {
                LOGGER.debug(LOG_EXIT_PATTERN, uuid, joinPoint.getSignature().getDeclaringTypeName(),
                        joinPoint.getSignature().getName(), result);
            }
        }
        return result;
    } catch (IllegalArgumentException e) {
        LOGGER.error(LOG_ERROR_ARROUND_PATTERN, uuid, Arrays.toString(joinPoint.getArgs()),
                joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName(), e);
        throw e;
    }
}

单声道日志:

2020-11-15 11:54:05.845 DEBUG 33264 --- [ctor-http-nio-3] *.webflux.api.app.aop.LoggingAspect  : Request uuid: ac0fbaec-59dc-429c-8a20-3053f7533fc9 -> Enter: com.*.springboot.webflux.api.app.web.controllers.UserController.get() with argument[s] = [1]
2020-11-15 11:54:05.845 DEBUG 33264 --- [ctor-http-nio-3] *.webflux.api.app.aop.LoggingAspect  : Request uuid: 38760d52-01e6-449e-b464-7ffe0f0b7e86 -> Enter: com.*.springboot.webflux.api.app.services.UserServiceImpl.findById() with argument[s] = [1]
2020-11-15 11:54:05.846  INFO 33264 --- [ctor-http-nio-3] *.w.api.app.aop.ProfilingAspect      : StopWatch 'Profiling': running time = 1122400 ns
---------------------------------------------
ns         %     Task name
---------------------------------------------
001122400  100 %  execution(UserServiceImpl.findById(..))

2020-11-15 11:54:05.849 DEBUG 33264 --- [oundedElastic-1] *.webflux.api.app.aop.LoggingAspect  : Request uuid: 3466a23a-5087-44ba-86bc-617b577643db -> Enter: org.springframework.data.repository.CrudRepository.findById() with argument[s] = [1]
Hibernate: 
    select
        user0_.id as id1_0_0_,
        user0_.birthdate as birthdat2_0_0_,
        user0_.email as email3_0_0_,
        user0_.name as name4_0_0_,
        user0_.surname as surname5_0_0_ 
    from
        users user0_ 
    where
        user0_.id=?
2020-11-15 11:54:05.860 DEBUG 33264 --- [oundedElastic-1] *.webflux.api.app.aop.LoggingAspect  : Request uuid: 3466a23a-5087-44ba-86bc-617b577643db -> Exit: org.springframework.data.repository.CrudRepository.findById() with result = Optional[User(id=1, name=John, surname=Doe, email=john@mail.com, birthdate=2011-12-18 13:17:17.0)]
2020-11-15 11:54:05.860 DEBUG 33264 --- [oundedElastic-1] *.webflux.api.app.aop.LoggingAspect  : Request uuid: 38760d52-01e6-449e-b464-7ffe0f0b7e86 -> Exit: com.*.springboot.webflux.api.app.services.UserServiceImpl.findById() with result = UserDTO(id=1, name=John, surname=Doe, email=john@mail.com, birthdate=2011-12-18 13:17:17.0)
2020-11-15 11:54:05.861 DEBUG 33264 --- [oundedElastic-1] *.webflux.api.app.aop.LoggingAspect  : Request uuid: ac0fbaec-59dc-429c-8a20-3053f7533fc9 -> Exit: com.*.springboot.webflux.api.app.web.controllers.UserController.get() with result = <200 OK OK,UserDTO(id=1, name=John, surname=Doe, email=john@mail.com, birthdate=2011-12-18 13:17:17.0),[Content-Type:"application/json"]>
2020-11-15 11:52:30.905 DEBUG 33264 --- [ctor-http-nio-3] *.webflux.api.app.aop.LoggingAspect  : Request uuid: 0d2e2c18-c9b3-491e-93e7-8fbbb5238224 -> Enter: com.*.springboot.webflux.api.app.web.controllers.UserController.findAll() with argument[s] = []
2020-11-15 11:52:30.914 DEBUG 33264 --- [ctor-http-nio-3] *.webflux.api.app.aop.LoggingAspect  : Request uuid: 46a86774-de89-438a-afae-776b02751701 -> Enter: com.*.springboot.webflux.api.app.services.UserServiceImpl.findAll() with argument[s] = []
2020-11-15 11:52:30.927  INFO 33264 --- [ctor-http-nio-3] *.w.api.app.aop.ProfilingAspect      : StopWatch 'Profiling': running time = 12118900 ns
---------------------------------------------
ns         %     Task name
---------------------------------------------
012118900  100 %  execution(UserServiceImpl.findAll())

2020-11-15 11:52:30.934 DEBUG 33264 --- [ctor-http-nio-3] *.webflux.api.app.aop.LoggingAspect  : Request uuid: 0d2e2c18-c9b3-491e-93e7-8fbbb5238224 -> Exit: com.*.springboot.webflux.api.app.web.controllers.UserController.findAll() with result = <200 OK OK,FluxMap,[Content-Type:"application/json"]>
2020-11-15 11:52:30.989 DEBUG 33264 --- [oundedElastic-1] *.webflux.api.app.aop.LoggingAspect  : Request uuid: d4240286-c0e4-4eae-94ad-496079e2d9a0 -> Enter: org.springframework.data.jpa.repository.JpaRepository.findAll() with argument[s] = []
Hibernate: 
    select
        user0_.id as id1_0_,
        user0_.birthdate as birthdat2_0_,
        user0_.email as email3_0_,
        user0_.name as name4_0_,
        user0_.surname as surname5_0_ 
    from
        users user0_
2020-11-15 11:52:31.144 DEBUG 33264 --- [oundedElastic-1] *.webflux.api.app.aop.LoggingAspect  : Request uuid: d4240286-c0e4-4eae-94ad-496079e2d9a0 -> Exit: org.springframework.data.jpa.repository.JpaRepository.findAll() with result = [User(id=1, name=John, surname=Doe, email=john@mail.com, birthdate=2011-12-18 13:17:17.0), User(id=2, name=Oscar, surname=Suarez, email=oscar@mail.com, birthdate=2011-12-18 13:17:17.0), User(id=3, name=Maria, surname=Salgado, email=salgado@mail.com, birthdate=2011-12-18 13:17:17.0), User(id=4, name=Manuel, surname=Lopez, email=manuel@mail.com, birthdate=2011-12-18 13:17:17.0)]
2020-11-15 11:52:31.174 DEBUG 33264 --- [oundedElastic-1] *.webflux.api.app.aop.LoggingAspect  : Request uuid: 46a86774-de89-438a-afae-776b02751701 -> Exit: com.*.springboot.webflux.api.app.services.UserServiceImpl.findAll() with result = UserDTO(id=1, name=John, surname=Doe, email=john@mail.com, birthdate=2011-12-18 13:17:17.0)
2020-11-15 11:52:31.174 DEBUG 33264 --- [oundedElastic-1] *.webflux.api.app.aop.LoggingAspect  : Request uuid: 46a86774-de89-438a-afae-776b02751701 -> Exit: com.*.springboot.webflux.api.app.services.UserServiceImpl.findAll() with result = UserDTO(id=2, name=Oscar, surname=Suarez, email=oscar@mail.com, birthdate=2011-12-18 13:17:17.0)
2020-11-15 11:52:31.174 DEBUG 33264 --- [oundedElastic-1] *.webflux.api.app.aop.LoggingAspect  : Request uuid: 46a86774-de89-438a-afae-776b02751701 -> Exit: com.*.springboot.webflux.api.app.services.UserServiceImpl.findAll() with result = UserDTO(id=3, name=Maria, surname=Salgado, email=salgado@mail.com, birthdate=2011-12-18 13:17:17.0)
2020-11-15 11:52:31.174 DEBUG 33264 --- [oundedElastic-1] *.webflux.api.app.aop.LoggingAspect  : Request uuid: 46a86774-de89-438a-afae-776b02751701 -> Exit: com.*.springboot.webflux.api.app.services.UserServiceImpl.findAll() with result = UserDTO(id=4, name=Manuel, surname=Lopez, email=manuel@mail.com, birthdate=2011-12-18 13:17:17.0)
 类似资料:
  • 上次我在考虑如何在我们的应用程序中正确使用记录器。例如,我有一个控制器,它返回一个用户流,但在日志中,我看到“Fetch users”日志是由另一个线程记录的,而不是处理管道上的线程,但这是一个好的方法吗? 在这种情况下,使用了两个线程,从我的角度来看,这不是一个好的选择,但我找不到在反应应用程序中使用记录器的好做法。我认为下面的方法更好,因为分配内存是来自处理线程,而不是来自spring web

  • 问题内容: 我需要与执行日志记录使用。 我在没有基本示例的情况下实现了日志记录? 也有小的样本在不使用日志的情况下使用(只是制作了)? 我不知道如何整合它? 问题答案: Spring使我们使用AOP变得非常容易。这是一个简单的日志记录示例: 然后只需配置你的applicationContext.xml(或等效文件): 你会在MyLogger类中注意到我@After在方法上方指定的内容。这被称为建议

  • 我们正在使用Spring引导将指标发送到应用程序洞察我们正在使用应用程序洞察日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志日志。 下面是我们在logj2-spring.xml中使用的附加程序 ** 我们在应用洞察搜索屏幕上看到日志,但是我有几个问题。 > 是否有一种方法可以

  • 问题内容: 我想将“跟踪”消息添加到我的所有公共方法中,如下所示: 现在,我想使用AOP(和字节码检测)将所有这些自动添加到我的方法中。我在想。是否有意义?您知道任何开放源代码吗? 问题答案: 我创建了一个简单的方面来捕获公共方法的执行。该AspectJ代码的核心是切入点定义: 在这里,我们将捕获任何包,任何类,具有任意数量的参数,具有任何返回类型的所有公共方法。 建议执行可以在下面的代码段中可视

  • 嗯,这个例子看起来很不完整,因为它从来没有提到关键字。通过查看源代码,我看到了一个示例(测试?)它在log4j.xml中使用了,但对如何使用或调试实际的记录器没有太多解释。 关于如何实际使用/实现ApplicationInsightsAppender for Log4J,有没有人有任何指示? 以下是github https://github.com/microsoft/applicationins