Skip to content

Commit 96f9aeb

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

File tree

6 files changed

+135
-4
lines changed

6 files changed

+135
-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: 35 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,14 @@ 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+
50+
private static final Tag OUTCOME_SUCCESS = Tag.of("outcome", "SUCCESS");
51+
52+
private static final Tag OUTCOME_CLIENT_ERROR = Tag.of("outcome", "CLIENT_ERROR");
53+
54+
private static final Tag OUTCOME_SERVER_ERROR = Tag.of("outcome", "SERVER_ERROR");
55+
4756
private WebFluxTags() {
4857
}
4958

@@ -60,7 +69,7 @@ public static Tag method(ServerWebExchange exchange) {
6069
}
6170

6271
/**
63-
* Creates a {@code method} tag based on the response status of the given
72+
* Creates a {@code status} tag based on the response status of the given
6473
* {@code exchange}.
6574
* @param exchange the exchange
6675
* @return the "status" tag derived from the response status
@@ -117,4 +126,29 @@ public static Tag exception(Throwable exception) {
117126
return EXCEPTION_NONE;
118127
}
119128

129+
/**
130+
* Creates a {@code outcome} tag based on the response status of the given
131+
* {@code exchange}.
132+
* @param exchange the exchange
133+
* @return the "outcome" tag derived from the response status
134+
*/
135+
public static Tag outcome(ServerWebExchange exchange) {
136+
if (exchange != null && exchange.getResponse().getStatusCode() != null) {
137+
HttpStatus status = exchange.getResponse().getStatusCode();
138+
if (status.is1xxInformational() || status.is2xxSuccessful()
139+
|| status.is3xxRedirection()) {
140+
return OUTCOME_SUCCESS;
141+
}
142+
else if (status.is4xxClientError()) {
143+
return OUTCOME_CLIENT_ERROR;
144+
}
145+
else {
146+
return OUTCOME_SERVER_ERROR;
147+
}
148+
}
149+
else {
150+
return OUTCOME_UNKNOWN;
151+
}
152+
}
153+
120154
}

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: 33 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,14 @@ 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+
54+
private static final Tag OUTCOME_SUCCESS = Tag.of("outcome", "SUCCESS");
55+
56+
private static final Tag OUTCOME_CLIENT_ERROR = Tag.of("outcome", "CLIENT_ERROR");
57+
58+
private static final Tag OUTCOME_SERVER_ERROR = Tag.of("outcome", "SERVER_ERROR");
59+
5160
private static final Tag METHOD_UNKNOWN = Tag.of("method", "UNKNOWN");
5261

5362
private WebMvcTags() {
@@ -64,7 +73,7 @@ public static Tag method(HttpServletRequest request) {
6473
}
6574

6675
/**
67-
* Creates a {@code method} tag based on the status of the given {@code response}.
76+
* Creates a {@code status} tag based on the status of the given {@code response}.
6877
* @param response the HTTP response
6978
* @return the status tag derived from the status of the response
7079
*/
@@ -142,4 +151,27 @@ public static Tag exception(Throwable exception) {
142151
return EXCEPTION_NONE;
143152
}
144153

154+
/**
155+
* Creates a {@code outcome} tag based on the status of the given {@code response}.
156+
* @param response the HTTP response
157+
* @return the outcome tag derived from the status of the response
158+
*/
159+
public static Tag outcome(HttpServletResponse response) {
160+
if (response != null) {
161+
int status = response.getStatus();
162+
if (status < 400) {
163+
return OUTCOME_SUCCESS;
164+
}
165+
else if (status < 500) {
166+
return OUTCOME_CLIENT_ERROR;
167+
}
168+
else {
169+
return OUTCOME_SERVER_ERROR;
170+
}
171+
}
172+
else {
173+
return OUTCOME_UNKNOWN;
174+
}
175+
}
176+
145177
}

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)