Skip to content

Commit ebffe6e

Browse files
committed
Merge pull request #13817 from jkschneider:metrics-anon-exception
* pr/13817: Polish "Make sure exception tag values are not empty in web metrics" Make sure exception tag values are not empty in web metrics
2 parents 66156cc + 592754d commit ebffe6e

File tree

4 files changed

+48
-4
lines changed

4 files changed

+48
-4
lines changed

spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/reactive/server/WebFluxTags.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import io.micrometer.core.instrument.Tag;
2020

2121
import org.springframework.http.HttpStatus;
22+
import org.springframework.util.StringUtils;
2223
import org.springframework.web.reactive.HandlerMapping;
2324
import org.springframework.web.server.ServerWebExchange;
2425
import org.springframework.web.util.pattern.PathPattern;
@@ -109,7 +110,9 @@ public static Tag uri(ServerWebExchange exchange) {
109110
*/
110111
public static Tag exception(Throwable exception) {
111112
if (exception != null) {
112-
return Tag.of("exception", exception.getClass().getSimpleName());
113+
String simpleName = exception.getClass().getSimpleName();
114+
return Tag.of("exception", StringUtils.hasText(simpleName) ? simpleName
115+
: exception.getClass().getName());
113116
}
114117
return EXCEPTION_NONE;
115118
}

spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/servlet/WebMvcTags.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,12 @@ private static String getPathInfo(HttpServletRequest request) {
134134
* @return the exception tag derived from the exception
135135
*/
136136
public static Tag exception(Throwable exception) {
137-
return (exception != null
138-
? Tag.of("exception", exception.getClass().getSimpleName())
139-
: EXCEPTION_NONE);
137+
if (exception != null) {
138+
String simpleName = exception.getClass().getSimpleName();
139+
return Tag.of("exception", StringUtils.hasText(simpleName) ? simpleName
140+
: exception.getClass().getName());
141+
}
142+
return EXCEPTION_NONE;
140143
}
141144

142145
}

spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/reactive/server/MetricsWebFilterTests.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,24 @@ public void filterAddsTagsToRegistryForExceptions() {
7777
}).block();
7878
assertMetricsContainsTag("uri", "/projects/{project}");
7979
assertMetricsContainsTag("status", "500");
80+
assertMetricsContainsTag("exception", "IllegalStateException");
81+
}
82+
83+
@Test
84+
public void filterAddsNonEmptyTagsToRegistryForAnonymousExceptions() {
85+
final Exception anonymous = new Exception("test error") {
86+
};
87+
88+
MockServerWebExchange exchange = createExchange("/projects/spring-boot",
89+
"/projects/{project}");
90+
this.webFilter.filter(exchange, (serverWebExchange) -> Mono.error(anonymous))
91+
.onErrorResume((t) -> {
92+
exchange.getResponse().setStatusCodeValue(500);
93+
return exchange.getResponse().setComplete();
94+
}).block();
95+
assertMetricsContainsTag("uri", "/projects/{project}");
96+
assertMetricsContainsTag("status", "500");
97+
assertMetricsContainsTag("exception", anonymous.getClass().getName());
8098
}
8199

82100
@Test

spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/servlet/WebMvcMetricsFilterTests.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,18 @@ public void unhandledError() {
188188
.tags("exception", "RuntimeException").timer().count()).isEqualTo(1L);
189189
}
190190

191+
@Test
192+
public void anonymousError() {
193+
try {
194+
this.mvc.perform(get("/api/c1/anonymousError/10"));
195+
}
196+
catch (Throwable ignore) {
197+
}
198+
assertThat(this.registry.get("http.server.requests")
199+
.tag("uri", "/api/c1/anonymousError/{id}").timer().getId()
200+
.getTag("exception")).endsWith("$1");
201+
}
202+
191203
@Test
192204
public void asyncCallableRequest() throws Exception {
193205
AtomicReference<MvcResult> result = new AtomicReference<>();
@@ -440,6 +452,14 @@ public String alwaysThrowsException(@PathVariable Long id) {
440452
throw new IllegalStateException("Boom on " + id + "!");
441453
}
442454

455+
@Timed
456+
@GetMapping("/anonymousError/{id}")
457+
public String alwaysThrowsAnonymousException(@PathVariable Long id)
458+
throws Exception {
459+
throw new Exception("this exception won't have a simple class name") {
460+
};
461+
}
462+
443463
@Timed
444464
@GetMapping("/unhandledError/{id}")
445465
public String alwaysThrowsUnhandledException(@PathVariable Long id) {

0 commit comments

Comments
 (0)