Skip to content

Commit b9dc9a7

Browse files
author
rostislav.dimitrov
committed
Fixed feign-micrometer exception handling.
1 parent 4f6cff2 commit b9dc9a7

File tree

2 files changed

+51
-18
lines changed

2 files changed

+51
-18
lines changed

micrometer/src/main/java/feign/micrometer/MicrometerObservationCapability.java

+26-10
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import feign.FeignException;
2222
import feign.Request;
2323
import feign.Response;
24+
import feign.Util;
2425
import io.micrometer.observation.Observation;
2526
import io.micrometer.observation.ObservationRegistry;
2627

@@ -59,9 +60,18 @@ public Client enrich(Client client) {
5960
try {
6061
Response response = client.execute(request, options);
6162

62-
throwExceptionOnErrorStatusCode(response, request);
63+
if (response.body() != null) {
64+
response =
65+
response.toBuilder().body(Util.toByteArray(response.body().asInputStream())).build();
66+
}
6367

64-
finalizeObservation(feignContext, observation, null, response);
68+
FeignException exception = null;
69+
70+
if (responseContainsError(response)) {
71+
exception = getFeignExceptionFromStatusCode(response, request);
72+
}
73+
74+
finalizeObservation(feignContext, observation, exception, response);
6575
return response;
6676
} catch (Exception ex) {
6777
finalizeObservation(feignContext, observation, ex, null);
@@ -89,12 +99,13 @@ public AsyncClient<Object> enrich(AsyncClient<Object> client) {
8999
.execute(feignContext.getCarrier(), options, context)
90100
.whenComplete(
91101
(r, ex) -> {
92-
try {
93-
throwExceptionOnErrorStatusCode(r, request);
94-
finalizeObservation(feignContext, observation, ex, r);
95-
} catch (FeignException statusCodeException) {
96-
finalizeObservation(feignContext, observation, statusCodeException, null);
102+
FeignException exception = null;
103+
104+
if (responseContainsError(r)) {
105+
exception = getFeignExceptionFromStatusCode(r, request);
97106
}
107+
108+
finalizeObservation(feignContext, observation, exception, r);
98109
});
99110
} catch (Exception ex) {
100111
finalizeObservation(feignContext, observation, ex, null);
@@ -113,9 +124,14 @@ private void finalizeObservation(
113124
observation.stop();
114125
}
115126

116-
private void throwExceptionOnErrorStatusCode(Response response, Request request) {
117-
if (response.status() >= 400 && response.status() < 600) {
118-
throw FeignException.errorStatus(request.requestTemplate().method(), response);
127+
private FeignException getFeignExceptionFromStatusCode(Response response, Request request) {
128+
if (responseContainsError(response)) {
129+
return FeignException.errorStatus(request.requestTemplate().method(), response);
119130
}
131+
return null;
132+
}
133+
134+
private boolean responseContainsError(Response response) {
135+
return response.status() >= 400 && response.status() < 600;
120136
}
121137
}

micrometer/src/test/java/feign/micrometer/FeignHeaderInstrumentationTest.java

+25-8
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
2121
import static com.github.tomakehurst.wiremock.client.WireMock.get;
2222
import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor;
23+
import static com.github.tomakehurst.wiremock.client.WireMock.noContent;
2324
import static com.github.tomakehurst.wiremock.client.WireMock.ok;
2425
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
2526
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
@@ -99,6 +100,21 @@ void getTemplatedPathForUriWithException(WireMockRuntimeInfo wmRuntimeInfo) {
99100
.isEqualTo("BadRequest");
100101
}
101102

103+
@Test
104+
void getTemplatedPathForUriWithNoContent(WireMockRuntimeInfo wmRuntimeInfo) {
105+
stubFor(get(anyUrl()).willReturn(noContent()));
106+
107+
TestClient testClient = clientInstrumentedWithObservations(wmRuntimeInfo.getHttpBaseUrl());
108+
109+
try {
110+
testClient.templated("1", "2");
111+
} catch (FeignException e) {
112+
assertThat(e).isInstanceOf(FeignException.BadRequest.class);
113+
}
114+
115+
assertThat(meterRegistry.get(METER_NAME).meter().getId().getTag("error")).isEqualTo("none");
116+
}
117+
102118
@Test
103119
void getTemplatedPathForUriForAsync(WireMockRuntimeInfo wmRuntimeInfo)
104120
throws ExecutionException, InterruptedException {
@@ -117,18 +133,19 @@ void getTemplatedPathForUriForAsync(WireMockRuntimeInfo wmRuntimeInfo)
117133
}
118134

119135
@Test
120-
void getTemplatedPathForUriForAsyncWithException(WireMockRuntimeInfo wmRuntimeInfo) {
136+
void getTemplatedPathForUriForAsyncWithException(WireMockRuntimeInfo wmRuntimeInfo)
137+
throws InterruptedException {
121138
stubFor(get(anyUrl()).willReturn(badRequest()));
122139

123140
AsyncTestClient testClient =
124141
asyncClientInstrumentedWithObservations(wmRuntimeInfo.getHttpBaseUrl());
125-
testClient
126-
.templated("1", "2")
127-
.whenComplete(
128-
(s, throwable) -> {
129-
assertThat(meterRegistry.get(METER_NAME).meter().getId().getTag("error"))
130-
.isEqualTo("BadRequest");
131-
});
142+
143+
try {
144+
testClient.templated("1", "2").get();
145+
} catch (ExecutionException e) {
146+
assertThat(meterRegistry.get(METER_NAME).meter().getId().getTag("error"))
147+
.isEqualTo("BadRequest");
148+
}
132149
}
133150

134151
private void assertTags() {

0 commit comments

Comments
 (0)