Easier Multi-Dimensional Metrics in Java

Maxime Petazzoni
signalfx
Published in
3 min readJan 22, 2019

Metrics are one of the most efficient and approachable ways of getting deep visibility into your applications. Instrumenting your first-party applications, as well as their subsystems and business logic, helps you develop and operate those applications with increased velocity and confidence. However, there are two key elements to unlocking this potential. First, you need a monitoring system that can ingest, process, analyze and alert on all of your metrics in real-time and at high resolution; that’s why we built SignalFx around a unique real-time streaming and analytics architecture. Second, you need code instrumentation to be as easy as possible so it becomes second nature when writing code, helping you develop a culture of instrumentation within your engineering team.

Dropwizard Metrics Library for Java

SignalFx has always relied on and integrated with popular open-source metrics instrumentation libraries. We believe that instrumentation should remain open to prevent vendor lock-in, allowing engineers to work with the libraries they love. In Java, we integrate with the widely used and battle-tested Dropwizard Metrics library (formerly known as Codahale) through our signalfx-java library that provides a metrics reporter for SignalFx.

Sending metrics from your Java application to SignalFx has always been very easy. First, add the required dependency on signalfx-codahale to your Maven or Gradle build file.

<dependency>
<groupId>com.signalfx.public</groupId>
<artifactId>signalfx-codahale</artifactId>
<version>0.0.48</version>
</dependency>

Then, setup the SignalFxReporter in your application:

MetricRegistry registry = new MetricRegistry();
SignalFxReporter reporter = new SignalFxReporter
.Builder(registry, "SIGNALFX_AUTH_TOKEN").build();
reporter.start(1, TimeUnit.SECONDS);

Finally, just use the Dropwizard metrics from this registry to instrument your code:

registry.counter("errors").inc();
registry.register("my_queue_size", queue::size);

But in today’s Metrics 2.0 world, being able to report metrics with additional dimensions (also known as tags) is key to unlocking the possibility of asking a lot of interesting questions from your data by slicing, dicing or aggregating across those dimensions. Because Dropwizard has to support reporting metrics to a lot of different backends that may not support dimensions, it provides a “common denominator” interface with no direct support for specifying dimensions when instrumenting your code.

We set out to fix this problem for users of the SignalFx reporter and created SfxMetrics: a helper class that makes it easy, convenient and concise to define and report metrics with (or without) additional dimensions! We’ve been using it internally for quite a while, and recently open-sourced it in version 0.0.48 of our SignalFx Java client library.

Dropwizard Metrics on Easy Mode: SfxMetrics

SfxMetrics is designed to be the main metrics helper that your code will interact with, instead of Dropwizard’s MetricRegistry. It wraps the registry with additional logic to report metrics with the dimensions that you’ve defined:

SfxMetrics metrics = new SfxMetrics(
registry, reporter.getMetricMetadata());

If you use a dependency injection system like Guice, you should by that instance in the singleton scope so you can access it easily via injection throughout your application.

Once you have your SfxMetrics instance, defining, using and reporting metrics, even with additional dimensions, is very easy to write (and read!):

// Increments the count of errors (no additional dimensions)
metrics.counter("errors").inc();
// Increments the count of errors for a specific error type
// as a dimension
metrics.counter("errors", "type", error.getErrorType()).inc();
// Dimensions can also be passed in as a map
metrics.counter("errors", dimensionsMap).inc();

The same method signatures exist for gauges, histograms and timers. Explore the available SfxMetrics methods to see them all!

SfxMetrics also provides a new flavor of gauges: settable gauges. Instead of having to provide a Gauge<> implementation that is called to acquire a value, SettableLongGauge and SettableDoubleGauge provide a simpler interface for updating a memoized value only when you need to change it:

SettableLongGauge lag = metrics.longGauge(
"consumer_lag_ms",
"consumer", consumer.getName());
for (Message message : consumer.stream()) {
lag.setValue(System.currentTimeMillis()
- message.getEnqueueTimeMillis());
process(message);
}
SignalFx chart showing the multiple dimensions of a consumer lag metric

Conclusion

Observability is too important to the software development lifecycle — from development to deployment and operation at scale in production — for instrumentation to get in the way. If you use Dropwizard’s Metrics library in Java, we hope that SfxMetrics will make your lives easier when writing code and adding rich metrics instrumentation to your applications!

Originally published at www.signalfx.com.

--

--

Maxime Petazzoni
signalfx
Writer for

Chasing rainbows, running, driving, and building software for SignalFx in beautiful, sunny California.