Spring Boot 2: Migrating from Dropwizard metrics to Micrometer
MetricRegistry
wherever you need some metrics (see: Monitoring and measuring reactive application with Dropwizard Metrics). This has many drawbacks:- we are mixing business and technical dependencies in our components
- therefore I am sometimes reluctant to add new metrics because it requires me to inject
MetricRegistry
- also
MetricRegistry
must be stubbed in unit tests
Think SLF4J, but for metrics
It's actually quite accurate. Whenever I need a
Logger
I don't inject LoggerFactory
, instead I simply use static methods available everywhere. The same goes for Micrometer, I simply use static factory methods on globally available Metrics
class:private final Timer indexTimer = Metrics.timer("es.timer");That's it! You can put metrics anywhere you like without polluting your constructor with
private final LongAdder concurrent = Metrics.gauge("es.concurrent", new LongAdder());
private final Counter successes = Metrics.counter("es.index", "result", "success");
private final Counter failures = Metrics.counter("es.index", "result", "failure");
MetricRegistry
. The API is very similar, e.g.:concurrent.increment()One major difference is gauges vs. counters. In Dropwizard Metrics counters can go up and down whereas in Micrometer counter must increase monotonically. I thought it's a bug... Counter is used in simple scenarios like counting how many requests succeeded. So how can we measure things like the number of concurrent requests or queue length? With gauges, but it's slightly convoluted.
Did you notice how
Metrics.gauge()
takes a new LongAdder()
as an argument? And returns it? This way we create a gauge that track (by periodically polling for value) any instance of Number
class (e.g. AtomicLong
or LongAdder
). We can modify the returned LongAdder
and its current value will be reflected by the gauge. Neat! Moreover, there are helper methods like gaugeCollectionSize()
and gaugeMapSize()
that take any Collection
or Map
respectively - and are quite self-explanatory.Built-in JVM metrics
Micrometer also has a bunch of built-in system and JVM metrics, for example:LogbackMetrics
- number of log messages per each log level. You can watch e.g. error rateProcessorMetrics
- average system loadJvmMemoryMetrics
- memory usage, split by areaJvmThreadMetrics
- number of thread (live, daemon, peak...)JvmGcMetrics
- GC promotion rate, etc.
The dashboard definition for Grafana is available on GitHub. Notice how this application uses about 100 MiB of RAM while sustaining almost two thousand concurrent connections (!) Also less than 45 live threads compared to thousands of concurrent connections is impressive.
It's worth mentioning that the setup of Micrometer in Spring Boot is really simple. First, add the appropriate dependency:
compile 'io.micrometer:micrometer-registry-graphite:1.0.0-rc.5'and a bunch of configuration parameters. Zero code:
spring.metrics.export.graphite:
host: graphite
port: 2003
protocol: Plaintext
step: PT1S
In the last part of this short series, we will wrap everything together in a Spring Web Flux application.
This is part of a longer series:
- Spring, Reactor and ElasticSearch: from callbacks to reactive streams
- Spring, Reactor and ElasticSearch: bechmarking with fake test data
- Monitoring and measuring reactive application with Dropwizard Metrics
- Spring Boot 2: Migrating from Dropwizard metrics to Micrometer
- Spring Boot 2: Fluxes, from Elasticsearch to controller