SoFunction
Updated on 2025-03-08

Three ways to call SpringBoot statistics interface time-consuming

introduction

In actual development, understanding the response time of the interface in the project is essential. The SpringBoot project supports more than one function. Next, we use AOP, ApplicationListener, and Tomcat to implement three different monitoring interface response times.

AOP

First, we create a class in the project, for example, WebLogAspect, and then add @Aspect and @Component annotations to the class, declaring that it is a bean and a section:

import ;  
import ;  
import .*;  
import org.;  
import org.;  
import ;  
import ;  
import ;  
  
import ;  
import ;  
  
@Aspect  
@Component  
public class WebLogAspect {  
  
    private static final Logger logger = ();  
  
    // Define an entry point to intercept all methods with @RequestMapping annotation    @Pointcut("@annotation()")  
    public void webLog() {}  
  
    // Pre-notification, record request information before method execution    @Before("webLog()")  
    public void doBefore(JoinPoint joinPoint) {  
        ServletRequestAttributes attributes = (ServletRequestAttributes) ();  
        HttpServletRequest request = ();  
  
        // Record request information        ("Request to start:URL={}, IP={}, method={}", (), (), ());  
    }  
  
    // Surround notifications and record the execution time of the method    @Around("webLog()")  
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {  
        long startTime = ();  
  
        Object result = (); // Continue to execute the intercepted method  
        long endTime = ();  
        long executeTime = endTime - startTime;  
  
        // Record execution time        ("Request ends:time consuming={}ms", executeTime);  
  
        return result;  
    }  
  
    // Exception notification, record exception information when the method throws an exception    @AfterThrowing(pointcut = "webLog()", throwing = "ex")  
    public void doAfterThrowing(JoinPoint joinPoint, Exception ex) {  
        ServletRequestAttributes attributes = (ServletRequestAttributes) ();  
        HttpServletRequest request = ();  
  
        // Record exception information        ("Request exception:URL={}, abnormal={}", (), ());  
    }  
  
    // Post-protected notification (return notification), record information after the method returns normally    @AfterReturning(returning = "retVal", pointcut = "webLog()")  
    public void doAfterReturning(JoinPoint joinPoint, Object retVal) {  
        // You can record the return value here, but we usually don't record it because it may contain sensitive information        // ("Request returns: return value = {}", retVal);    }  
}

2024-06-19 17:49:37.373 [TID: N/A] WARN  [] Request start: URL=http://localhost:18080/springboot/test1, IP=0:0:0:0:0:0:0:0:0:1, Method=POST
2024-06-19 17:49:37.386 [TID: N/A] WARN  [] Request end: Time taken = 13ms
2024-06-19 17:49:37.501 [TID: N/A] WARN  [] Request start: URL=http://localhost:18080/springboot/test2, IP=0:0:0:0:0:0:0:0:0:0:1, Method=POST
2024-06-19 17:49:37.516 [TID: N/A] WARN  [] Request end: Time taken = 15ms
2024-06-19 17:49:37.905 [TID: N/A] WARN  [] Request start: URL=http://localhost:18080/springboot/test3, IP=0:0:0:0:0:0:0:0:0:0:1, Method=POST
2024-06-19 17:49:37.913 [TID: N/A] WARN  [] Request end: Time taken = 8ms

advantage:

  • Globality: The execution time of the interface in the global scope can be recorded without modifying the business code.
  • Flexibility: You can flexibly define which interfaces need to record execution time as needed.
  • Accuracy: You can accurately record the time from the start of the method to the end.

shortcoming:

  • Configuration Complexity: AOP configuration can be relatively complex, especially for beginners.
  • Performance overhead: Although performance overhead is usually small, it still needs to be considered in high concurrency scenarios and it will block the main thread.

**Common use: **In the Spring framework, AOP is a powerful tool for achieving cross-cutting concerns such as logging, transaction management, etc. Therefore, using AOP to record the execution time of the interface is a very common and recommended practice.

ApplicationListener

First, we create a class in the project, for example, called TakeTimeCountListener, and then implement the ApplicationListener interface:

import org.;
import org.;
import ;
import ;
import ;

@Component
public class TakeTimeCountListener implements ApplicationListener<ServletRequestHandledEvent> {

    public final Logger logger = (());
    
    @Override
    public void onApplicationEvent(ServletRequestHandledEvent event) {
        Throwable failureCause = () ;
        if (failureCause != null) {
            ("Cause of error: {}", ());
        }
        // For example, I only record logs with interface response time greater than 1 second        if (() > 1000) {
                ("Request a client address:{}, askURL: {}, askMethod: {}, ask耗时:{} ms",
                (),
                (),
                (),
                ());
        }

    }
}

