Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add response code meters for ResponseMetered annotation #3043

Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -18,8 +18,9 @@
* }
* </code></pre>
* <p>
* A meter for the defining class with the name {@code fancyName} will be created for 1xx/2xx/3xx/4xx/5xx responses
* and each time the {@code #fancyName(String)} method is invoked, the appropriate response meter will be marked.
* A meter for the defining class with the name {@code fancyName} will be created for every response code
* in addition to 1xx/2xx/3xx/4xx/5xx responses. Each time the {@code #fancyName(String)} method is invoked,
* the appropriate response meter will be marked.
*/
@Inherited
@Documented
Expand Down
Expand Up @@ -27,6 +27,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
Expand Down Expand Up @@ -127,18 +128,28 @@ public ExceptionMeterMetric(final MetricRegistry registry,
*/
private static class ResponseMeterMetric {
public final List<Meter> meters;
private final ConcurrentMap<Integer, Meter> responseCodeMeters = new ConcurrentHashMap<>();
private final MetricRegistry metricRegistry;
private final String metricName;

public ResponseMeterMetric(final MetricRegistry registry,
final ResourceMethod method,
final ResponseMetered responseMetered) {
final String metricName = chooseName(responseMetered.name(), responseMetered.absolute(), method);
this.metricName = chooseName(responseMetered.name(), responseMetered.absolute(), method);
this.meters = Collections.unmodifiableList(Arrays.asList(
registry.meter(name(metricName, "1xx-responses")), // 1xx
registry.meter(name(metricName, "2xx-responses")), // 2xx
registry.meter(name(metricName, "3xx-responses")), // 3xx
registry.meter(name(metricName, "4xx-responses")), // 4xx
registry.meter(name(metricName, "5xx-responses")) // 5xx
));
this.metricRegistry = registry;
}

public Meter getResponseCodeMeter(int statusCode) {
dennyac marked this conversation as resolved.
Show resolved Hide resolved
return responseCodeMeters
.computeIfAbsent(statusCode, sc -> metricRegistry
.meter(name(metricName, String.format("%d-responses", sc))));
}
}

Expand Down Expand Up @@ -273,11 +284,13 @@ public void onEvent(RequestEvent event) {
if (containerResponse == null) {
if (event.getException() != null) {
metric.meters.get(4).mark();
metric.getResponseCodeMeter(500).mark();
}
} else {
final int responseStatus = containerResponse.getStatus() / 100;
if (responseStatus >= 1 && responseStatus <= 5) {
metric.meters.get(responseStatus - 1).mark();
metric.getResponseCodeMeter(containerResponse.getStatus()).mark();
}
}
}
Expand Down
Expand Up @@ -99,12 +99,27 @@ public void responseMeteredMethodsAreMetered() {
final Meter meter2xx = registry.meter(name(InstrumentedResource.class,
"response2xxMetered",
"2xx-responses"));
final Meter meter200 = registry.meter(name(InstrumentedResource.class,
"response2xxMetered",
"200-responses"));
final Meter meter4xx = registry.meter(name(InstrumentedResource.class,
"response4xxMetered",
"4xx-responses"));
final Meter meter400 = registry.meter(name(InstrumentedResource.class,
"response4xxMetered",
"400-responses"));
final Meter meter401 = registry.meter(name(InstrumentedResource.class,
"response4xxMetered",
"401-responses"));
final Meter meter5xx = registry.meter(name(InstrumentedResource.class,
"response5xxMetered",
"5xx-responses"));
final Meter meter500 = registry.meter(name(InstrumentedResource.class,
"response5xxMetered",
"500-responses"));
final Meter meter503 = registry.meter(name(InstrumentedResource.class,
"response5xxMetered",
"503-responses"));

assertThat(meter2xx.getCount()).isZero();
assertThat(target("response-2xx-metered")
Expand All @@ -118,15 +133,31 @@ public void responseMeteredMethodsAreMetered() {
.get().getStatus())
.isEqualTo(400);

assertThat(target("response-4xx-metered")
.queryParam("status_code", 401)
.request()
.get().getStatus())
.isEqualTo(401);

assertThat(meter5xx.getCount()).isZero();
assertThat(target("response-5xx-metered")
.request()
.get().getStatus())
.isEqualTo(500);
assertThat(target("response-5xx-metered")
.queryParam("status_code", 503)
.request()
.get().getStatus())
.isEqualTo(503);

assertThat(meter2xx.getCount()).isEqualTo(1);
assertThat(meter4xx.getCount()).isEqualTo(1);
assertThat(meter5xx.getCount()).isEqualTo(1);
assertThat(meter4xx.getCount()).isEqualTo(2);
assertThat(meter5xx.getCount()).isEqualTo(2);
assertThat(meter200.getCount()).isEqualTo(1);
assertThat(meter400.getCount()).isEqualTo(1);
assertThat(meter401.getCount()).isEqualTo(1);
assertThat(meter500.getCount()).isEqualTo(1);
assertThat(meter503.getCount()).isEqualTo(1);
}

@Test
Expand Down
Expand Up @@ -62,6 +62,11 @@ public void responseMetered4xxPerClassMethodsAreMetered() {
.request()
.get().getStatus())
.isEqualTo(400);
assertThat(target("responseMetered4xxPerClass")
.queryParam("status_code", 401)
.request()
.get().getStatus())
.isEqualTo(401);
assertThat(target("responseMeteredBadRequestPerClass")
.request()
.get().getStatus())
Expand All @@ -70,11 +75,15 @@ public void responseMetered4xxPerClassMethodsAreMetered() {
final Meter meter4xx = registry.meter(name(InstrumentedResourceResponseMeteredPerClass.class,
"responseMetered4xxPerClass",
"4xx-responses"));
final Meter meter401 = registry.meter(name(InstrumentedResourceResponseMeteredPerClass.class,
"responseMetered4xxPerClass",
"401-responses"));
final Meter meterException4xx = registry.meter(name(InstrumentedResourceResponseMeteredPerClass.class,
"responseMeteredBadRequestPerClass",
"4xx-responses"));

assertThat(meter4xx.getCount()).isEqualTo(1);
assertThat(meter4xx.getCount()).isEqualTo(2);
assertThat(meter401.getCount()).isEqualTo(1);
assertThat(meterException4xx.getCount()).isEqualTo(1);
}

Expand All @@ -84,12 +93,22 @@ public void responseMetered5xxPerClassMethodsAreMetered() {
.request()
.get().getStatus())
.isEqualTo(500);
assertThat(target("responseMetered5xxPerClass")
.queryParam("status_code", 503)
.request()
.get().getStatus())
.isEqualTo(503);

final Meter meter5xx = registry.meter(name(InstrumentedResourceResponseMeteredPerClass.class,
"responseMetered5xxPerClass",
"5xx-responses"));

assertThat(meter5xx.getCount()).isEqualTo(1);
final Meter meter503 = registry.meter(name(InstrumentedResourceResponseMeteredPerClass.class,
"responseMetered5xxPerClass",
"503-responses"));

assertThat(meter5xx.getCount()).isEqualTo(2);
assertThat(meter503.getCount()).isEqualTo(1);
}

@Test
Expand Down
Expand Up @@ -51,15 +51,15 @@ public Response response2xxMetered() {
@GET
@ResponseMetered
@Path("/response-4xx-metered")
public Response response4xxMetered() {
return Response.status(Response.Status.BAD_REQUEST).build();
public Response response4xxMetered(@QueryParam("status_code") @DefaultValue("400") int statusCode) {
return Response.status(Response.Status.fromStatusCode(statusCode)).build();
}

@GET
@ResponseMetered
@Path("/response-5xx-metered")
public Response response5xxMetered() {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
public Response response5xxMetered(@QueryParam("status_code") @DefaultValue("500") int statusCode) {
return Response.status(Response.Status.fromStatusCode(statusCode)).build();
}

@Path("/subresource")
Expand Down
Expand Up @@ -6,6 +6,8 @@
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

Expand All @@ -22,14 +24,14 @@ public Response responseMetered2xxPerClass() {

@GET
@Path("/responseMetered4xxPerClass")
public Response responseMetered4xxPerClass() {
return Response.status(Response.Status.BAD_REQUEST).build();
public Response responseMetered4xxPerClass(@QueryParam("status_code") @DefaultValue("400") int statusCode) {
return Response.status(Response.Status.fromStatusCode(statusCode)).build();
}

@GET
@Path("/responseMetered5xxPerClass")
public Response responseMetered5xxPerClass() {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
public Response responseMetered5xxPerClass(@QueryParam("status_code") @DefaultValue("500") int statusCode) {
return Response.status(Response.Status.fromStatusCode(statusCode)).build();
}

@GET
Expand Down