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

#859 fix inherited timed annotation #861

Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fixing issue #859 that did not allow metric annotations on inherited …
…resource methods
  • Loading branch information
mtakaki committed Sep 1, 2015
commit 74ae4fa717e5dca6750a4cd4bd4f94e43c369669
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import org.glassfish.jersey.server.monitoring.ApplicationEventListener;
import org.glassfish.jersey.server.monitoring.RequestEvent;
import org.glassfish.jersey.server.monitoring.RequestEventListener;
import org.omg.CORBA.DefinitionKind;

import javax.ws.rs.core.Configuration;
import javax.ws.rs.ext.Provider;
Expand All @@ -35,14 +36,13 @@
* request events indicating that the method is about to be invoked, or just got done
* being invoked.
*/

@Provider
public class InstrumentedResourceMethodApplicationListener implements ApplicationEventListener, ModelProcessor {

private final MetricRegistry metrics;
private ConcurrentMap<Method, Timer> timers = new ConcurrentHashMap<>();
private ConcurrentMap<Method, Meter> meters = new ConcurrentHashMap<>();
private ConcurrentMap<Method, ExceptionMeterMetric> exceptionMeters = new ConcurrentHashMap<>();
private final ConcurrentMap<String, Timer> timers = new ConcurrentHashMap<>();
private final ConcurrentMap<String, Meter> meters = new ConcurrentHashMap<>();
private final ConcurrentMap<String, ExceptionMeterMetric> exceptionMeters = new ConcurrentHashMap<>();

/**
* Construct an application event listener using the given metrics registry.
Expand All @@ -68,29 +68,34 @@ private static class ExceptionMeterMetric {

public ExceptionMeterMetric(final MetricRegistry registry,
final Class<?> handlerClass,
final ResourceMethod method,
final Method definitionMethod,
final ExceptionMetered exceptionMetered) {
final String name = chooseName(exceptionMetered.name(),
exceptionMetered.absolute(), handlerClass, method, ExceptionMetered.DEFAULT_NAME_SUFFIX);
exceptionMetered.absolute(), handlerClass, definitionMethod, ExceptionMetered.DEFAULT_NAME_SUFFIX);
this.meter = registry.meter(name);
this.cause = exceptionMetered.cause();
}
}

private static class TimerRequestEventListener implements RequestEventListener {
private final ConcurrentMap<Method, Timer> timers;
private final ConcurrentMap<String, Timer> timers;
private Timer.Context context = null;

public TimerRequestEventListener(final ConcurrentMap<Method, Timer> timers) {
public TimerRequestEventListener(final ConcurrentMap<String, Timer> timers) {
this.timers = timers;
}

@Override
public void onEvent(RequestEvent event) {
if (event.getType() == RequestEvent.Type.RESOURCE_METHOD_START) {
final Timer timer = this.timers.get(event.getUriInfo()
.getMatchedResourceMethod().getInvocable().getHandlingMethod());
if (timer != null) {
final ResourceMethod method = event.getUriInfo().getMatchedResourceMethod();
final Invocable methodInvocable = method.getInvocable();
final Method definitionMethod = methodInvocable.getDefinitionMethod();
final Timed annotation = definitionMethod.getAnnotation(Timed.class);

if (annotation != null) {
final Class<?> handlerClass = methodInvocable.getHandler().getHandlerClass();
final Timer timer = this.timers.get(chooseName(annotation.name(), annotation.absolute(), handlerClass, definitionMethod));
this.context = timer.time();
}
} else if (event.getType() == RequestEvent.Type.RESOURCE_METHOD_FINISHED) {
Expand All @@ -102,43 +107,55 @@ public void onEvent(RequestEvent event) {
}

private static class MeterRequestEventListener implements RequestEventListener {
private final ConcurrentMap<Method, Meter> meters;
private final ConcurrentMap<String, Meter> meters;

public MeterRequestEventListener(final ConcurrentMap<Method, Meter> meters) {
public MeterRequestEventListener(final ConcurrentMap<String, Meter> meters) {
this.meters = meters;
}

@Override
public void onEvent(RequestEvent event) {
if (event.getType() == RequestEvent.Type.RESOURCE_METHOD_START) {
final Meter meter = this.meters.get(event.getUriInfo()
.getMatchedResourceMethod().getInvocable().getDefinitionMethod());
if (meter != null) {
final ResourceMethod method = event.getUriInfo().getMatchedResourceMethod();
final Invocable methodInvocable = method.getInvocable();
final Method definitionMethod = methodInvocable.getDefinitionMethod();
final Metered annotation = definitionMethod.getAnnotation(Metered.class);

if (annotation != null) {
final Class<?> handlerClass = methodInvocable.getHandler().getHandlerClass();
final Meter meter = this.meters.get(chooseName(annotation.name(), annotation.absolute(), handlerClass, definitionMethod));
meter.mark();
}
}
}
}

private static class ExceptionMeterRequestEventListener implements RequestEventListener {
private final ConcurrentMap<Method, ExceptionMeterMetric> exceptionMeters;
private final ConcurrentMap<String, ExceptionMeterMetric> exceptionMeters;

public ExceptionMeterRequestEventListener(final ConcurrentMap<Method, ExceptionMeterMetric> exceptionMeters) {
public ExceptionMeterRequestEventListener(final ConcurrentMap<String, ExceptionMeterMetric> exceptionMeters) {
this.exceptionMeters = exceptionMeters;
}

@Override
public void onEvent(RequestEvent event) {
if (event.getType() == RequestEvent.Type.ON_EXCEPTION) {
final ResourceMethod method = event.getUriInfo().getMatchedResourceMethod();
final ExceptionMeterMetric metric = (method != null) ?
this.exceptionMeters.get(method.getInvocable().getDefinitionMethod()) : null;

if (metric != null) {
if (metric.cause.isAssignableFrom(event.getException().getClass()) ||
(event.getException().getCause() != null &&
metric.cause.isAssignableFrom(event.getException().getCause().getClass()))) {
metric.meter.mark();

if (method != null) {
final Invocable methodInvocable = method.getInvocable();
final Method definitionMethod = methodInvocable.getDefinitionMethod();
final ExceptionMetered annotation = definitionMethod.getAnnotation(ExceptionMetered.class);

if (annotation != null) {
final Class<?> handlerClass = methodInvocable.getHandler().getHandlerClass();
final ExceptionMeterMetric metric = this.exceptionMeters.get(chooseName(annotation.name(), annotation.absolute(), handlerClass, definitionMethod));

if (metric.cause.isAssignableFrom(event.getException().getClass()) ||
(event.getException().getCause() != null &&
metric.cause.isAssignableFrom(event.getException().getCause().getClass()))) {
metric.meter.mark();
}
}
}
}
Expand Down Expand Up @@ -209,63 +226,49 @@ public RequestEventListener onRequest(final RequestEvent event) {

private void registerTimedAnnotations(final ResourceMethod method) {
final Invocable methodInvocable = method.getInvocable();
final Class<?> handlerClass = methodInvocable.getHandler().getHandlerClass();
final Method handlingMethod = methodInvocable.getHandlingMethod();
final Timed annotation = handlingMethod.getAnnotation(Timed.class);
final Method definitionMethod = methodInvocable.getDefinitionMethod();
final Timed annotation = definitionMethod.getAnnotation(Timed.class);

if (annotation != null) {
timers.putIfAbsent(handlingMethod, timerMetric(this.metrics, handlerClass, method, annotation));
if (annotation != null) {
final Class<?> handlerClass = methodInvocable.getHandler().getHandlerClass();
String methodName = chooseName(annotation.name(), annotation.absolute(), handlerClass, definitionMethod);
timers.putIfAbsent(methodName, this.metrics.timer(methodName));
}
}

private void registerMeteredAnnotations(final ResourceMethod method) {
final Invocable methodInvocable = method.getInvocable();
final Class<?> handlerClass = methodInvocable.getHandler().getHandlerClass();
final Method handlingMethod = methodInvocable.getHandlingMethod();
final Metered annotation = handlingMethod.getAnnotation(Metered.class);
final Method definitionMethod = methodInvocable.getDefinitionMethod();
final Metered annotation = definitionMethod.getAnnotation(Metered.class);

if (annotation != null) {
meters.putIfAbsent(handlingMethod, meterMetric(metrics, handlerClass, method, annotation));
if (annotation != null) {
final Class<?> handlerClass = methodInvocable.getHandler().getHandlerClass();
String methodName = chooseName(annotation.name(), annotation.absolute(), handlerClass, definitionMethod);
meters.putIfAbsent(methodName, this.metrics.meter(methodName));
}
}

private void registerExceptionMeteredAnnotations(final ResourceMethod method) {
final Invocable methodInvocable = method.getInvocable();
final Class<?> handlerClass = methodInvocable.getHandler().getHandlerClass();
final Method handlingMethod = methodInvocable.getHandlingMethod();
final ExceptionMetered annotation = handlingMethod.getAnnotation(ExceptionMetered.class);
final Method definitionMethod = methodInvocable.getDefinitionMethod();
final ExceptionMetered annotation = definitionMethod.getAnnotation(ExceptionMetered.class);

if (annotation != null) {
exceptionMeters.putIfAbsent(handlingMethod, new ExceptionMeterMetric(metrics, handlerClass, method, annotation));
if (annotation != null) {
final Class<?> handlerClass = methodInvocable.getHandler().getHandlerClass();
String methodName = chooseName(annotation.name(), annotation.absolute(), handlerClass, definitionMethod);
exceptionMeters.putIfAbsent(methodName, new ExceptionMeterMetric(metrics, handlerClass, definitionMethod, annotation));
}
}

private static Timer timerMetric(final MetricRegistry registry,
final Class<?> handlerClass,
final ResourceMethod method,
final Timed timed) {
final String name = chooseName(timed.name(), timed.absolute(), handlerClass, method);
return registry.timer(name);
}

private static Meter meterMetric(final MetricRegistry registry,
final Class<?> handlerClass,
final ResourceMethod method,
final Metered metered) {
final String name = chooseName(metered.name(), metered.absolute(), handlerClass, method);
return registry.meter(name);
}

protected static String chooseName(final String explicitName, final boolean absolute, final Class<?> handlerClass,
final ResourceMethod method, final String... suffixes) {
protected static String chooseName(final String explicitName, final boolean absolute, final Class<?> handlerClass,
final Method definitionMethod, final String... suffixes) {
if (explicitName != null && !explicitName.isEmpty()) {
if (absolute) {
return explicitName;
}
return name(handlerClass, explicitName);
}

return name(name(handlerClass, method.getInvocable().getDefinitionMethod().getName()),
suffixes);
return name(name(handlerClass, definitionMethod.getName()), suffixes);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Timer;
import com.codahale.metrics.jersey2.resources.InstrumentedChildResource;
import com.codahale.metrics.jersey2.resources.InstrumentedParentResource;
import com.codahale.metrics.jersey2.resources.InstrumentedResource;
import com.codahale.metrics.jersey2.resources.InstrumentedSecondChildResource;
import com.codahale.metrics.jersey2.resources.InstrumentedSubResource;
Expand Down Expand Up @@ -61,15 +60,39 @@ public void timedMethodsAreTimed() {

assertThat(timer.getCount()).isEqualTo(1);
}


@Test
public void absoluteTimedMethodsAreTimed() {
assertThat(target("timed/absolute")
.request()
.get(String.class))
.isEqualTo("yay");

final Timer timer = registry.timer("absoluteTimed");

assertThat(timer.getCount()).isEqualTo(1);
}

@Test
public void namedTimedMethodsAreTimed() {
assertThat(target("timed/named")
.request()
.get(String.class))
.isEqualTo("yay");

final Timer timer = registry.timer(name(InstrumentedResource.class, "namedTimed"));

assertThat(timer.getCount()).isEqualTo(1);
}

@Test
public void childTimedMethodsAreTimed() {
assertThat(target("/child/timed")
.request()
.get(String.class))
.isEqualTo("yay");

final Timer timer = registry.timer(name(InstrumentedParentResource.class, "timed"));
final Timer timer = registry.timer(name(InstrumentedChildResource.class, "timed"));

assertThat(timer.getCount()).isEqualTo(1);
}
Expand All @@ -85,6 +108,28 @@ public void meteredMethodsAreMetered() {
assertThat(meter.getCount()).isEqualTo(1);
}

@Test
public void absoluteMeteredMethodsAreMetered() {
assertThat(target("metered/absolute")
.request()
.get(String.class))
.isEqualTo("woo");

final Meter meter = registry.meter("absoluteMetered");
assertThat(meter.getCount()).isEqualTo(1);
}

@Test
public void namedMeteredMethodsAreMetered() {
assertThat(target("metered/named")
.request()
.get(String.class))
.isEqualTo("woo");

final Meter meter = registry.meter(name(InstrumentedResource.class, "namedMetered"));
assertThat(meter.getCount()).isEqualTo(1);
}

@Test
public void exceptionMeteredMethodsAreExceptionMetered() {
final Meter meter = registry.meter(name(InstrumentedResource.class,
Expand Down Expand Up @@ -112,6 +157,57 @@ public void exceptionMeteredMethodsAreExceptionMetered() {
assertThat(meter.getCount()).isEqualTo(1);
}

@Test
public void absoluteExceptionMeteredMethodsAreExceptionMetered() {
final Meter meter = registry.meter("absoluteExceptionMetered");

assertThat(target("exception-metered/absolute")
.request()
.get(String.class))
.isEqualTo("fuh");

assertThat(meter.getCount()).isZero();

try {
target("exception-metered/absolute")
.queryParam("splode", true)
.request()
.get(String.class);

failBecauseExceptionWasNotThrown(ProcessingException.class);
} catch (ProcessingException e) {
assertThat(e.getCause()).isInstanceOf(IOException.class);
}

assertThat(meter.getCount()).isEqualTo(1);
}

@Test
public void namedExceptionMeteredMethodsAreExceptionMetered() {
final Meter meter = registry.meter(name(InstrumentedResource.class,
"namedExceptionMeteredOtherName"));

assertThat(target("exception-metered/named")
.request()
.get(String.class))
.isEqualTo("fuh");

assertThat(meter.getCount()).isZero();

try {
target("exception-metered/named")
.queryParam("splode", true)
.request()
.get(String.class);

failBecauseExceptionWasNotThrown(ProcessingException.class);
} catch (ProcessingException e) {
assertThat(e.getCause()).isInstanceOf(IOException.class);
}

assertThat(meter.getCount()).isEqualTo(1);
}

@Test
public void testResourceNotFound() {
final Response response = target().path("not-found").request().get();
Expand Down
Loading