简体   繁体   English

Spring AOP/AspectJ 记录方法的执行时间,但如何将 arguments 传递给它? (春季启动 API)

[英]Spring AOP/AspectJ logging the execution time of a method but how to pass arguments to it? (Spring boot API)

I am using Spring AOP/AspectJ in my Spring Boot API to make an annotation in Java like @TrackExecutionTime , that I can slap on any method and it logs the total time it took the method to run. I am using Spring AOP/AspectJ in my Spring Boot API to make an annotation in Java like @TrackExecutionTime , that I can slap on any method and it logs the total time it took the method to run. This is working currently in my Spring boot up.这目前在我的 Spring 启动中有效。 My issue is, my API is getting hit thousands of times a day, and I want log some other unique info with this execution time, so I can track/trace each request through my logs.我的问题是,我的 API 每天被点击数千次,我想用这个执行时间记录一些其他独特的信息,所以我可以通过我的日志跟踪/跟踪每个请求。 Some of the data that I can use is sent with the POST request body from the JSON, but I can't see how to pass these arguments into the definition of this annotation - can anyone help?我可以使用的一些数据是与来自 JSON 的 POST 请求正文一起发送的,但我看不到如何将这些 arguments 传递到此注释的定义中 - 有人可以帮忙吗?

I want to pass some arguments (customer firstname, lastname, etc..) from this Customer object that is the requestBody the client will POST as JSON to my API to my annotation logger: I want to pass some arguments (customer firstname, lastname, etc..) from this Customer object that is the requestBody the client will POST as JSON to my API to my annotation logger:

@RestController
public class CustomersController implements CustomersApi {

    @Autowired
    private CustomerService customerService;

      return ResponseEntity.ok(offersService.fetchCustomer(Customer, clientId));
    }

I defined the concrete class and the interface for annotation like this.我定义了具体的 class 和这样的注释接口。 This is where I want to pass the Customer object so I can log the firstname or lastname:这是我要传递客户 object 的地方,以便我可以记录名字或姓氏:


@Aspect
@Component
@Slf4j
@ConditionalOnExpression("${aspect.enabled:true}")
public class ExecutionTimeAdvice {

    @Around("@annotation(com.mailshine.springboot.aop.aspectj.advise.TrackExecutionTime)")
    public Object executionTime(ProceedingJoinPoint point) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object object = point.proceed();
        long endtime = System.currentTimeMillis();

        log.info("Class Name: "+ point.getSignature().getDeclaringTypeName() +". Method Name: "+ point.getSignature().getName() + ". Time taken for Execution is : " + (endtime-startTime) +"ms");
        return object;
    }
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TrackExecutionTime {
}

You can try to add a String with the content that you want into the annotation:您可以尝试将带有所需内容的字符串添加到注释中:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TrackExecutionTime {
    String getContent() default "";
}

Using it on the method:在方法上使用它:

@TrackExecutionTime(getContent = "something")
private static void someMethod(...)

and then on the advice parse that content:然后根据建议解析该内容:

@Around("@annotation(myAnnotation)") 
public Object executionTime(ProceedingJoinPoint point, TrackExecutionTime myAnnotation)throws Throwable {
    ...
    String content = myAnnotation.getContent();
}

This is very easy to do;这很容易做到; I was a dum-dum when I originally posted this, but here's the answer for anyone looking to do the same:当我最初发布这个时,我是一个笨蛋,但对于任何想要做同样事情的人来说,这里都是答案:

When you create your interface that defines you annotation using Spring AOP/AspectJ, in your concrete class like I listed above, it has access to all the arguments passed to your method from the ProceedingJoinPoint object. When you create your interface that defines you annotation using Spring AOP/AspectJ, in your concrete class like I listed above, it has access to all the arguments passed to your method from the ProceedingJoinPoint object. So you can call getArgs() on this object to get all the arguments passed to the method in-question when its runs.因此,您可以在此 object 上调用getArgs() ,以在运行时将所有 arguments 传递给有问题的方法。 It will return an Object[] so you will just need to have some conditional checks to cast it down to the type of your choice and make sure its not empty, so you don't get any exceptions at runtime.它将返回一个 Object[],因此您只需要进行一些条件检查即可将其转换为您选择的类型并确保它不为空,因此您在运行时不会遇到任何异常。 This is helpful if clients are POSTing to your API and you want to track the execution time of methods, but maybe you have hundreds/thousands of requests and need to specifically trace down exactly which calls follow which paths and what may be slowing your API down... so posting additional data from the requestBody maybe helpful in your logs...如果客户端正在向您的 API 发布并且您想要跟踪方法的执行时间,这将很有帮助,但也许您有成百上千的请求并且需要专门追踪哪些调用遵循哪些路径以及可能会减慢 API 的原因...因此从 requestBody 发布其他数据可能对您的日志有帮助...

eg I'll pretend I am tracking some method, that takes in a "Student" data type, which holds a bunch of data on a student (name, dob, gpa, etc...).例如,我会假装我正在跟踪某种方法,该方法采用“学生”数据类型,其中包含学生的一堆数据(姓名、出生日期、gpa 等)。 This way, if I have different methods that query the Database with different SQL queries based on the requestBody the client POST to the API with, I can log this, to track down exactly which requests are slowing my API down and their flow within my codebase and which SQL queries they are calling.这样,如果我有不同的方法使用不同的 SQL 查询来查询数据库以及他们正在调用的 SQL 查询。 ie IE

@Aspect
@Component
@Slf4j
@ConditionalOnExpression("${aspect.enabled:true}")
public class ExecutionTimeAdvice {

    @Around("@annotation(com.mailshine.springboot.aop.aspectj.advise.TrackExecutionTime)")
    public Object executionTime(ProceedingJoinPoint point) throws Throwable {
        MyCustomStudentType student; // Class to hold Student data
        String studentName = "";
        Object[] argsArray = point.getArgs();
        
        if (argsArray.length > 0 && argsArray[0] instanceof MyCustomStudentType) {
             student = (MyCustomStudentType) argsArray[0];
             studentName = student.getName();
        }

        long startTime = System.currentTimeMillis();
        Object object = point.proceed();
        long endtime = System.currentTimeMillis();

        // add the student name to your logs or any info you want to add with your
        // execution time of your method, to make tracking your logs easier
        log.info("Class Name: "+ point.getSignature().getDeclaringTypeName() +". Method Name: "+ point.getSignature().getName() + ". Time taken for Execution is : " + (endtime-startTime) +"ms" + ", for student name: " + studentName);

        return object;
    }
}

for a method:对于一个方法:

public void someMethod(String input)  

you can write a pointcut expression like this:你可以这样写一个切入点表达式:

@Around("@annotation(com.mailshine.springboot.aop.aspectj.advise.TrackExecutionTime) && args(input)")
    public Object executionTime(ProceedingJoinPoint point, String input) throws Throwable {}

the input argument is now readily available to the executionTime method. input参数现在可用于executionTime方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM