Discussion:
Measuring execution time for each resource method separately
Marshall Pierce
2011-12-28 20:18:24 UTC
Permalink
Hi,
I'm trying to find a minimally invasive way of capturing various
statistics about Jersey resource method invocation. It's pretty easy to
hook into the inbound and outbound flow via
com.sun.jersey.spi.container.ResourceFilterFactory and that should work
fine for things like measuring the frequency of 5xx status codes.
However, that doesn't offer an easy way to actually wrap an individual
invocation the way javax.servlet.Filter does.

This is what I'm trying to do conceptually (from
http://metrics.codahale.com/getting-started.html):


final TimerContext context = ...;
try {
// invoke resource method
} finally {
context.stop();
}


The goal is to be able to use a TimerContext (and other metrics) that
are tied to each individual AbstractMethod so that I can see data for
"GET /foo/{fooId}" without having to map "/foo/33" and "/foo/96" to the
proper resource myself.

It looks like one approach might be to combine a request-scoped
TimerContext that gets set in a ContainerRequestFilter with a servlet
Filter that actually measures the time and applies the measured
invocation time to the timer. This feels messy, though.

I can also do it via AOP, and that's not necessarily a bad way to go. I
don't object to AOP; I'm just curious if I can do it cleanly without AOP.

Any suggestions for a better way to do this?

-Marshall
Stephane Bailliez
2011-12-28 22:58:52 UTC
Permalink
May or may not help, but try something like the code below

You can then apply it to individual resources
with: @ResourceFilters(TimingResourceFilter.class)

This can be generalized to everything, in the example below, the
StatisticsService is just a rough in memory service that keeps tracks of
metrics and perform statistical computation with streaming values (I used
commons-math), another implementation can easily be substituted, but that's
the idea. (note that the service could also be injected automatically too
by wrapping it into a SingletonTypeInjectableProvider when you declare it
as a singleton in your application)


/**
* Timing filter on resources. It will monitor how long it takes to invoke
a particular resource and
* store it on the statistics service.
* <p/>
* All resources will be stored in the 'rest' group.
*/
public class TimingResourceFilter implements ResourceFilter,
ContainerRequestFilter, ContainerResponseFilter {
public static final String STATISTICS_GROUP = "rest";

// filter() is actually called in 2 separate stages, so we need to
store the timing in a thread local

private final static class TimerThreadLocal extends ThreadLocal<Long> {
public long start() {
long value = System.currentTimeMillis();
this.set(value);
return value;
}

public long stop() {
return System.currentTimeMillis() - get();
}

@Override
protected Long initialValue() {
return System.currentTimeMillis();
}
}

private final StatisticsService service;
private final static TimerThreadLocal timer = new TimerThreadLocal();

public TimingResourceFilter(@Context ServletContext hc) {
this.service = (StatisticsService)
hc.getAttribute(StatisticsService.SERVICE_KEY);
}

public ContainerRequestFilter getRequestFilter() {
return this;
}

public ContainerResponseFilter getResponseFilter() {
return this;
}

public ContainerRequest filter(ContainerRequest request) {
long now = timer.start();
return request;
}

public ContainerResponse filter(ContainerRequest request,
ContainerResponse response) {
long dt = timer.stop();
service.add(STATISTICS_GROUP, request.getPath(true), dt); // store
metrics the way you want here
return response;
}
}
Post by Marshall Pierce
Hi,
I'm trying to find a minimally invasive way of capturing various
statistics about Jersey resource method invocation. It's pretty easy to
hook into the inbound and outbound flow via com.sun.jersey.spi.container.*
*ResourceFilterFactory and that should work fine for things like
measuring the frequency of 5xx status codes. However, that doesn't offer an
easy way to actually wrap an individual invocation the way
javax.servlet.Filter does.
This is what I'm trying to do conceptually (from
http://metrics.codahale.com/**getting-started.html<http://metrics.codahale.com/getting-started.html>
final TimerContext context = ...;
try {
// invoke resource method
} finally {
context.stop();
}
The goal is to be able to use a TimerContext (and other metrics) that are
tied to each individual AbstractMethod so that I can see data for "GET
/foo/{fooId}" without having to map "/foo/33" and "/foo/96" to the proper
resource myself.
It looks like one approach might be to combine a request-scoped
TimerContext that gets set in a ContainerRequestFilter with a servlet
Filter that actually measures the time and applies the measured invocation
time to the timer. This feels messy, though.
I can also do it via AOP, and that's not necessarily a bad way to go. I
don't object to AOP; I'm just curious if I can do it cleanly without AOP.
Any suggestions for a better way to do this?
-Marshall
Coda Hale
2011-12-29 01:25:39 UTC
Permalink
FWIW, I've just added a metrics-jersey module to Metrics 2.0.0-BETA19-SNAPSHOT which has a ResourceMethodDispatchProvider implementation which adds support for all @Timed/@Metered/@ExceptionMetered-annotated resource methods:

