44. Metrics

Spring Boot Actuator includes a metrics service with ‘gauge’ and ‘counter’ support. A ‘gauge’ records a single value; and a ‘counter’ records a delta (an increment or decrement). Spring Boot Actuator also provides a PublicMetrics interface that you can implement to expose metrics that you cannot record via one of those two mechanisms. Look at SystemPublicMetrics for an example.

Metrics for all HTTP requests are automatically recorded, so if you hit the metrics endpoint you should see a response similar to this:

{
    "counter.status.200.root": 20,
    "counter.status.200.metrics": 3,
    "counter.status.200.star-star": 5,
    "counter.status.401.root": 4,
    "gauge.response.star-star": 6,
    "gauge.response.root": 2,
    "gauge.response.metrics": 3,
    "classes": 5808,
    "classes.loaded": 5808,
    "classes.unloaded": 0,
    "heap": 3728384,
    "heap.committed": 986624,
    "heap.init": 262144,
    "heap.used": 52765,
    "mem": 986624,
    "mem.free": 933858,
    "processors": 8,
    "threads": 15,
    "threads.daemon": 11,
    "threads.peak": 15,
    "uptime": 494836,
    "instance.uptime": 489782,
    "datasource.primary.active": 5,
    "datasource.primary.usage": 0.25
}

Here we can see basic memory, heap, class loading, processor and thread pool information along with some HTTP metrics. In this instance the root (‘/’) and /metrics URLs have returned HTTP 200 responses 20 and 3 times respectively. It also appears that the root URL returned HTTP 401 (unauthorized) 4 times. The double asterix (star-star) comes from a request matched by Spring MVC as /** (normally a static resource).

The gauge shows the last response time for a request. So the last request to root took 2ms to respond and the last to /metrics took 3ms.

[Note]Note

In this example we are actually accessing the endpoint over HTTP using the /metrics URL, this explains why metrics appears in the response.

44.1 System metrics

The following system metrics are exposed by Spring Boot:

  • The total system memory in Kb (mem)
  • The amount of free memory in Kb (mem.free)
  • The number of processors (processors)
  • The system uptime in milliseconds (uptime)
  • The application context uptime in milliseconds (instance.uptime)
  • The average system load (systemload.average)
  • Heap information in Kb (heap, heap.committed, heap.init, heap.used)
  • Thread information (threads, thread.peak, thead.daemon)
  • Class load information (classes, classes.loaded, classes.unloaded)
  • Garbage collection information (gc.xxx.count, gc.xxx.time)

44.2 DataSource metrics

The following metrics are exposed for each supported DataSource defined in your application:

  • The maximum number connections (datasource.xxx.max).
  • The minimum number of connections (datasource.xxx.min).
  • The number of active connections (datasource.xxx.active)
  • The current usage of the connection pool (datasource.xxx.usage).

All data source metrics share the datasource. prefix. The prefix is further qualified for each data source:

  • If the data source is the primary data source (that is either the only available data source or the one flagged @Primary amongst the existing ones), the prefix is datasource.primary.
  • If the data source bean name ends with dataSource, the prefix is the name of the bean without dataSource (i.e. datasource.batch for batchDataSource).
  • In all other cases, the name of the bean is used.

It is possible to override part or all of those defaults by registering a bean with a customized version of DataSourcePublicMetrics. By default, Spring Boot provides metadata for all supported datasources; you can add additional DataSourcePoolMetadataProvider beans if your favorite data source isn’t supported out of the box. See DataSourcePoolMetadataProvidersConfiguration for examples.

44.3 Tomcat session metrics

If you are using Tomcat as your embedded servlet container, session metrics will automatically be exposed. The httpsessions.active and httpsessions.max keys provide the number of active and maximum sessions.

44.4 Recording your own metrics

To record your own metrics inject a CounterService and/or GaugeService into your bean. The CounterService exposes increment, decrement and reset methods; the GaugeService provides a submit method.

Here is a simple example that counts the number of times that a method is invoked:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.metrics.CounterService;
import org.springframework.stereotype.Service;

@Service
public class MyService {

    private final CounterService counterService;

    @Autowired
    public MyService(CounterService counterService) {
        this.counterService = counterService;
    }

    public void exampleMethod() {
        this.counterService.increment("services.system.myservice.invoked");
    }

}
[Tip]Tip

You can use any string as a metric name but you should follow guidelines of your chosen store/graphing technology. Some good guidelines for Graphite are available on Matt Aimonetti’s Blog.

44.5 Adding your own public metrics

To add additional metrics that are computed every time the metrics endpoint is invoked, simply register additional PublicMetrics implementation bean(s). By default, all such beans are gathered by the endpoint. You can easily change that by defining your own MetricsEndpoint.

44.6 Metric repositories

Metric service implementations are usually bound to a MetricRepository. A MetricRepository is responsible for storing and retrieving metric information. Spring Boot provides an InMemoryMetricRepository and a RedisMetricRepository out of the box (the in-memory repository is the default) but you can also write your own. The MetricRepository interface is actually composed of higher level MetricReader and MetricWriter interfaces. For full details refer to the Javadoc.

There’s nothing to stop you hooking a MetricRepository with back-end storage directly into your app, but we recommend using the default InMemoryMetricRepository (possibly with a custom Map instance if you are worried about heap usage) and populating a back-end repository through a scheduled export job. In that way you get some buffering in memory of the metric values and you can reduce the network chatter by exporting less frequently or in batches. Spring Boot provides an Exporter interface and a few basic implementations for you to get started with that.

44.7 Dropwizard Metrics

User of the Dropwizard ‘Metrics’ library will automatically find that Spring Boot metrics are published to com.codahale.metrics.MetricRegistry. A default com.codahale.metrics.MetricRegistry Spring bean will be created when you declare a dependency to the io.dropwizard.metrics:metrics-core library; you can also register you own @Bean instance if you need customizations. Metrics from the MetricRegistry are also automatically exposed via the /metrics endpoint

Users can create Dropwizard metrics by prefixing their metric names with the appropriate type (e.g. histogram.*, meter.*).

44.8 Message channel integration

If the ‘Spring Messaging’ jar is on your classpath a MessageChannel called metricsChannel is automatically created (unless one already exists). All metric update events are additionally published as ‘messages’ on that channel. Additional analysis or actions can be taken by clients subscribing to that channel.