2024-06-19 17:14:59.620 [TID: N/A] WARN  [] Request client address: 0:0:0:0:0:0:0:0:0:1, Request URL: /springboot/test1, Request Method: GET, Request time: 51 ms
2024-06-19 17:14:59.716 [TID: N/A] WARN  [] Request client address: 0:0:0:0:0:0:0:0:0:1, Request URL: /springboot/test2, Request Method: GET, Request time: 136 ms
2024-06-19 17:14:59.787 [TID: N/A] WARN  [] Request client address: 0:0:0:0:0:0:0:0:0:1, Request URL: /springboot/test3, Request Method: POST, Request time: 255 ms
2024-06-19 17:14:59.859 [TID: N/A] WARN  [] Request client address: 0:0:0:0:0:0:0:0:0:1, Request URL: /springboot/test4, Request Method: POST, Request time: 167 ms

advantage:

  • Integration: Tightly integrated with Spring MVC framework, no additional configuration required.
  • Performance: Changing the method will not block the main thread, which means that the controller has returned normally when processing the method. It can be verified by breakpoint debugging in the method.
  • Simple and easy to use: just implement the ApplicationListener interface and listen to the ServletRequestHandledEvent event.

shortcoming:

  • Scope of application: It is mainly applicable to web requests under the Spring MVC framework, and may not be applicable to non-Web interfaces (such as RESTful APIs).
  • Accuracy: Only the processing time of the entire request can be recorded, and the specific method execution time cannot be accurate.

**Common use:**In Spring MVC applications, using ApplicationListener to record request processing time is a common practice, but is usually used for monitoring and performance analysis rather than precisely recording interface execution time.

Tomcat

The implementation of Tomcat is very simple. You only need to enable the access log that it supports. In SpringBoot, we can add the following configuration to the properties or yaml file:

# Enable Tomcat access log=true  
# Enable buffer mode, the log will be written to the buffer first, and then flushed to disk regularly=true  
# Specify the log storage directory, which is the logs folder relative to the project root directory=logs 
# Define the date format of the log file name-date-format=.yyyy-MM-dd 
# Define the format of logging# The meaning of each field:# %{X-Forwarded-For}i: X-Forwarded-For in the request header, usually used to record the client's real IP# %p: Local port# %l: Remote user, usually '-'# %r: The first line of the request (for example: GET/HTTP/1.1)# %t: Request time (format is determined by the log processor)# Note: There is a duplicate %r here, which may be an error, usually the second %r does not need it# %s: HTTP status code# %b: Number of response bytes, excluding HTTP headers, if 0, no output is# %T: Request processing time (in seconds)=%{X-Forwarded-For}i %p %l %r %t %r %s %b %T
# Log file name prefix=localhost_access_log
# Log file name suffix=.log
server:  
  tomcat:  
    accesslog:  
      enabled: true  # Enable Tomcat access log      buffered: true  # Enable buffer mode, the log will be written to the buffer first, and then flushed to disk regularly      directory: logs  # Specify the log storage directory, which is the logs folder relative to the project root directory      file-date-format: ".yyyy-MM-dd"   # Define the date format of the log file name      pattern: "%{X-Forwarded-For}i %p %l %r %t %s %b %T"  # Define the format of logging      prefix: localhost_access_log   # Log file name prefix      suffix: .log # Log file name suffix

- 8080 - - [19/Jun/2024:00:00:09 +0800] GET /springboot/test1 HTTP/1.1 200 92 0.247 Ignored_Trace
- 8080 - - [19/Jun/2024:00:00:09 +0800] GET /springboot/test2 HTTP/1.1 200 92 0.247 Ignored_Trace
- 8080 - - [19/Jun/2024:09:49:55 +0800] POST /springboot/test3 HTTP/1.1 200 291556 0.314 Ignored_Trace

advantage:

  • Integration: Tomcat built-in features, no additional code or configuration required.
  • Comprehensive: Record all request and response information processed through Tomcat.

shortcoming:

  • Performance: Access logs may have some impact on Tomcat performance.
  • Accuracy: Only the processing time of the entire request can be recorded, and the specific method execution time cannot be accurate.
  • Configuration Complexity: For complex log formats or requirements, it may be necessary to modify the configuration file of Tomcat.

**Common usage: **Tomcat's access log is usually used to monitor the access status of the web server, such as IP address, request path, HTTP status code, etc. While it can record request processing time, it is not usually used for precise performance analysis or interface execution time recording.

The above is the detailed content of the three methods of calling SpringBoot statistical interfaces. For more information about SpringBoot statistical interfaces, please pay attention to my other related articles!