es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo medir el tiempo de una solicitud en Spring Boot, incluyendo el estado 404?

Me gustaría medir el tiempo de procesamiento para cada solicitud HTTP en una aplicación Spring Boot (como access.log).

Por ejemplo, podría implementar GenericFilterBean:

doFilter(ServletRequest request, ServletResponse response, FilterChain chain){
  long start = now();
  try {
    chain.doFilter(request, response);
  } finally {
    long stop = now();
    print(stop - start);
  }
}

Si implemento @RestControllerAdvice para manejar cada excepción, entonces medir el tiempo en doFilter funcionará lo suficientemente bien (sé que podría haber problemas con excepciones del filtro).

Pero hay un problema con las solicitudes 404, porque la solicitud no toca ningún @RestController y no llega a @RestControllerAdvice.
La solicitud pasará por GenericFilterBean y luego Tomcat enviará la solicitud a ErrorController con estado 404.

Para mí, la solicitud se completa cuando ErrorController se completa.
Pero no sé cómo rastrear la solicitud desde el punto de entrada hasta el punto de salida cuando la solicitud se envía como error.

Tags:  

Answer

  1. Avatar for davy.ai

    Para medir el tiempo de procesamiento para cada solicitud HTTP en una aplicación Spring Boot, incluyendo las solicitudes que resulten en un estado 404, puedes implementar una combinación de un Filter, un Interceptor y un ErrorController.

    Primero, crea un Filter que registre el tiempo de inicio de cada solicitud. Dentro del método doFilter, guarda el tiempo de inicio en los atributos de la solicitud:

    @Component
    public class TimingFilter implements Filter {
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            long startTime = System.currentTimeMillis();
            request.setAttribute("startTime", startTime);
            chain.doFilter(request, response);
        }
    }
    

    A continuación, crea un Interceptor que registre el tiempo de finalización de cada solicitud. Dentro del método postHandle, obtén el tiempo de inicio de los atributos de la solicitud, calcula el tiempo transcurrido y registra esta información:

    @Component
    public class TimingInterceptor implements HandlerInterceptor {
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            long startTime = (Long) request.getAttribute("startTime");
            long endTime = System.currentTimeMillis();
            long elapsed = endTime - startTime;
            String requestUri = request.getRequestURI();
            if (StringUtils.isNotEmpty(request.getQueryString())) {
                requestUri += "?" + request.getQueryString();
            }
            log.info(requestUri + " tardó " + elapsed + " ms");
        }
    }
    

    Finalmente, crea un ErrorController que registre el tiempo de procesamiento para las solicitudes que resulten en un estado 404. Utiliza el mismo enfoque que en el Interceptor, pero obtén el tiempo de inicio del objeto HttpServletRequest:

    @Controller
    public class TimingErrorController implements ErrorController {
        @Override
        public String getErrorPath() {
            return "/error";
        }
    
        @RequestMapping("/error")
        public String handleNotFound(HttpServletRequest request, HttpServletResponse response) {
            long startTime = (Long) request.getAttribute("startTime");
            long endTime = System.currentTimeMillis();
            long elapsed = endTime - startTime;
            log.info(request.getMethod() + " " + request.getRequestURI() + " devolvió un estado 404 en " + elapsed + " ms");
            return "error";
        }
    }
    

    Con estos componentes en su lugar, puedes medir el tiempo de procesamiento para cada solicitud HTTP, incluyendo las solicitudes que resulten en un estado 404. Ten en cuenta que este enfoque asume que el ErrorController es el destino final para todas las solicitudes, lo cual puede no ser el caso si tienes filtros o interceptores de servlet adicionales.

Comments are closed.