Drop Wizard Metrics

Dropwizard Metrics is a java library designed to abstract gathering and reporting of metrics. It supports several metric types: Gauge, Counters, Histograms, Meters and Timers and can report these metrics in a variety of ways including JMX, Console, CSV files, SLF4J loggers, and graphite. The integration with graphite makes it particularly powerful as you can then store and analyze your metrics with many different tools like grafana to visualize performance or Shinken for alerting off metrics.

Metric Registry

The MetricRegistry class is a collection of all the metrics for your application. Each metric is associated with a MetricRegistry and has a unique name within that registry (e.g. com.example.Queue.size). There is a static helper method on the MetricRegistry class to help create names:

MetricRegistry.name(Queue.class, "requests", "size")
MetricRegistry.name(Queue.class, "responses", "size")

Global named registries can be shared through the static SharedMetricRegistries class. This allows the same registry to be used in different sections of code without explicitly passing a MetricRegistry instance around.

Metric types

Gauge

Records a single value at a given point in time, for example measuring the rate of cache evictions over time. Each tick we get and record the number of cache evictions.

registry.register(name(SessionStore.class, "cache-evictions"), new Gauge<Integer>() {
    @Override
    public Integer getValue() {
        return cache.getEvictionsCount();
    }
});

Counters

A counter is a simple incrementing and decrementing 64-bit integer

final Counter evictions = registry.counter(name(SessionStore.class, "cache-evictions"));
evictions.inc();
evictions.inc(3);
evictions.dec();
evictions.dec(2);

Histograms

Measures the distribution of values in a stream of data: e.g., the number of results returned by a search. Allow you to measure not just easy things like the min, mean, max, and standard deviation of values, but also quantiles like the median or 95th percentile.

final Histogram resultCounts = registry.histogram(name(ProductDAO.class, "result-counts");
resultCounts.update(results.size());

How a histogram gathers and calculates metrics can be changed, see reservoir.

Meters

Measures the rate at which a set of events occur. Meters measure the rate of the events in a few different ways. The mean rate is the average rate of events. It’s generally useful for trivia, but as it represents the total rate for your application’s entire lifetime (e.g., the total number of requests handled, divided by the number of seconds the process has been running), it does’t offer a sense of recency.

final Meter getRequests = registry.meter(name(WebProxy.class, "get-requests", "requests"));
getRequests.mark();
getRequests.mark(requests.size());

Timers

A timer is basically a histogram of the duration of a type of event and a meter of the rate of its occurrence. Can be used to time things like how long it takes for a database request to take and do statistical analysis of this data.

final Timer timer = registry.timer(name(WebProxy.class, "get-requests"));

final Timer.Context context = timer.time();
try {
    // handle request
} finally {
    context.stop();
}

Health Checks

When an application relies on some external service (a database, a rest service, etc) to monitor the health of that external service explicitly. metrics-healthchecks provides a way to do this with the HealthCheck class.

public class DatabaseHealthCheck extends HealthCheck {
    private final Database database;

    public DatabaseHealthCheck(Database database) {
        this.database = database;
    }

    @Override
    protected Result check() throws Exception {
        if (database.ping()) {
            return Result.healthy();
        }
        return Result.unhealthy("Can't ping database");
    }
}

registry.register("database", new DatabaseHealthCheck(database));

JVM Instrumentation

The metrics-jvm module contains a number of reusable gauges and metric sets which allow you to easily instrument JVM internals such as garbage collection time, memory usage, thread usage etc.

import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.jvm.GarbageCollectorMetricSet;
import com.codahale.metrics.jvm.MemoryUsageGaugeSet;

MetricRegistry registry = new MetricRegistry();

registry.registerAll(new MemoryUsageGaugeSet());  registry.registerAll(new GarbageCollectorMetricSet());
7/26/15 10:42:14 AM ============================================================  

-- Gauges ----------------------------------------------------------------------  
PS-MarkSweep.count  
       value = 1  
PS-MarkSweep.time  
       value = 40  
PS-Scavenge.count  
       value = 7  
PS-Scavenge.time  
       value = 52

This blog has a good demo application using spring boot and dropwizard metrics, including a section explaining what JVM metrics are provided and what they mean.

Instrumenting Web Applications

The metrics-servlet module provides a Servlet filter which has meters for status codes, a counter for the number of active requests, and a timer for request duration.

In web.xml:

<filter>
    <filter-name>instrumentedFilter</filter-name>
    <filter-class>com.codahale.metrics.servlet.InstrumentedFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>instrumentedFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

You will need to add your MetricRegistry to the servlet context as an attribute named com.codahale.metrics.servlet.InstrumentedFilter.registry you can do this several ways, like extending InstrumentedFilterContextListener or dependency injection

metrics-servlet vs metrics-servlets

Here are two very similar and confusingly named modules. I'm still a little confused without having worked with it first hand, but my understanding is that metrics-servlet (sans 's') will automatically gather metrics around your various request endpoints while metrics-servlets (sans-sans 's') provides a sort of admin interface into your metrics which you can access via http. It also provides a couple convenience endpoints like /ping which provides you a ping endpoint and /healthcheck which runs all your healthchecks but it is primarily about access to metrics.

So metrics-servlet helps gathering data while metrics-servlets helps access data.

Spring Integration

The metrics-spring module is a third-party module which enables the use of Metrics annotations with Spring AOP, complete with simple XML configuration

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:metrics="http://www.yammer.com/schema/metrics"
       xsi:schemaLocation="
           http://www.yammer.com/schema/metrics http://www.yammer.com/schema/metrics/metrics.xsd
           http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

    <metrics:metrics-registry id="metrics"/>
    <metrics:health-check-registry id="health"/>

    <metrics:annotation-driven metrics-registry="metrics" health-check-registry="health"/>

    <metrics:jmx-reporter id="metricsJmxReporter" metrics-registry="metrics"/>

    <!-- other beans -->

</beans>

Graphite Integration

The metrics-graphite module provides GraphiteReporter, which allows your application to constantly stream metric values to a Graphite server

final Graphite graphite = new Graphite(new InetSocketAddress("graphite.example.com", 2003));
final GraphiteReporter reporter = GraphiteReporter.forRegistry(registry)
                                                  .prefixedWith("web1.example.com")
                                                  .convertRatesTo(TimeUnit.SECONDS)
                                                  .convertDurationsTo(TimeUnit.MILLISECONDS)
                                                  .filter(MetricFilter.ALL)
                                                  .build(graphite);
reporter.start(1, TimeUnit.MINUTES);

It can easily be combined with the metrics-spring module to get all the spring DI goodies as seen in this blog.

Alternative - Netflix Servo

Netflix Servo was created apparently because dropwizard metrics wasn't satisfying the people at Netflix who decided to write their own library in the same vein. It offers many of the same concepts as Dropwizard Metrics including annotation drive metrics, automatic JMX exposure and publishing to external systems. Not sure if the ecosystem is as large as metrics, it doesn't seem to be at first glance.

Most of the other alternatives I found like javasimon and ERMA seemed far less developed, documented, supported, etc. They honestly don't warrant very much examination compared to Dropwizard Metrics and Servo. I could be wrong/lazy though.

Additional Resources

results matching ""

    No results matching ""