如何记录Spring Boot中Rest Web服务所用的时间?

我正在使用Spring Boot编写Web Rest Web服务。

我想记录我的webservice处理请求所花费的时间。 另外我想记录调用的头文件,方法和URI。

几个月前我在我的jersey网络服务中使用ContainerRequestFilter and ContainerResponseFilter filter() method.做了类似的工作ContainerRequestFilter and ContainerResponseFilter filter() method.

另外,AOP更好还是过滤?

你试过像这样的基本filter吗?

 import java.io.IOException; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; @Component @WebFilter("/*") public class StatsFilter implements Filter { private static final Logger LOGGER = LoggerFactory.getLogger(StatsFilter.class); @Override public void init(FilterConfig filterConfig) throws ServletException { // empty } @Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { long time = System.currentTimeMillis(); try { chain.doFilter(req, resp); } finally { time = System.currentTimeMillis() - time; LOGGER.trace("{}: {} ms ", ((HttpServletRequest) req).getRequestURI(), time); } } @Override public void destroy() { // empty } } 

Spring boot:日志拦截器

  public class ApiLogger extends HandlerInterceptorAdapter { private static final Logger logger = LoggerFactory .getLogger(ApiLogger.class); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String requestId = UUID.randomUUID().toString(); log(request,response, requestId); long startTime = System.currentTimeMillis(); request.setAttribute("startTime", startTime); request.setAttribute("requestId", requestId); return true; } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { super.afterCompletion(request, response, handler, ex); long startTime = (Long)request.getAttribute("startTime"); long endTime = System.currentTimeMillis(); long executeTime = endTime - startTime; logger.info("requestId {}, Handle :{} , request take time: {}",request.getAttribute("requestId"), handler, executeTime); } private void log(HttpServletRequest request, HttpServletResponse response, String requestId) { logger.info("requestId {}, host {} HttpMethod: {}, URI : {}",requestId, request.getHeader("host"), request.getMethod(), request.getRequestURI() ); } } 

注册拦截器:

 @Configuration @EnableWebMvc public class AppConfig extends WebMvcConfigurerAdapter { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new ApiLogger()).addPathPatterns("/api/v1/*"); } } 

David的回答是正确的 – filter是在Spring Boot中实现此类function的好方法。

Spring Boot有一个内置端点 ,它返回有关最近100个请求的信息,如下所示:

 [{ "timestamp": 1394343677415, "info": { "method": "GET", "path": "/trace", "headers": { "request": { "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Connection": "keep-alive", "Accept-Encoding": "gzip, deflate", "User-Agent": "Mozilla/5.0 Gecko/Firefox", "Accept-Language": "en-US,en;q=0.5", "Cookie": "_ga=GA1.1.827067509.1390890128; ..." "Authorization": "Basic ...", "Host": "localhost:8080" }, "response": { "Strict-Transport-Security": "max-age=31536000 ; includeSubDomains", "X-Application-Context": "application:8080", "Content-Type": "application/json;charset=UTF-8", "status": "200" } } } },{ "timestamp": 1394343684465, ... }] 

如果您的应用程序正在调用其他服务或查询数据库,请考虑使用Sniffy进行性能分析 – 它不仅会向您显示在服务器上花费的时间,还会向您显示调用下游系统所花费的时间。 在这里查看现场演示(检查顶部底角的黑色小部件)。

免责声明 :我是Sniffy的作者

Sniffy演示截图

如果您的控制器是Async,请使用Aspect获取正确且完整的执行时间。

 import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import java.util.Arrays; import java.util.UUID; @Aspect @Component public class LoggingAspect { static Logger log = LoggerFactory.getLogger(LoggingAspect.class); @Around("execution(* com.aakchoo.api.controller..*(..))") public Object profileExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { long start = System.currentTimeMillis(); String className = joinPoint.getSignature().getDeclaringTypeName(); String methodName = joinPoint.getSignature().getName(); String apiName = className + "."+ methodName; HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); String requestId = UUID.randomUUID().toString(); log.info("----->>>>>\nREQUESTED_ID: {}\nHOST: {} HttpMethod: {}\nURI: {}\nAPI: {}\nArguments: {}\n", requestId, request.getHeader("host"), request.getMethod(), request.getRequestURI(), apiName, Arrays.toString(joinPoint.getArgs())); Object result = joinPoint.proceed(); long elapsedTime = System.currentTimeMillis() - start; log.info("<<<<<-----\nExecution Time: {} ms [REQUESTED_ID: {}] [API: {}]", elapsedTime,requestId,apiName); return result; } } 

将@EnableAspectJAutoProxy添加到Applciation类

 @EnableAsync @SpringBootApplication @EnableAspectJAutoProxy public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } 

而你的build.gradle将需要以下内容

 compile 'org.aspectj:aspectjweaver:1.8.10' compile 'org.springframework.boot:spring-boot-starter-aop' 

也许你可以使用log4j并将日志配置为DEBUG