Using Micrometer in Helidon Applications

Tim Quinn
Helidon
Published in
4 min readMay 24, 2021

Oracle’s Project Helidon simplifies the job of building Java microservices by, among other things, including support for metrics inspired by the MicroProfile Metrics specification. Helidon metrics include some built-in measurements, but also allow app developers to add their own using the same MicroProfile-inspired API.

Helidon release 2.3.0 adds built-in support for Micrometer metrics. You can use the Micrometer API and annotations to create and update your own application meters and make them available via an endpoint Helidon creates. (This does not replace the built-in Helidon metrics features.)

This article shows how to add Micrometer support and your own Micrometer meters to a Helidon SE or MP app. We’ll assume you have used the Helidon CLI to create an SE or MP quick-start Helidon application.

Adding Micrometer support to your SE app

Modify pom.xml

Add the Helidon Micrometer integration dependency:

<dependency>
<groupId>io.helidon.integrations.micrometer/groupId>
<artifactId>helidon-integrations-micrometer</artifactId>
</dependency>

Modify Main.java

The main class sets up the Helidon routing for your endpoints and any built-in Helidon features you choose. Change the main class to create and register MicrometerSupport as well.

import io.helidon.integrations.micrometer.MicrometerSupport;
...
MicrometerSupport micrometerSupport = MicrometerSupport.create();
GreetService greetService =
new GreetService(config, micrometerSupport.registry());
...
Routing.builder()
.register(health)
.register(metrics)
.register(micrometerSupport)
.register("/greet", greetService)
.build();

The new .register invocation exposes Helidon’s built-in Micrometer support /micrometer endpoint to produce Prometheus-formatted output.

Modify GreetService.java

Revise the GreetService class so its constructor accepts the Micrometer registry as a parameter and GET accesses create and update a Micrometer meter.

Add imports:

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;

Declare Micrometer MeterRegistry and Micrometer Counterfields:

private final MeterRegistry meterRegistry;
private final Counter getCounter;

Change the constructor to accept and save the MeterRegistry parameter and create the counter:

GreetService(Config config, MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
getCounter = meterRegistry.counter("greeting.get");
greeting.set(config.get("app.greeting").asString()
.orElse("Ciao"));
}

Change theupdate methodto add a request handler for every get HTTP operation. This handler updates the Micrometer Counterbefore passing the request off to the next handler without disturbing the other handlers for the service:

public void update(Routing.Rules rules) {
rules
.get((req, resp) -> {
getCounter.increment();
req.next();
})

.get("/", this::getDefaultMessageHandler)
.get("/{name}", this::getMessageHandler)
.put("/greeting", this::updateGreetingHandler);
}

Try it

Build and run the revised application:

mvn package
java -jar target/quickstart-se.jar

Access the new endpoint:

% curl http://localhost:8080/micrometer
# HELP greeting_get_total
# TYPE greeting_get_total counter
greeting_get_total 0.0

Retrieve at least one greeting:

% curl http://localhost:8080/greet
{"message":"Hello World!"}
% curl http://localhost:8080/greet/reader
{"message":"Hello reader!"}

Check the Micrometer output again, noting the change in value:

curl http://localhost:8080/micrometer
# HELP greeting_get_total
# TYPE greeting_get_total counter
greeting_get_total 2.0

Add Micrometer support to your MP app

You can use the Micrometer @Counted and @Timedannotations in your Helidon MP application.

Modify pom.xml

Add the dependency for Helidon Micrometer with CDI support:

<dependency>
<groupId>io.helidon.integrations.micrometer</groupId>
<artifactId>helidon-integrations-micrometer-cdi</artifactId>
</dependency>

Add Micrometer annotations to GreetResource.java

We use Micrometer annotations to track (by time and invocation count) all GET accesses and to count separately all requests for personalized greetings.

We will use the same @Timedannotation on two GET methods, so first define constants we can reuse:

private static final String GETS_TIMER_NAME = "allGets";
private static final String GETS_TIMER_DESCR =
"Tracks all GET operations";

Add

  • Micrometer @Timed annotation to both GET methods, and
  • Micrometer @Counted annotation to the personalized GET method:
@GET
@Timed(value = GETS_TIMER_NAME, description = GETS_TIMER_DESCR)
@Produces(MediaType.APPLICATION_JSON)
public JsonObject getDefaultMessage() {
...
}
...
@Counted(value = "personalizedGets",
description = "Counts personalized GET operations")
@Timed(value = GETS_TIMER_NAME, description = GETS_TIMER_DESCR)

@Path("/{name}")
@GET
@Produces(MediaType.APPLICATION_JSON)
public JsonObject getMessage(@PathParam("name") String name) {
...
}

Try it

Build and run the revised application:

mvn package
java -jar target/quickstart-mp.jar

Access the Micrometer endpoint:

curl http://localhost:8080/micrometer
# HELP allGets_seconds_max Tracks all GET operations
# TYPE allGets_seconds_max gauge
allGets_seconds_max 0.0
# HELP allGets_seconds Tracks all GET operations
# TYPE allGets_seconds summary
allGets_seconds_count 0.0
allGets_seconds_sum 0.0
# HELP personalizedGets_total Counts personalized GET operations
# TYPE personalizedGets_total counter
personalizedGets_total 0.0

Retrieve at least one greeting:

% curl http://localhost:8080/greet
{"message":"Hello World!"}
% curl http://localhost:8080/greet/reader
{"message":"Hello reader!"}

Check the Micrometer output again, noting the change in values:

curl http://localhost:8080/micrometer
# HELP allGets_seconds_max Tracks all GET operations
# TYPE allGets_seconds_max gauge
allGets_seconds_max 0.003666501
# HELP allGets_seconds Tracks all GET operations
# TYPE allGets_seconds summary
allGets_seconds_count 2.0
allGets_seconds_sum 0.003923641
# HELP personalizedGets_total Counts personalized GET operation
# TYPE personalizedGets_total counter
personalizedGets_total 1.0

Summary

With just a few changes, you can add Micrometer support for your own metrics to your Helidon SE or MP application and make those metrics accessible at the built-in /micrometer endpoint.

Built-in Helidon metrics continue to be available at the/metricsendpoint.

Go to our documentation site to find out more about Micrometer support in Helidon SE and Helidon MP.

--

--

Tim Quinn
Helidon
Writer for

Working for Oracle on Project Helidon. Previously, WebLogic Server multitenancy, GlassFish, database design, and high-throughput systems.