Several months ago I put up a tutorial on using Jetty, Jersey, Jackson and Guice to make a small JSON web service stack. The code is more of a proof of concept than anything else, but we’re going to be giving it a few more real-world features today by adding the use of the Metrics library. As a quick review, the project is a web service that allows accessing peanut butter & jelly sandwiches over HTTP. It has a primitive “stats” resource to allow you to see how many sandwiches have been made and how much peanut butter & jelly was used. This stats facility is more of demo of how to wire stuff together with Guice and how requests are routed to JAX-RS resources than a useful way to monitor usage, though. We’re going to do two things to improve the situation. First, we’ll re-implement the number of sandwiches and amount of PB&J tracking using individual Counters and Gauges. Second, we’ll add code to automatically create various useful metrics for every resource method via Jersey ResourceFilter, ResourceFilterFactory, ContainerFilterResponseFilter, ResourceMethodDispatchAdapter, and ResourceMethodDispatchProvider implementations. Fun! As before, I’ll outline the code changes in this article, but the complete code is in the repo for your browsing pleasure.
Reimplementing Sandwich stats
The SandwichStats object (a singleton) keeps track of the number of sandwiches and the amount of PB & J used to make them. This data is exposed through SandwichStatsResource, which response to GET of /sandwich/stats
with data like {"sandwichesMade":2,"gramsOfJam":200,"gramsOfPeanutButter":400}
. We want to keep track of those three numbers with metrics now as well. Metrics (the library) offers many different types of metrics (the concept). For these three numbers, there are two ways we could do it. We could use a Gauge to expose the numbers that SandwichStats is already tracking internally, or we could use a Counter that we increment whenever we increment the fields that SandwichStats already has. To demonstrate the use of Gauges and Counters, we’ll do some of both. When creating a metric object, you can use a MetricsRegistry instance or the static method on the Metrics class. If you have multiple applications running inside the same JVM, or need that separation of metrics for other reasons, use MetricsRegistery. If you aren’t doing that, you can use the static methods on Metrics, but we’ll go ahead and use a MetricsRegistry because it’s just as easy as using the Metrics class when we have Guice to help us. First, add a binding for MetricsRegistry in a Guice module:
bind(MetricsRegistry.class).toInstance(Metrics.defaultRegistry());