From a6ccdbe19fb27cef6fd08490959849c6fd0bcb53 Mon Sep 17 00:00:00 2001 From: Johnny Lim Date: Fri, 22 Feb 2019 10:09:39 +0900 Subject: [PATCH 1/3] Handle missing exceptions in WebMvcMetricsFilter Prior to this commit, exceptions nested in `NestedServletExceptions` would not be recorded by the `WebMvcMetricsFilter`. This commit ensures that exceptions happening downstream (e.g. happening while writing the response body itself) are properly recorded. See https://github.com/micrometer-metrics/micrometer/issues/1190 See gh-16014 --- .../boot/actuate/metrics/web/servlet/WebMvcMetricsFilter.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/servlet/WebMvcMetricsFilter.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/servlet/WebMvcMetricsFilter.java index b99125c0ae..3f51d8c177 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/servlet/WebMvcMetricsFilter.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/servlet/WebMvcMetricsFilter.java @@ -130,6 +130,10 @@ public class WebMvcMetricsFilter extends OncePerRequestFilter { record(timingContext, response, request, ex.getCause()); throw ex; } + catch (ServletException | IOException | RuntimeException ex) { + record(timingContext, response, request, ex); + throw ex; + } } private TimingContext startAndAttachTimingContext(HttpServletRequest request) { From 61380415781bd2341c78017464823eaefc9d9dfc Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Wed, 13 Mar 2019 11:02:27 +0100 Subject: [PATCH 2/3] Polish Fixes gh-16014 --- .../web/servlet/WebMvcMetricsFilterTests.java | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/servlet/WebMvcMetricsFilterTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/servlet/WebMvcMetricsFilterTests.java index 7b53c25569..5a084f8cdb 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/servlet/WebMvcMetricsFilterTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/servlet/WebMvcMetricsFilterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2018 the original author or authors. + * Copyright 2012-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -76,6 +76,7 @@ import org.springframework.web.context.WebApplicationContext; import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter; import org.springframework.web.util.NestedServletException; import static org.assertj.core.api.Assertions.assertThat; @@ -188,6 +189,16 @@ public class WebMvcMetricsFilterTests { .tags("exception", "RuntimeException").timer().count()).isEqualTo(1L); } + @Test + public void streamingError() throws Exception { + MvcResult result = this.mvc.perform(get("/api/c1/streamingError")) + .andExpect(request().asyncStarted()).andReturn(); + assertThatCode( + () -> this.mvc.perform(asyncDispatch(result)).andExpect(status().isOk())); + assertThat(this.registry.get("http.server.requests") + .tags("exception", "IOException").timer().count()).isEqualTo(1L); + } + @Test public void anonymousError() { try { @@ -451,6 +462,14 @@ public class WebMvcMetricsFilterTests { throw new RuntimeException("Boom on " + id + "!"); } + @GetMapping("/streamingError") + public ResponseBodyEmitter streamingError() { + ResponseBodyEmitter emitter = new ResponseBodyEmitter(); + emitter.completeWithError( + new IOException("error while writing to the response")); + return emitter; + } + @Timed @GetMapping("/regex/{id:\\.[a-z]+}") public String successfulRegex(@PathVariable String id) { From 8866a25ef79eda30c56c2844152f49cfc476c2d1 Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Wed, 13 Mar 2019 11:55:53 +0100 Subject: [PATCH 3/3] Polish Undertow tests --- .../undertow/UndertowServletWebServerFactoryTests.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/UndertowServletWebServerFactoryTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/UndertowServletWebServerFactoryTests.java index 028b6c82b7..45f92cdd6c 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/UndertowServletWebServerFactoryTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/UndertowServletWebServerFactoryTests.java @@ -30,7 +30,6 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import javax.net.ssl.SSLException; -import javax.net.ssl.SSLHandshakeException; import io.undertow.Undertow.Builder; import io.undertow.servlet.api.DeploymentInfo; @@ -209,8 +208,8 @@ public class UndertowServletWebServerFactoryTests @Test public void sslRestrictedProtocolsEmptyCipherFailure() throws Exception { - this.thrown.expect(anyOf(instanceOf(SSLHandshakeException.class), - instanceOf(SocketException.class))); + this.thrown.expect( + anyOf(instanceOf(SSLException.class), instanceOf(SocketException.class))); testRestrictedSSLProtocolsAndCipherSuites(new String[] { "TLSv1.2" }, new String[] { "TLS_EMPTY_RENEGOTIATION_INFO_SCSV" }); }