Skip to content

Commit e8de5a6

Browse files
committed
Provide a public API for determining a request's outcome
Closes gh-18150
1 parent 9b8decf commit e8de5a6

File tree

8 files changed

+205
-141
lines changed

8 files changed

+205
-141
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright 2012-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.actuate.metrics.http;
18+
19+
import io.micrometer.core.instrument.Tag;
20+
21+
/**
22+
* The outcome of an HTTP request.
23+
*
24+
* @author Andy Wilkinson
25+
* @since 2.2.0
26+
*/
27+
public enum Outcome {
28+
29+
/**
30+
* Outcome of the request was informational.
31+
*/
32+
INFORMATIONAL,
33+
34+
/**
35+
* Outcome of the request was success.
36+
*/
37+
SUCCESS,
38+
39+
/**
40+
* Outcome of the request was redirection.
41+
*/
42+
REDIRECTION,
43+
44+
/**
45+
* Outcome of the request was client error.
46+
*/
47+
CLIENT_ERROR,
48+
49+
/**
50+
* Outcome of the request was server error.
51+
*/
52+
SERVER_ERROR,
53+
54+
/**
55+
* Outcome of the request was unknown.
56+
*/
57+
UNKNOWN;
58+
59+
private final Tag tag;
60+
61+
Outcome() {
62+
this.tag = Tag.of("outcome", name());
63+
}
64+
65+
/**
66+
* Returns the {@code Outcome} as a {@link Tag} named {@code outcome}.
67+
* @return the {@code outcome} {@code Tag}
68+
*/
69+
public Tag asTag() {
70+
return this.tag;
71+
}
72+
73+
/**
74+
* Return the @code Outcome} for the given HTTP {@code status} code.
75+
* @param status the HTTP status code
76+
* @return the matching Outcome
77+
*/
78+
public static Outcome forStatus(int status) {
79+
if (status >= 100 && status < 200) {
80+
return INFORMATIONAL;
81+
}
82+
else if (status >= 200 && status < 300) {
83+
return SUCCESS;
84+
}
85+
else if (status >= 300 && status < 400) {
86+
return REDIRECTION;
87+
}
88+
else if (status >= 400 && status < 500) {
89+
return CLIENT_ERROR;
90+
}
91+
else if (status >= 500 && status < 600) {
92+
return SERVER_ERROR;
93+
}
94+
return UNKNOWN;
95+
}
96+
97+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright 2012-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/**
18+
* Support classes HTTP-related metrics.
19+
*/
20+
package org.springframework.boot.actuate.metrics.http;

spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/client/RestTemplateExchangeTags.java

+4-34
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,12 @@
1818

1919
import java.io.IOException;
2020
import java.net.URI;
21-
import java.util.Collections;
22-
import java.util.HashMap;
23-
import java.util.Map;
2421
import java.util.regex.Pattern;
2522

2623
import io.micrometer.core.instrument.Tag;
2724

25+
import org.springframework.boot.actuate.metrics.http.Outcome;
2826
import org.springframework.http.HttpRequest;
29-
import org.springframework.http.HttpStatus;
3027
import org.springframework.http.client.ClientHttpResponse;
3128
import org.springframework.util.StringUtils;
3229
import org.springframework.web.client.RestTemplate;
@@ -45,30 +42,6 @@ public final class RestTemplateExchangeTags {
4542

4643
private static final Pattern STRIP_URI_PATTERN = Pattern.compile("^https?://[^/]+/");
4744

48-
private static final Tag OUTCOME_UNKNOWN = Tag.of("outcome", "UNKNOWN");
49-
50-
private static final Tag OUTCOME_INFORMATIONAL = Tag.of("outcome", "INFORMATIONAL");
51-
52-
private static final Tag OUTCOME_SUCCESS = Tag.of("outcome", "SUCCESS");
53-
54-
private static final Tag OUTCOME_REDIRECTION = Tag.of("outcome", "REDIRECTION");
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-
60-
private static final Map<HttpStatus.Series, Tag> SERIES_OUTCOMES;
61-
62-
static {
63-
Map<HttpStatus.Series, Tag> seriesOutcomes = new HashMap<>();
64-
seriesOutcomes.put(HttpStatus.Series.INFORMATIONAL, OUTCOME_INFORMATIONAL);
65-
seriesOutcomes.put(HttpStatus.Series.SUCCESSFUL, OUTCOME_SUCCESS);
66-
seriesOutcomes.put(HttpStatus.Series.REDIRECTION, OUTCOME_REDIRECTION);
67-
seriesOutcomes.put(HttpStatus.Series.CLIENT_ERROR, OUTCOME_CLIENT_ERROR);
68-
seriesOutcomes.put(HttpStatus.Series.SERVER_ERROR, OUTCOME_SERVER_ERROR);
69-
SERIES_OUTCOMES = Collections.unmodifiableMap(seriesOutcomes);
70-
}
71-
7245
private RestTemplateExchangeTags() {
7346
}
7447

@@ -155,16 +128,13 @@ public static Tag clientName(HttpRequest request) {
155128
public static Tag outcome(ClientHttpResponse response) {
156129
try {
157130
if (response != null) {
158-
HttpStatus.Series series = HttpStatus.Series.resolve(response.getRawStatusCode());
159-
if (series != null) {
160-
return SERIES_OUTCOMES.getOrDefault(series, OUTCOME_UNKNOWN);
161-
}
131+
return Outcome.forStatus(response.getRawStatusCode()).asTag();
162132
}
163133
}
164-
catch (IOException | IllegalArgumentException ex) {
134+
catch (IOException ex) {
165135
// Continue
166136
}
167-
return OUTCOME_UNKNOWN;
137+
return Outcome.UNKNOWN.asTag();
168138
}
169139

170140
}

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

+3-41
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,11 @@
1717
package org.springframework.boot.actuate.metrics.web.reactive.client;
1818

1919
import java.io.IOException;
20-
import java.util.Collections;
21-
import java.util.HashMap;
22-
import java.util.Map;
2320
import java.util.regex.Pattern;
2421

2522
import io.micrometer.core.instrument.Tag;
2623

27-
import org.springframework.http.HttpStatus;
28-
import org.springframework.http.HttpStatus.Series;
24+
import org.springframework.boot.actuate.metrics.http.Outcome;
2925
import org.springframework.http.client.reactive.ClientHttpRequest;
3026
import org.springframework.web.reactive.function.client.ClientRequest;
3127
import org.springframework.web.reactive.function.client.ClientResponse;
@@ -51,30 +47,6 @@ public final class WebClientExchangeTags {
5147

5248
private static final Tag CLIENT_NAME_NONE = Tag.of("clientName", "none");
5349

54-
private static final Tag OUTCOME_UNKNOWN = Tag.of("outcome", "UNKNOWN");
55-
56-
private static final Tag OUTCOME_INFORMATIONAL = Tag.of("outcome", "INFORMATIONAL");
57-
58-
private static final Tag OUTCOME_SUCCESS = Tag.of("outcome", "SUCCESS");
59-
60-
private static final Tag OUTCOME_REDIRECTION = Tag.of("outcome", "REDIRECTION");
61-
62-
private static final Tag OUTCOME_CLIENT_ERROR = Tag.of("outcome", "CLIENT_ERROR");
63-
64-
private static final Tag OUTCOME_SERVER_ERROR = Tag.of("outcome", "SERVER_ERROR");
65-
66-
private static final Map<Series, Tag> SERIES_OUTCOMES;
67-
68-
static {
69-
Map<Series, Tag> seriesOutcomes = new HashMap<>();
70-
seriesOutcomes.put(Series.INFORMATIONAL, OUTCOME_INFORMATIONAL);
71-
seriesOutcomes.put(Series.SUCCESSFUL, OUTCOME_SUCCESS);
72-
seriesOutcomes.put(Series.REDIRECTION, OUTCOME_REDIRECTION);
73-
seriesOutcomes.put(Series.CLIENT_ERROR, OUTCOME_CLIENT_ERROR);
74-
seriesOutcomes.put(Series.SERVER_ERROR, OUTCOME_SERVER_ERROR);
75-
SERIES_OUTCOMES = Collections.unmodifiableMap(seriesOutcomes);
76-
}
77-
7850
private WebClientExchangeTags() {
7951
}
8052

@@ -146,18 +118,8 @@ public static Tag clientName(ClientRequest request) {
146118
* @since 2.2.0
147119
*/
148120
public static Tag outcome(ClientResponse response) {
149-
try {
150-
if (response != null) {
151-
Series series = HttpStatus.Series.resolve(response.rawStatusCode());
152-
if (series != null) {
153-
return SERIES_OUTCOMES.getOrDefault(series, OUTCOME_UNKNOWN);
154-
}
155-
}
156-
}
157-
catch (IllegalArgumentException ex) {
158-
// Continue
159-
}
160-
return OUTCOME_UNKNOWN;
121+
Outcome outcome = (response != null) ? Outcome.forStatus(response.rawStatusCode()) : Outcome.UNKNOWN;
122+
return outcome.asTag();
161123
}
162124

163125
}

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

+3-28
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import io.micrometer.core.instrument.Tag;
2020

21+
import org.springframework.boot.actuate.metrics.http.Outcome;
2122
import org.springframework.http.HttpStatus;
2223
import org.springframework.util.StringUtils;
2324
import org.springframework.web.reactive.HandlerMapping;
@@ -45,18 +46,6 @@ public final class WebFluxTags {
4546

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

48-
private static final Tag OUTCOME_UNKNOWN = Tag.of("outcome", "UNKNOWN");
49-
50-
private static final Tag OUTCOME_INFORMATIONAL = Tag.of("outcome", "INFORMATIONAL");
51-
52-
private static final Tag OUTCOME_SUCCESS = Tag.of("outcome", "SUCCESS");
53-
54-
private static final Tag OUTCOME_REDIRECTION = Tag.of("outcome", "REDIRECTION");
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-
6049
private WebFluxTags() {
6150
}
6251

@@ -145,22 +134,8 @@ public static Tag exception(Throwable exception) {
145134
*/
146135
public static Tag outcome(ServerWebExchange exchange) {
147136
HttpStatus status = exchange.getResponse().getStatusCode();
148-
if (status != null) {
149-
if (status.is1xxInformational()) {
150-
return OUTCOME_INFORMATIONAL;
151-
}
152-
if (status.is2xxSuccessful()) {
153-
return OUTCOME_SUCCESS;
154-
}
155-
if (status.is3xxRedirection()) {
156-
return OUTCOME_REDIRECTION;
157-
}
158-
if (status.is4xxClientError()) {
159-
return OUTCOME_CLIENT_ERROR;
160-
}
161-
return OUTCOME_SERVER_ERROR;
162-
}
163-
return OUTCOME_UNKNOWN;
137+
Outcome outcome = (status != null) ? Outcome.forStatus(status.value()) : Outcome.UNKNOWN;
138+
return outcome.asTag();
164139
}
165140

166141
}

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

+3-30
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
import io.micrometer.core.instrument.Tag;
2525

26+
import org.springframework.boot.actuate.metrics.http.Outcome;
2627
import org.springframework.http.HttpStatus;
2728
import org.springframework.util.StringUtils;
2829
import org.springframework.web.servlet.HandlerMapping;
@@ -54,18 +55,6 @@ public final class WebMvcTags {
5455

5556
private static final Tag STATUS_UNKNOWN = Tag.of("status", "UNKNOWN");
5657

57-
private static final Tag OUTCOME_UNKNOWN = Tag.of("outcome", "UNKNOWN");
58-
59-
private static final Tag OUTCOME_INFORMATIONAL = Tag.of("outcome", "INFORMATIONAL");
60-
61-
private static final Tag OUTCOME_SUCCESS = Tag.of("outcome", "SUCCESS");
62-
63-
private static final Tag OUTCOME_REDIRECTION = Tag.of("outcome", "REDIRECTION");
64-
65-
private static final Tag OUTCOME_CLIENT_ERROR = Tag.of("outcome", "CLIENT_ERROR");
66-
67-
private static final Tag OUTCOME_SERVER_ERROR = Tag.of("outcome", "SERVER_ERROR");
68-
6958
private static final Tag METHOD_UNKNOWN = Tag.of("method", "UNKNOWN");
7059

7160
private static final Pattern TRAILING_SLASH_PATTERN = Pattern.compile("/$");
@@ -174,24 +163,8 @@ public static Tag exception(Throwable exception) {
174163
* @since 2.1.0
175164
*/
176165
public static Tag outcome(HttpServletResponse response) {
177-
if (response != null) {
178-
HttpStatus.Series series = HttpStatus.Series.resolve(response.getStatus());
179-
if (series != null) {
180-
switch (series) {
181-
case INFORMATIONAL:
182-
return OUTCOME_INFORMATIONAL;
183-
case SUCCESSFUL:
184-
return OUTCOME_SUCCESS;
185-
case REDIRECTION:
186-
return OUTCOME_REDIRECTION;
187-
case CLIENT_ERROR:
188-
return OUTCOME_CLIENT_ERROR;
189-
case SERVER_ERROR:
190-
return OUTCOME_SERVER_ERROR;
191-
}
192-
}
193-
}
194-
return OUTCOME_UNKNOWN;
166+
Outcome outcome = (response != null) ? Outcome.forStatus(response.getStatus()) : Outcome.UNKNOWN;
167+
return outcome.asTag();
195168
}
196169

197170
}

0 commit comments

Comments
 (0)