Skip to content

15.3.3 Registering custom metrics

In section 15.2.4, we looked at how you could navigate the /metrics endpoint to consume various metrics published by Actuator, with a focus on metrics pertaining to HTTP requests. The metrics provided by Actuator are very useful, but the /metrics endpoint isn’t limited to only those built-in metrics.

Ultimately, Actuator metrics are implemented by Micrometer https://micrometer.io/, a vendor-neutral metrics facade that makes it possible for applications to publish any metrics they want and to display them in the third-party monitoring system of their choice, including support for Prometheus, Datadog, and New Relic, among others.

The most basic means of publishing metrics with Micrometer is through Micrometer’s MeterRegistry. In a Spring Boot application, all you need to do to publish metrics is inject a MeterRegistry wherever you may need to publish counters, timers, or gauges that capture the metrics for your application.

As an example of publishing custom metrics, suppose you want to keep counters for the numbers of tacos that have been created with different ingredients. That is, you want to track how many tacos have been made with lettuce, ground beef, flour tortillas, or any of the available ingredients. The TacoMetrics bean in the next listing shows how you might use MeterRegistry to gather that information.

Listing 15.6 TacoMetrics registers metrics around taco ingredients

java
package tacos.tacos;
import java.util.List;
import
org.springframework.data.rest.core.event.AbstractRepositoryEventListener;
import org.springframework.stereotype.Component;
import io.micrometer.core.instrument.MeterRegistry;

@Component
public class TacoMetrics extends AbstractRepositoryEventListener<Taco> {
  private MeterRegistry meterRegistry;
  public TacoMetrics(MeterRegistry meterRegistry) {
    this.meterRegistry = meterRegistry;
  }

  @Override
  protected void onAfterCreate(Taco taco) {
    List<Ingredient> ingredients = taco.getIngredients();
    for (Ingredient ingredient : ingredients) {
      meterRegistry.counter("tacocloud",
        "ingredient", ingredient.getId()).increment();
    }
  }
}

As you can see, TacoMetrics is injected through its constructor with a MeterRegistry. It also extends AbstractRepositoryEventListener, a Spring Data class that enables the interception of repository events and overrides the onAfterCreate() method so that it can be notified any time a new Taco object is saved.

Within onAfterCreate(), a counter is declared for each ingredient where the tag name is ingredient and the tag value is equal to the ingredient ID. If a counter with that tag already exists, it will be reused. The counter is incremented, indicating that another taco has been created for the ingredient.

After a few tacos have been created, you can start querying the /metrics endpoint for ingredient counts. A GET request to /metrics/tacocloud yields some unfiltered metric counts, as shown next::

bash
$ curl localhost:8087/actuator/metrics/tacocloud
{
  "name": "tacocloud",
    "measurements": [ { "statistic": "COUNT", "value": 84 }
  ],
  "availableTags": [
    {
      "tag": "ingredient",
      "values": [ "FLTO", "CHED", "LETC", "GRBF",
                  "COTO", "JACK", "TMTO", "SLSA"]
    }
  ]
}

The count value under measurements doesn’t mean much here, because it’s a sum of all the counts for all ingredients. But let’s suppose you want to know how many tacos have been created with flour tortillas (FLTO). All you need to do is specify the ingredient tag with a value of FLTO as follows:

bash
$ curl localhost:8087/actuator/metrics/tacocloud?tag=ingredient:FLTO
{
  "name": "tacocloud",
  "measurements": [
    { "statistic": "COUNT", "value": 39 }
  ],
  "availableTags": []
}

Now it’s clear that 39 tacos have had flour tortillas as one of their ingredients.

Released under the MIT License.