Skip to content

Commit fe901ca

Browse files
authored
Collect http_response_code for successfull and failed requests (#1375)
On previous implementation response code would only be collected for errors. To avoid mixing new and old metrics, gave the one that includes successfull codes a different name
1 parent c4b89c2 commit fe901ca

File tree

11 files changed

+429
-162
lines changed

11 files changed

+429
-162
lines changed

dropwizard-metrics4/pom.xml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<!--
33
4-
Copyright 2012-2020 The Feign Authors
4+
Copyright 2012-2021 The Feign Authors
55
66
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
77
in compliance with the License. You may obtain a copy of the License at
@@ -50,5 +50,11 @@
5050
<version>2.0.0.0</version>
5151
<scope>test</scope>
5252
</dependency>
53+
<dependency>
54+
<groupId>${project.groupId}</groupId>
55+
<artifactId>feign-micrometer</artifactId>
56+
<type>test-jar</type>
57+
<scope>test</scope>
58+
</dependency>
5359
</dependencies>
5460
</project>

dropwizard-metrics4/src/main/java/feign/metrics4/MeteredClient.java

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2012-2020 The Feign Authors
2+
* Copyright 2012-2021 The Feign Authors
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
55
* in compliance with the License. You may obtain a copy of the License at
@@ -45,7 +45,27 @@ public Response execute(Request request, Options options) throws IOException {
4545
metricRegistry.timer(
4646
metricName.metricName(template.methodMetadata(), template.feignTarget()),
4747
metricSuppliers.timers()).time()) {
48-
return client.execute(request, options);
48+
Response response = client.execute(request, options);
49+
metricRegistry.meter(
50+
MetricRegistry.name(
51+
metricName.metricName(template.methodMetadata(), template.feignTarget(),
52+
"http_response_code"),
53+
"status_group", response.status() / 100 + "xx", "http_status",
54+
String.valueOf(response.status())),
55+
metricSuppliers.meters()).mark();
56+
return response;
57+
} catch (FeignException e) {
58+
metricRegistry.meter(
59+
MetricRegistry.name(
60+
metricName.metricName(template.methodMetadata(), template.feignTarget(),
61+
"http_response_code"),
62+
"status_group", e.status() / 100 + "xx", "http_status", String.valueOf(e.status())),
63+
metricSuppliers.meters()).mark();
64+
throw e;
65+
} catch (IOException | RuntimeException e) {
66+
throw e;
67+
} catch (Exception e) {
68+
throw new IOException(e);
4969
}
5070
}
5171

Lines changed: 59 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2012-2020 The Feign Authors
2+
* Copyright 2012-2021 The Feign Authors
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
55
* in compliance with the License. You may obtain a copy of the License at
@@ -13,49 +13,75 @@
1313
*/
1414
package feign.metrics4;
1515

16-
import static org.hamcrest.Matchers.aMapWithSize;
17-
import static org.hamcrest.Matchers.containsString;
18-
import static org.junit.Assert.assertThat;
16+
import java.util.Arrays;
17+
import java.util.Map;
18+
import java.util.Map.Entry;
19+
import com.codahale.metrics.Metric;
1920
import com.codahale.metrics.MetricRegistry;
20-
import com.codahale.metrics.SharedMetricRegistries;
21-
import org.junit.Test;
22-
import feign.Feign;
23-
import feign.RequestLine;
24-
import feign.mock.HttpMethod;
25-
import feign.mock.MockClient;
26-
import feign.mock.MockTarget;
21+
import feign.Capability;
22+
import feign.Util;
23+
import feign.micrometer.AbstractMetricsTestBase;
2724

