diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/MetricsFilter.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/MetricsFilter.java index c011237aeea..cfcd6fc1098 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/MetricsFilter.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/MetricsFilter.java @@ -109,6 +109,9 @@ final class MetricsFilter extends OncePerRequestFilter { } finally { if (!request.isAsyncStarted()) { + if (response.isCommitted()) { + status = getStatus(response); + } stopWatch.stop(); request.removeAttribute(ATTRIBUTE_STOP_WATCH); recordMetrics(request, path, status, stopWatch.getTotalTimeMillis()); diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/MetricFilterAutoConfigurationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/MetricFilterAutoConfigurationTests.java index 73f90a53326..62b3aa1bb7f 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/MetricFilterAutoConfigurationTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/MetricFilterAutoConfigurationTests.java @@ -365,6 +365,37 @@ public class MetricFilterAutoConfigurationTests { context.close(); } + @Test + public void whenExceptionIsThrownResponseStatusIsUsedWhenResponseHasBeenCommitted() + throws Exception { + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); + context.register(Config.class, MetricFilterAutoConfiguration.class); + context.refresh(); + Filter filter = context.getBean(Filter.class); + final MockHttpServletRequest request = new MockHttpServletRequest("GET", + "/test/path"); + final MockHttpServletResponse response = new MockHttpServletResponse(); + FilterChain chain = mock(FilterChain.class); + willAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + response.setStatus(200); + response.setCommitted(true); + throw new IOException(); + } + }).given(chain).doFilter(request, response); + try { + filter.doFilter(request, response, chain); + fail(); + } + catch (IOException ex) { + // Continue + } + verify(context.getBean(CounterService.class)) + .increment(eq("status.200.test.path")); + context.close(); + } + @Configuration public static class Config {