MetricRegistrywherever 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
MetricRegistrymust be stubbed in unit tests
Think SLF4J, but for metrics
It's actually quite accurate. Whenever I need a
LoggerI 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
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
new LongAdder()as an argument? And returns it? This way we create a gauge that track (by periodically polling for value) any instance of
LongAdder). We can modify the returned
LongAdderand its current value will be reflected by the gauge. Neat! Moreover, there are helper methods like
gaugeMapSize()that take any
Maprespectively - and are quite self-explanatory.
Built-in JVM metricsMicrometer 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 rate
ProcessorMetrics- average system load
JvmMemoryMetrics- memory usage, split by area
JvmThreadMetrics- 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:
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