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 Counter
fields:
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 method
to add a request handler for every get
HTTP operation. This handler updates the Micrometer Counter
before 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 @Timed
annotations 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 @Timed
annotation 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 bothGET
methods, and - Micrometer
@Counted
annotation to the personalizedGET
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/metrics
endpoint.
Go to our documentation site to find out more about Micrometer support in Helidon SE and Helidon MP.