1. Overview
Spectator is a library for instrumenting code and collecting data for dimensional time series backend systems. Spectator originated at Netflix for various metrics collection, and the corresponding backend system used with it is mainly Atlas.
In this tutorial, we’ll learn what Spectator provides and how we can use it to collect metrics.
2. Maven Dependencies
Before we dive into the actual implementation, let’s add the Spectator dependency to the pom.xml file:
<dependency>
<groupId>com.netflix.spectator</groupId>
<artifactId>spectator-api</artifactId>
<version>1.7.7</version>
</dependency>
The spectator-api is the core spectator library.
3. Basics of Registry, Meter, and Metrics
Before we start digging more into this library, we should first understand the basics of Registry, Meter, and Metrics*.*
- Registry is where we maintain a set of meters
- Meter is used for collecting a set of measurements about our application, e.g., Counter, Timer, Gauge, etc.
- Metrics are individual measurements that we display on a Meter, e.g., count, duration, max, average, etc.
Let’s explore these further and understand how they are used in the Spectator library.
4. Registry
The Spectator library comes with Registry as an interface, with some built-in implementations, e.g., DefaultRegistry and NoopRegistry. We can also create custom Registry implementations as per our requirements.
A Registry implementation can be used as below:
Registry registry = new DefaultRegistry();
5. Meter
Meter is of mainly two types, i.e., Active and Passive.
5.1. Active Meters
These meters are used to measure some event’s occurrence. We have three types of such meters:
- Counter
- Timers
- DistributionSummary
5.2. Passive Meters
These meters are used to get the value of the metric when needed. For example, the number of running threads could be a metric we want to measure. We have a single type of such meter, Gauge.
Next, let’s explore these different types of meters in detail.
6. Counter
These meters measure the rate at which an event occurs. For example, suppose we want to measure the rate at which elements are inserted or removed from a list.
Let’s first register a counter to the Registry object on initialization:
insertCounter = registry.counter("list.insert.count");
removeCounter = registry.counter("list.remove.count");
Here, we can allow users to use any Registry implementation using dependency injection.
Now, we can increment or decrement the Counter meter for addition to list or deletion from a list, respectively:
requestList.add(element);
insertCounter.increment();
requestList.remove(0);
removeCounter.increment();
In this way, we can generate two meters, and later, we can push the metrics to Atlas for visualization.
7. Timers
These meters measure the time spent on some event. Spectatorsupports two types of timers:
7.1. Timer
These timers are mainly used to measure short-duration events. Therefore, they usually measure the time spent after the completion of the event.
First, we need to register this meter in the Registry:
requestLatency = registry.timer("app.request.latency");
Next, we can invoke the record() method of Timer to measure the time spent in handling the request:
requestLatency.record(() -> handleRequest(input));
7.2. LongTaskTimer
These timers are mainly used to measure the duration of long-running tasks. Therefore, we can query these timers even when the event is in process. This is also a type of Gauge. We can see metrics like duration and activeTasks when the event is in progress.
Again, as a first step, we need to register this meter:
refreshDuration = LongTaskTimer.get(registry, registry.createId("metadata.refreshDuration"));
Next, we can use LongTaskTimer to start and stop measurements around the long-running task:
long taskId = refreshDuration.start();
try {
Thread.sleep(input);
return "Done";
} catch (InterruptedException e) {
e.printStackTrace();
throw e;
} finally {
refreshDuration.stop(taskId);
}
8. Gauges
As we discussed earlier, gauges are passive meters. Therefore, these give a value that is sampled at any point in time for a running task. So, for example, we would use it if we wanted to know the number of running threads in a JVM or the heap memory usage at any point in time.
We have two types of gauges:
- Polled Gauges
- Active Gauges
8.1. Polled Gauges
This type of gauges polls a running task’s value in the background. It creates a hook on the task it monitors. Hence, there is no need to update the value in this gauge.
Now, let’s see how to use this gauge to monitor a List‘s size:
PolledMeter.using(registry)
.withName("list.size")
.monitorValue(listSize);
Here, PolledMeter is the class that allows background polling on listSize using the monitorValue() method. Further, listSize is the variable that tracks the size of our sample list.
8.2. Active Gauges
This type of gauge requires regular manual updates on the value with respect to updates in monitoring tasks. Here is an example of using active gauges*:*
gauge = registry.gauge("list.size");
We first register this gauge in the Registry. Then, we manually update it on the addition or removal of elements from the list:
list.add(element);
gauge.set(listSize);
list.remove(0);
gauge.set(listSize);
9. DistributionSummary
Now, we will look into another meter known as DistributionSummary. It tracks the distribution of events. This meter can measure the size of the request payload. For example, we’ll use DistributionSummary to measure a request’s size.
First, as always, we register this meter in Registry:
distributionSummary = registry.distributionSummary("app.request.size");
Now, we can use this meter similar to a Timer to record the request’s size:
distributionSummary.record((long) input.length());
handleRequest();
10. Spectator vs. Servo vs. Micrometer
Servo is also a library to measure different code metrics. Spectator is a successor to Servo, built by Netflix. Spectator was initially launched for Java 8, and from a future support perspective, it is a better option.
These Netflix libraries are one of the various options available in the market to measure different metrics. We can always use them individually, or we can go for a facade like Micrometer. Micrometer lets users switch between different metrics measuring libraries with ease. Hence, it also allows a choice of different backend monitoring systems.
11. Conclusion
In this article, we have introduced Spectator, a library from Netflix for metrics measurement. Also, we looked into the usage of its various active and passive meters. We can push and publish the instrumented data to the time-series database Atlas.
As always, the full implementation code of this article can be found over on GitHub.