diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/reactive/server/MetricsWebFilter.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/reactive/server/MetricsWebFilter.java index 8250b09a07..799bf0103d 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/reactive/server/MetricsWebFilter.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/reactive/server/MetricsWebFilter.java @@ -62,8 +62,17 @@ public class MetricsWebFilter implements WebFilter { long start = System.nanoTime(); ServerHttpResponse response = exchange.getResponse(); return call.doOnSuccess((done) -> success(exchange, start)) - .doOnError((cause) -> response - .beforeCommit(() -> error(exchange, start, cause))); + .doOnError((cause) -> { + if (response.isCommitted()) { + error(exchange, start, cause); + } + else { + response.beforeCommit(() -> { + error(exchange, start, cause); + return Mono.empty(); + }); + } + }); } private void success(ServerWebExchange exchange, long start) { @@ -72,11 +81,10 @@ public class MetricsWebFilter implements WebFilter { TimeUnit.NANOSECONDS); } - private Mono error(ServerWebExchange exchange, long start, Throwable cause) { + private void error(ServerWebExchange exchange, long start, Throwable cause) { Iterable tags = this.tagsProvider.httpRequestTags(exchange, cause); this.registry.timer(this.metricName, tags).record(System.nanoTime() - start, TimeUnit.NANOSECONDS); - return Mono.empty(); } } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/reactive/server/MetricsWebFilterTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/reactive/server/MetricsWebFilterTests.java index 82cf4e6afd..97540d8e7b 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/reactive/server/MetricsWebFilterTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/reactive/server/MetricsWebFilterTests.java @@ -74,6 +74,22 @@ public class MetricsWebFilterTests { assertMetricsContainsTag("status", "500"); } + @Test + public void filterAddsTagsToRegistryForExceptionsAndCommittedResponse() { + MockServerWebExchange exchange = createExchange("/projects/spring-boot", + "/projects/{project}"); + this.webFilter.filter(exchange, + serverWebExchange -> { + exchange.getResponse().setStatusCodeValue(500); + return exchange.getResponse().setComplete() + .then(Mono.error(new IllegalStateException("test error"))); + }) + .onErrorResume(t -> Mono.empty()) + .block(); + assertMetricsContainsTag("uri", "/projects/{project}"); + assertMetricsContainsTag("status", "500"); + } + private MockServerWebExchange createExchange(String path, String pathPattern) { PathPatternParser parser = new PathPatternParser(); MockServerWebExchange exchange = MockServerWebExchange