Skip to content

Commit 10d3c81

Browse files
author
Michael McFadyen
committed
Add outcome tag to web mvc servlet and reactive metrics. Fixes gh-13801.
1 parent d127d07 commit 10d3c81

File tree

6 files changed

+127
-4
lines changed

6 files changed

+127
-4
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ public class DefaultWebFluxTagsProvider implements WebFluxTagsProvider {
3535
public Iterable<Tag> httpRequestTags(ServerWebExchange exchange,
3636
Throwable exception) {
3737
return Arrays.asList(WebFluxTags.method(exchange), WebFluxTags.uri(exchange),
38-
WebFluxTags.exception(exception), WebFluxTags.status(exchange));
38+
WebFluxTags.exception(exception), WebFluxTags.status(exchange),
39+
WebFluxTags.outcome(exchange));
3940
}
4041

4142
}

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

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
*
3131
* @author Jon Schneider
3232
* @author Andy Wilkinson
33+
* @author Michael McFadyen
3334
* @since 2.0.0
3435
*/
3536
public final class WebFluxTags {
@@ -44,6 +45,8 @@ public final class WebFluxTags {
4445

4546
private static final Tag EXCEPTION_NONE = Tag.of("exception", "None");
4647

48+
private static final Tag OUTCOME_UNKNOWN = Tag.of("outcome", "UNKNOWN");
49+
4750
private WebFluxTags() {
4851
}
4952

@@ -60,7 +63,7 @@ public static Tag method(ServerWebExchange exchange) {
6063
}
6164

6265
/**
63-
* Creates a {@code method} tag based on the response status of the given
66+
* Creates a {@code status} tag based on the response status of the given
6467
* {@code exchange}.
6568
* @param exchange the exchange
6669
* @return the "status" tag derived from the response status
@@ -117,4 +120,31 @@ public static Tag exception(Throwable exception) {
117120
return EXCEPTION_NONE;
118121
}
119122

123+
/**
124+
* Creates a {@code outcome} tag based on the response status of the given
125+
* {@code exchange}.
126+
* @param exchange the exchange
127+
* @return the "outcome" tag derived from the response status
128+
*/
129+
public static Tag outcome(ServerWebExchange exchange) {
130+
if (exchange != null && exchange.getResponse().getStatusCode() != null) {
131+
HttpStatus status = exchange.getResponse().getStatusCode();
132+
String outcome;
133+
if (status.is1xxInformational() || status.is2xxSuccessful()
134+
|| status.is3xxRedirection()) {
135+
outcome = "SUCCESS";
136+
}
137+
else if (status.is4xxClientError()) {
138+
outcome = "CLIENT_ERROR";
139+
}
140+
else {
141+
outcome = "SERVER_ERROR";
142+
}
143+
return Tag.of("outcome", outcome);
144+
}
145+
else {
146+
return OUTCOME_UNKNOWN;
147+
}
148+
}
149+
120150
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ public class DefaultWebMvcTagsProvider implements WebMvcTagsProvider {
3434
public Iterable<Tag> getTags(HttpServletRequest request, HttpServletResponse response,
3535
Object handler, Throwable exception) {
3636
return Tags.of(WebMvcTags.method(request), WebMvcTags.uri(request, response),
37-
WebMvcTags.exception(exception), WebMvcTags.status(response));
37+
WebMvcTags.exception(exception), WebMvcTags.status(response),
38+
WebMvcTags.outcome(response));
3839
}
3940

4041
@Override

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

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
* @author Jon Schneider
3333
* @author Andy Wilkinson
3434
* @author Brian Clozel
35+
* @author Michael McFadyen
3536
* @since 2.0.0
3637
*/
3738
public final class WebMvcTags {
@@ -48,6 +49,8 @@ public final class WebMvcTags {
4849

4950
private static final Tag STATUS_UNKNOWN = Tag.of("status", "UNKNOWN");
5051

52+
private static final Tag OUTCOME_UNKNOWN = Tag.of("outcome", "UNKNOWN");
53+
5154
private static final Tag METHOD_UNKNOWN = Tag.of("method", "UNKNOWN");
5255

5356
private WebMvcTags() {
@@ -64,7 +67,7 @@ public static Tag method(HttpServletRequest request) {
6467
}
6568

6669
/**
67-
* Creates a {@code method} tag based on the status of the given {@code response}.
70+
* Creates a {@code status} tag based on the status of the given {@code response}.
6871
* @param response the HTTP response
6972
* @return the status tag derived from the status of the response
7073
*/
@@ -142,4 +145,29 @@ public static Tag exception(Throwable exception) {
142145
return EXCEPTION_NONE;
143146
}
144147

148+
/**
149+
* Creates a {@code outcome} tag based on the status of the given {@code response}.
150+
* @param response the HTTP response
151+
* @return the outcome tag derived from the status of the response
152+
*/
153+
public static Tag outcome(HttpServletResponse response) {
154+
if (response != null) {
155+
int status = response.getStatus();
156+
String outcome;
157+
if (status < 400) {
158+
outcome = "SUCCESS";
159+
}
160+
else if (status < 500) {
161+
outcome = "CLIENT_ERROR";
162+
}
163+
else {
164+
outcome = "SERVER_ERROR";
165+
}
166+
return Tag.of("outcome", outcome);
167+
}
168+
else {
169+
return OUTCOME_UNKNOWN;
170+
}
171+
}
172+
145173
}

spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/web/servlet/WebMvcTagsTests.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
*
3232
* @author Andy Wilkinson
3333
* @author Brian Clozel
34+
* @author Michael McFadyen
3435
*/
3536
public class WebMvcTagsTests {
3637

@@ -91,4 +92,31 @@ public void uriTagIsUnknownWhenRequestIsNull() {
9192
assertThat(tag.getValue()).isEqualTo("UNKNOWN");
9293
}
9394

95+
@Test
96+
public void outcomeTagIsUnknownWhenResponseIsNull() {
97+
Tag tag = WebMvcTags.outcome(null);
98+
assertThat(tag.getValue()).isEqualTo("UNKNOWN");
99+
}
100+
101+
@Test
102+
public void outcomeTagIsSuccessWhenResponseIs2XX() {
103+
this.response.setStatus(200);
104+
Tag tag = WebMvcTags.outcome(this.response);
105+
assertThat(tag.getValue()).isEqualTo("SUCCESS");
106+
}
107+
108+
@Test
109+
public void outcomeTagIsClientErrorWhenResponseIs4XX() {
110+
this.response.setStatus(400);
111+
Tag tag = WebMvcTags.outcome(this.response);
112+
assertThat(tag.getValue()).isEqualTo("CLIENT_ERROR");
113+
}
114+
115+
@Test
116+
public void outcomeTagIsServerErrorWhenResponseIs5XX() {
117+
this.response.setStatus(500);
118+
Tag tag = WebMvcTags.outcome(this.response);
119+
assertThat(tag.getValue()).isEqualTo("SERVER_ERROR");
120+
}
121+
94122
}

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

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
* Tests for {@link WebFluxTags}.
3737
*
3838
* @author Brian Clozel
39+
* @author Michael McFadyen
3940
*/
4041
public class WebFluxTagsTests {
4142

@@ -94,4 +95,38 @@ public void methodTagToleratesNonStandardHttpMethods() {
9495
assertThat(tag.getValue()).isEqualTo("CUSTOM");
9596
}
9697

98+
@Test
99+
public void outcomeTagIsUnknownWhenResponseIsNull() {
100+
Tag tag = WebFluxTags.outcome(null);
101+
assertThat(tag.getValue()).isEqualTo("UNKNOWN");
102+
}
103+
104+
@Test
105+
public void outcomeTagIsUnknownWhenResponseStatusIsNull() {
106+
this.exchange.getResponse().setStatusCode(null);
107+
Tag tag = WebFluxTags.outcome(this.exchange);
108+
assertThat(tag.getValue()).isEqualTo("UNKNOWN");
109+
}
110+
111+
@Test
112+
public void outcomeTagIsSuccessWhenResponseIs2XX() {
113+
this.exchange.getResponse().setStatusCode(HttpStatus.OK);
114+
Tag tag = WebFluxTags.outcome(this.exchange);
115+
assertThat(tag.getValue()).isEqualTo("SUCCESS");
116+
}
117+
118+
@Test
119+
public void outcomeTagIsClientErrorWhenResponseIs4XX() {
120+
this.exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
121+
Tag tag = WebFluxTags.outcome(this.exchange);
122+
assertThat(tag.getValue()).isEqualTo("CLIENT_ERROR");
123+
}
124+
125+
@Test
126+
public void outcomeTagIsServerErrorWhenResponseIs5XX() {
127+
this.exchange.getResponse().setStatusCode(HttpStatus.BAD_GATEWAY);
128+
Tag tag = WebFluxTags.outcome(this.exchange);
129+
assertThat(tag.getValue()).isEqualTo("SERVER_ERROR");
130+
}
131+
97132
}

0 commit comments

Comments
 (0)