28-
public class Metrics4CapabilityTest {
25+
public class Metrics4CapabilityTest
26+
extends AbstractMetricsTestBase<MetricRegistry, String, Metric> {
2927

30-
public interface SimpleSource {
28+
@Override
29+
protected MetricRegistry createMetricsRegistry() {
30+
return new MetricRegistry();
31+
}
32+
33+
protected Capability createMetricCapability() {
34+
return new Metrics4Capability(metricsRegistry);
35+
}
36+
37+
@Override
38+
protected Map<String, Metric> getFeignMetrics() {
39+
return metricsRegistry.getMetrics();
40+
}
3141

32-
@RequestLine("GET /get")
33-
String get(String body);
42+
@Override
43+
protected boolean doesMetricIdIncludeClient(String metricId) {
44+
return metricId.contains("feign.micrometer.AbstractMetricsTestBase$SimpleSource");
45+
}
46+
47+
@Override
48+
protected boolean doesMetricIncludeVerb(String metricId, String verb) {
49+
return metricId.contains(verb);
50+
}
3451

52+
@Override
53+
protected boolean doesMetricIncludeHost(String metricId) {
54+
// since metrics 4 don't have tags, we do not include hostname
55+
return true;
3556
}
3657

37-
@Test
38-
public void addMetricsCapability() {
39-
final MetricRegistry registry = SharedMetricRegistries.getOrCreate("unit_test");
4058

41-
final SimpleSource source = Feign.builder()
42-
.client(new MockClient()
43-
.ok(HttpMethod.GET, "/get", "1234567890abcde"))
44-
.addCapability(new Metrics4Capability(registry))
45-
.target(new MockTarget<>(Metrics4CapabilityTest.SimpleSource.class));
59+
@Override
60+
protected Metric getMetric(String suffix, String... tags) {
61+
Util.checkArgument(tags.length % 2 == 0, "tags must contain key-value pairs %s",
62+
Arrays.toString(tags));
4663

47-
source.get("0x3456789");
4864

49-
assertThat(registry.getMetrics(), aMapWithSize(6));
65+
return getFeignMetrics().entrySet()
66+
.stream()
67+
.filter(entry -> {
68+
String name = entry.getKey();
69+
if (!name.contains(suffix)) {
70+
return false;
71+
}
5072

51-
registry.getMetrics().keySet().forEach(metricName -> assertThat(
52-
"Expect all metric names to include client name:" + metricName,
53-
metricName,
54-
containsString("feign.metrics4.Metrics4CapabilityTest$SimpleSource")));
55-
registry.getMetrics().keySet().forEach(metricName -> assertThat(
56-
"Expect all metric names to include method name:" + metricName,
57-
metricName,
58-
containsString("get")));
73+
for (int i = 0; i < tags.length; i += 2) {
74+
if (!name.contains(tags[i]) && !name.contains(tags[i] + 1)) {
75+
return false;
76+
}
77+
}
78+
79+
return true;
80+
})
81+
.findAny()
82+
.map(Entry::getValue)
83+
.orElse(null);
5984
}
6085

86+
6187
}

dropwizard-metrics5/pom.xml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<!--
33
4-
Copyright 2012-2020 The Feign Authors
4+
Copyright 2012-2021 The Feign Authors
55
66
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
77
in compliance with the License. You may obtain a copy of the License at
@@ -50,5 +50,11 @@
5050
<version>2.0.0.0</version>
5151
<scope>test</scope>
5252
</dependency>
53+
<dependency>
54+
<groupId>${project.groupId}</groupId>
55+
<artifactId>feign-micrometer</artifactId>
56+
<type>test-jar</type>
57+
<scope>test</scope>
58+
</dependency>
5359
</dependencies>
5460
</project>

dropwizard-metrics5/src/main/java/feign/metrics5/MeteredClient.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2012-2020 The Feign Authors
2+
* Copyright 2012-2021 The Feign Authors
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
55
* in compliance with the License. You may obtain a copy of the License at
@@ -45,7 +45,26 @@ public Response execute(Request request, Options options) throws IOException {
4545
metricRegistry.timer(
4646
metricName.metricName(template.methodMetadata(), template.feignTarget()),
4747
metricSuppliers.timers()).time()) {
48-
return client.execute(request, options);
48+
Response response = client.execute(request, options);
49+
metricRegistry.counter(
50+
metricName
51+
.metricName(template.methodMetadata(), template.feignTarget(), "http_response_code")
52+
.tagged("http_status", String.valueOf(response.status()))
53+
.tagged("status_group", response.status() / 100 + "xx"))
54+
.inc();
55+
return response;
56+
} catch (FeignException e) {
57+
metricRegistry.counter(
58+
metricName
59+
.metricName(template.methodMetadata(), template.feignTarget(), "http_response_code")
60+
.tagged("http_status", String.valueOf(e.status()))
61+
.tagged("status_group", e.status() / 100 + "xx"))
62+
.inc();
63+
throw e;
64+
} catch (IOException | RuntimeException e) {
65+
throw e;
66+
} catch (Exception e) {
67+
throw new IOException(e);
4968
}
5069
}
5170

Lines changed: 62 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2012-2020 The Feign Authors
2+
* Copyright 2012-2021 The Feign Authors
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
55
* in compliance with the License. You may obtain a copy of the License at
@@ -13,54 +13,79 @@
1313
*/
1414
package feign.metrics5;
1515

16-
import static org.hamcrest.Matchers.aMapWithSize;
1716
import static org.hamcrest.Matchers.hasEntry;
18-
import static org.junit.Assert.assertThat;
19-
import org.junit.Test;
20-
import feign.Feign;
21-
import feign.RequestLine;
22-
import feign.mock.HttpMethod;
23-
import feign.mock.MockClient;
24-
import feign.mock.MockTarget;
17+
import java.util.Arrays;
18+
import java.util.Map;
19+
import java.util.Map.Entry;
20+
import feign.Capability;
21+
import feign.Util;
22+
import feign.micrometer.AbstractMetricsTestBase;
23+
import io.dropwizard.metrics5.Metric;
24+
import io.dropwizard.metrics5.MetricName;
2525
import io.dropwizard.metrics5.MetricRegistry;
26-
import io.dropwizard.metrics5.SharedMetricRegistries;
2726

28-
public class Metrics5CapabilityTest {
27+
public class Metrics5CapabilityTest
28+
extends AbstractMetricsTestBase<MetricRegistry, MetricName, Metric> {
2929

30-
public interface SimpleSource {
3130

32-
@RequestLine("GET /get")
33-
String get(String body);
31+
@Override
32+
protected MetricRegistry createMetricsRegistry() {
33+
return new MetricRegistry();
34+
}
35+
36+
protected Capability createMetricCapability() {
37+
return new Metrics5Capability(metricsRegistry);
38+
}
39+
40+
@Override
41+
protected Map<MetricName, Metric> getFeignMetrics() {
42+
return metricsRegistry.getMetrics();
43+
}
44+
45+
@Override
46+
protected boolean doesMetricIdIncludeClient(MetricName metricId) {
47+
return hasEntry("client", "feign.micrometer.AbstractMetricsTestBase$SimpleSource")
48+
.matches(metricId.getTags());
49+
}
50+
51+
@Override
52+
protected boolean doesMetricIncludeVerb(MetricName metricId, String verb) {
53+
return hasEntry("method", verb).matches(metricId.getTags());
54+
}
3455

56+
@Override
57+
protected boolean doesMetricIncludeHost(MetricName metricId) {
58+
// hostname is null due to feign-mock shortfalls
59+
return hasEntry("host", null).matches(metricId.getTags());
3560
}
3661

37-
@Test
38-
public void addMetricsCapability() {
39-
final MetricRegistry registry = SharedMetricRegistries.getOrCreate("unit_test");
62+
@Override
63+
protected Metric getMetric(String suffix, String... tags) {
64+
Util.checkArgument(tags.length % 2 == 0, "tags must contain key-value pairs %s",
65+
Arrays.toString(tags));
4066

41-
final SimpleSource source = Feign.builder()
42-
.client(new MockClient()
43-
.ok(HttpMethod.GET, "/get", "1234567890abcde"))
44-
.addCapability(new Metrics5Capability(registry))
45-
.target(new MockTarget<>(Metrics5CapabilityTest.SimpleSource.class));
4667

47-
source.get("0x3456789");
68+
return getFeignMetrics().entrySet()
69+
.stream()
70+
.filter(entry -> {
71+
MetricName name = entry.getKey();
72+
if (!name.getKey().endsWith(suffix)) {
73+
return false;
74+
}
4875

49-
assertThat(registry.getMetrics(), aMapWithSize(6));
76+
for (int i = 0; i < tags.length; i += 2) {
77+
if (name.getTags().containsKey(tags[i])) {
78+
if (!name.getTags().get(tags[i]).equals(tags[i + 1])) {
79+
return false;
80+
}
81+
}
82+
}
5083

51-
registry.getMetrics().keySet().forEach(metricName -> assertThat(
52-
"Expect all metric names to include client name:" + metricName,
53-
metricName.getTags(),
54-
hasEntry("client", "feign.metrics5.Metrics5CapabilityTest$SimpleSource")));
55-
registry.getMetrics().keySet().forEach(metricName -> assertThat(
56-
"Expect all metric names to include method name:" + metricName,
57-
metricName.getTags(),
58-
hasEntry("method", "get")));
59-
registry.getMetrics().keySet().forEach(metricName -> assertThat(
60-
"Expect all metric names to include host name:" + metricName,
61-
metricName.getTags(),
62-
// hostname is null due to feign-mock shortfalls
63-
hasEntry("host", null)));
84+
return true;
85+
})
86+
.findAny()
87+
.map(Entry::getValue)
88+
.orElse(null);
6489
}
6590

6691
}

micrometer/pom.xml

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<!--
33
4-
Copyright 2012-2020 The Feign Authors
4+
Copyright 2012-2021 The Feign Authors
55
66
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
77
in compliance with the License. You may obtain a copy of the License at
@@ -51,4 +51,20 @@
5151
<scope>test</scope>
5252
</dependency>
5353
</dependencies>
54+
55+
<build>
56+
<plugins>
57+
<plugin>
58+
<artifactId>maven-jar-plugin</artifactId>
59+
<executions>
60+
<execution>
61+
<goals>
62+
<goal>test-jar</goal>
63+
</goals>
64+
</execution>
65+
</executions>
66+
</plugin>
67+
</plugins>
68+
</build>
69+
5470
</project>

0 commit comments

Comments
 (0)