https://github.com/codahale/metrics/blob/master/metrics-jersey/src/main/java/com/yammer/metrics/jersey/InstrumentedResourceMethodDispatchProvider.java

Feedback appreciated.
--
Coda Hale
http://codahale.com
Post by Marshall Pierce
Hi,
I'm trying to find a minimally invasive way of capturing various
statistics about Jersey resource method invocation. It's pretty easy to
hook into the inbound and outbound flow via
com.sun.jersey.spi.container.ResourceFilterFactory and that should work
fine for things like measuring the frequency of 5xx status codes.
However, that doesn't offer an easy way to actually wrap an individual
invocation the way javax.servlet.Filter does.
This is what I'm trying to do conceptually (from
final TimerContext context = ...;
try {
// invoke resource method
} finally {
context.stop();
}
The goal is to be able to use a TimerContext (and other metrics) that
are tied to each individual AbstractMethod so that I can see data for
"GET /foo/{fooId}" without having to map "/foo/33" and "/foo/96" to the
proper resource myself.
It looks like one approach might be to combine a request-scoped
TimerContext that gets set in a ContainerRequestFilter with a servlet
Filter that actually measures the time and applies the measured
invocation time to the timer. This feels messy, though.
I can also do it via AOP, and that's not necessarily a bad way to go. I
don't object to AOP; I'm just curious if I can do it cleanly without AOP.
Any suggestions for a better way to do this?
-Marshall
Marshall Pierce
2011-12-29 22:13:52 UTC
Permalink
Post by Coda Hale
FWIW, I've just added a metrics-jersey module to Metrics
2.0.0-BETA19-SNAPSHOT which has a ResourceMethodDispatchProvider
implementation which adds support for all
https://github.com/codahale/metrics/blob/master/metrics-jersey/src/main/java/com/yammer/metrics/jersey/InstrumentedResourceMethodDispatchProvider.java
Feedback appreciated.
Coda,
First of all, thanks for Metrics. :)

That's an interesting approach. I hadn't noticed the
ResourceMethodDispatchProvider extension point before. (Are all these
various provider and factories documented somewhere I haven't found, or
do I just need to chase down every usage of an interface that ends with
'Provider' or 'Factory'?)

I do have a few reservations, though. It looks like subclassing
EntityParamDispatchProvider would effectively route all requests through
EPDP since InstrumentedResourceMethodDispatchProvider would be checked
before the system-provided implementations. (Unless EPDP would return
null for a given request, in which case no metrics would be applied,
though it doesn't like like this would happen in practice.) I could be
off base here; I haven't had time to try this out yet so I'm not sure if
it behaves this way in practice. Ideally I'd like to let the default
dispatch provider selection mechanism follow the normal path and then
apply metrics around whatever it selects. It looks like this mechanism
also wouldn't play nice if I wanted my own separate dispatch provider to
be used, though I might be misunderstanding how dispatch provider
selection works.

It'd also be nice to abstract out the application of metrics to a given
AbstractResourceMethod. Ideally I'd like to be able to register my own
code to decides not only what to name the per-AbstractResourceMethod
metric but whether or not the metric is used at all. In other words,
while I think those annotations are useful, I'd like to be able to apply
timing (or any other metric) to *all* resource methods without having to
put @Timed on each of them.

Marshall
George Sapountzis
2011-12-29 23:14:27 UTC
Permalink
Post by Marshall Pierce
That's an interesting approach. I hadn't noticed the
ResourceMethodDispatchProvider extension point before. (Are all these
various provider and factories documented somewhere I haven't found, or do I
just need to chase down every usage of an interface that ends with
'Provider' or 'Factory'?)
Here is a list I have here. I think I had just searched for all unique
files under META-INF/services/ in the jersey source tree.

META-INF/services/

javax.ws.rs.ext.RuntimeDelegate
javax.ws.rs.ext.MessageBodyReader
javax.ws.rs.ext.MessageBodyWriter

javax.servlet.ServletContainerInitializer
javax.enterprise.inject.spi.Extension

com.sun.jersey.spi.inject.InjectableProvider

com.sun.jersey.spi.container.ResourceMethodDispatchProvider
com.sun.jersey.spi.container.ResourceMethodCustomInvokerDispatchProvider

com.sun.jersey.spi.HeaderDelegateProvider
com.sun.jersey.spi.StringReaderProvider

com.sun.jersey.spi.container.WebApplicationProvider
com.sun.jersey.spi.container.ContainerProvider
com.sun.jersey.spi.container.ContainerNotifier

com.sun.jersey.spi.container.ContainerRequestFilter

com.sun.jersey.spi.monitoring.RequestListenerAdapter
com.sun.jersey.spi.monitoring.ResponseListenerAdapter
com.sun.jersey.spi.monitoring.DispatchingListenerAdapter
com.sun.jersey.spi.monitoring.GlassfishMonitoringProvider

com.sun.jersey.spi.template.ViewProcessor
Coda Hale
2011-12-30 00:07:19 UTC
Permalink
I agree, it's not a good fit, but the API is a) not really documented regarding overall behavior and b) mostly implemented in private classes.

If folks here have a better idea for how to decorate the underlying ResourceMethodDispatch instance in a cleaner way, I'd change this in a heartbeat.
--
Coda Hale
http://codahale.com
Post by Marshall Pierce
Post by Coda Hale
FWIW, I've just added a metrics-jersey module to Metrics
2.0.0-BETA19-SNAPSHOT which has a ResourceMethodDispatchProvider
implementation which adds support for all
https://github.com/codahale/metrics/blob/master/metrics-jersey/src/main/java/com/yammer/metrics/jersey/InstrumentedResourceMethodDispatchProvider.java
Feedback appreciated.
Coda,
First of all, thanks for Metrics. :)
That's an interesting approach. I hadn't noticed the
ResourceMethodDispatchProvider extension point before. (Are all these
various provider and factories documented somewhere I haven't found, or
do I just need to chase down every usage of an interface that ends with
'Provider' or 'Factory'?)
I do have a few reservations, though. It looks like subclassing
EntityParamDispatchProvider would effectively route all requests through
EPDP since InstrumentedResourceMethodDispatchProvider would be checked
before the system-provided implementations. (Unless EPDP would return
null for a given request, in which case no metrics would be applied,
though it doesn't like like this would happen in practice.) I could be
off base here; I haven't had time to try this out yet so I'm not sure if
it behaves this way in practice. Ideally I'd like to let the default
dispatch provider selection mechanism follow the normal path and then
apply metrics around whatever it selects. It looks like this mechanism
also wouldn't play nice if I wanted my own separate dispatch provider to
be used, though I might be misunderstanding how dispatch provider
selection works.
It'd also be nice to abstract out the application of metrics to a given
AbstractResourceMethod. Ideally I'd like to be able to register my own
code to decides not only what to name the per-AbstractResourceMethod
metric but whether or not the metric is used at all. In other words,
while I think those annotations are useful, I'd like to be able to apply
timing (or any other metric) to *all* resource methods without having to
Marshall
Marshall Pierce
2011-12-30 01:12:37 UTC
Permalink
Post by Coda Hale
I agree, it's not a good fit, but the API is a) not really documented
regarding overall behavior and b) mostly implemented in private
classes.
If folks here have a better idea for how to decorate the underlying
ResourceMethodDispatch instance in a cleaner way, I'd change this in
a heartbeat.
It sounds like we've identified a concrete task that Jersey doesn't
offer a good hook for: being able to observe resource method invocation
in a manner similar to what servlet Filters let you do.

