Measure and find bottlenecks before they affect your users 1/2

Inspired by a few talks during the last 33rd Degree conference I decided to implement, in one of the applications I develop, metrics which allow developers or operation team monitor running application and possibly detect potential problems early on.

After a quick investigation I decided to use the Metrics framework. What I expected was exposing at least some statistics concerning usage of application components. First of all I would use them during application stress tests to find particular components slowing down the application. After going into production, I imagine that such statistics would be helpful to monitor the running application.

Metrics framework perfectly fits my expectations. It is a Java framework. What is more there are Javascript ports which I am going to use to monitor Node.js server (more about it in one of the next posts).
I decided to integrate the tool with Spring application context using metrics-spring but of course it is possible to use it without Spring.

Here is the Spring application context with Metrics support:

<?xml version="1.0" encoding="UTF-8"?>
<beans
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:metrics="http://www.ryantenney.com/schema/metrics"   xsi:schemaLocation="http://www.springframework.org/schema/beans    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd    http://www.ryantenney.com/schema/metrics http://www.ryantenney.com/schema/metrics/metrics-3.0.xsd">
    <metrics:metric-registry id="metrics"/>
    <metrics:annotation-driven metric-registry="metrics"/>
    <metrics:reporter id="metricsJmxReporter" metric-registry="metrics" type="jmx"/>
    <metrics:reporter id="metricsLogReporter" metric-registry="metrics" type="slf4j" period="1m"/>
</beans>

The configuration defining a few beans:

  • metrics-registry is the bean used to register generated metrics; its explicit definition is optional, if not defined new MetricRegistry bean is created
  • annotation-driven element tells that annotations are used to mark methods/beans under monitoring
  • reporter element is used to report gathered statistics to the defined consumers; there are a few reporter implementation provided (jmx, console, slf4j, ganglia, graphite); I decided to use two of them:
    • jmx (JmxReporter) exposing metrics as JMX MBeans; they can be explored using standard tools like jconsole or VisualVM
    • slf4j (Slf4jReporter) logging metrics to an SLF4J logger; period attribute defines the interval used to report statistics to a log file

When configuration is done, it is time to annotate the bean methods which are to be monitored. To do that there is a simple @Timed annotation provided:

@RequestMapping(value = "/transaction", method = RequestMethod.POST)
@ResponseBody
@Timed
public HttpEntity<SubmitResultDTO> transaction(@RequestBody NewTransactionDTO transaction) { ...}
Using that simple configuration you get JMX MBeans exposed providing a nice set of metrics:
 sc1
What is more, if any statistic is clicked an online chart is presented:

 

sc2

Besides the JMX reporter there is also the SLF4J reported defined, which logs the following pieces of information:

sc3

 

Except JMX or SLF4J reporting more sophisticated tools can be used to consume statistics provided my Metrics. I would recommend trying Ganglia or Graphite as there are reporters provided for those consumers (GangliaReporter and GraphiteReporter).