It doesn't seem like this is *too* big a feature to add, but I have only
a passing familiarity with the dispatch mechanisms inside Jersey. Can
anyone weigh in with what would be needed to implement something along
these lines? I'm happy to help out with implementing it, but I'd feel
more comfortable diving in if I had a clearer idea of what will be needed.

Marshall
George Sapountzis
2011-12-30 02:07:09 UTC
Permalink
Post by Coda Hale
I agree, it's not a good fit, but the API is a) not really documented regarding overall behavior and b) mostly implemented in private classes.
If folks here have a better idea for how to decorate the underlying ResourceMethodDispatch instance in a cleaner way, I'd change this in a heartbeat.
haven't looked at the code but there is a
ResourceMethodDispatchAdapter extension point which may be useful
Coda Hale
2011-12-30 03:23:49 UTC
Permalink
Perfect! That was exactly what I needed. Now the ResourceMethodDispatchProvider is a pure decorator.

Thanks!
--
Coda Hale
http://codahale.com
Post by George Sapountzis
Post by Coda Hale
I agree, it's not a good fit, but the API is a) not really documented regarding overall behavior and b) mostly implemented in private classes.
If folks here have a better idea for how to decorate the underlying ResourceMethodDispatch instance in a cleaner way, I'd change this in a heartbeat.
haven't looked at the code but there is a
ResourceMethodDispatchAdapter extension point which may be useful
Marshall Pierce
2011-12-30 06:47:44 UTC
Permalink
Post by Coda Hale
Perfect! That was exactly what I needed. Now the ResourceMethodDispatchProvider is a pure decorator.
Thanks!
-- Coda Hale http://codahale.com
Post by George Sapountzis
haven't looked at the code but there is a
ResourceMethodDispatchAdapter extension point which may be useful
Embarrassingly, I found that interface and ignored it because it said
Adapter and I couldn't see how that could be relevant... ah well. I'm
glad someone was more thorough than I was. :)

Coda, do you see a reason to be particularly concerned with the order in
which metrics are measured around a resource method invocation? In other
words, if I make an abstraction around applying metrics like I described
earlier, do you think it's worth the effort to allow the user to specify
the order in which metrics are measured? (If this is straying too far
afield from jersey usage I'm happy to take the answer off-list.)

Loading...