- Micrometer Metrics
Helidon SE simplifies how you can use Micrometer for application-specific metrics:
The endpoint
/micrometer: A configurable endpoint that exposes metrics according to which Micrometer meter registry responds to the HTTP request.The
MicrometerSupportclass: A convenience class for enrolling Micrometer meter registries your application creates explicitly or for selecting which built-in Micrometer meter registries to use.Configuration to tailor the Prometheus and other Micrometer meter registries.
In Helidon 2.6.14, Micrometer support is separate from the Helidon SE metrics API and the built-in Helidon metrics.
Prerequisites
Declare the following dependency in your project:
<dependency>
<groupId>io.helidon.integrations.micrometer</groupId>
<artifactId>helidon-integrations-micrometer</artifactId>
</dependency>Micrometer supports different types of meter registries which have different output styles and formats. Helidon provides built-in support for the Prometheus meter registry. To use other meter registry types, you will need to add dependencies for them to your pom.xml and, optionally, add code to your application or add configuration to set them up as you wish.
Using Micrometer in Your Application
You need to make two types of changes to your application to use Helidon SE integration with Micrometer:
- Register an instance of
MicrometerSupportwith the web server. - Create meters using the meter registry which
MicrometerSupportmanages and update those meters.
Register an Instance of MicrometerSupport with the Web Server
import io.helidon.integrations.micrometer.MicrometerSupport;
//...
MicrometerSupport micrometerSupport = MicrometerSupport.create();
Routing.builder()
.register(micrometerSupport)
.register("/myapp", new MyService(micrometerSupport.registry()))
.build();- Create the
MicrometerSupportinstance, using the default built-in Prometheus meter registry. - Register the support instance as a service; by default,
MicrometerSupportexposes the endpoint as/micrometer. - Pass the
MicrometerSupportobject’s meter registry to your service for use in creating and updating meters.
Create and Update Meters in your Application Service
Counterimport io.micrometer.core.instrument.Counter;
public class MyService implements Service {
private final Counter requestCounter;
public MyService(MicrometerMeterRegistry registry) {
requestCounter = registry.counter("allRequests");
// ...
}
@Override
public void update(Routing.Rules rules) {
rules
.any(this::countRequests)
.get("/", this::myGet);
}
private void countRequests(ServerRequest request, ServerResponse response) {
requestCounter.increment();
request.next();
}
}- Use the Micrometer meter registry to create the request counter.
- Add routing for any request to invoke the method which counts requests by updating the counter.
- Update the counter and delegate the rest of the request processing to the next handler in the chain.
The example above enrolls the built-in Prometheus meter registry with the default Prometheus registry configuration. You can change the default setup for built-in registries, and you can enroll other meter registries your application creates itself.
Overriding Defaults for Built-in Meter Registry Types
Unless you specify otherwise, Helidon uses defaults for any built-in Micrometer meter registry. For example, Helidon configures the built-in Prometheus registry using PrometheusConfig.DEFAULT.
You can override these defaults in either of two ways:
Using the
MicrometerSupport.BuilderclassUsing configuration
Using MicrometerSupport.Builder
Use the MicrometerSupport.Builder class to set up Micrometer support however your application needs.
The builder lets you:
Provide your own Micrometer meter registry configuration that
MicrometerSupportuses to create a built-in meter registry, orInstantiate a Micrometer meter registry yourself, configured however you want, and add it to the
MicrometerSupportobject’s collection of meter registries
MicrometerSupport.BuilderPrometheusConfig myPrometheusConfig = ...;
MicrometerSupport support = MicrometerSupport.builder()
.enrollBuiltInRegistry(
MicrometerSupport.BuiltInRegistryType.PROMETHEUS,
myPrometheusConfig)
.build();- Create the meter registry configuration however you need.
- Enroll the
PROMETHEUSbuilt-in registry type with your custom configuration.
Using Configuration
To use configuration to control the selection and behavior of Helidon’s built-in Micrometer meter registries, include in your configuration (such as application.yaml) a micrometer.builtin-registries section.
micrometer:
builtin-registries:
- type: prometheusmicrometer:
builtin-registries:
- type: prometheus
prefix: myPrefixNote that the first config example is equivalent to the default Helidon Micrometer behavior; Helidon by default supports the Prometheus meter registry.
The configuration keys that are valid for the builtin-registries child entries depend on the type of Micrometer meter registry. For example, the Prometheus meter registry supports the prefix configuration setting but other meter registries might not and might support other settings. Refer to the documentation for the meter registry you want to configure to find out what items apply to that registry type.
Helidon does not validate the configuration keys you specify for meter registries.
Enrolling other Micrometer meter registries
To create additional types of registries and enroll them with MicrometerSupport, you need to:
- Write a
HandlerEach meter registry has its own way of producing output. Write your handler so that it has a reference to the meter registry it should use and so that its
acceptmethod sets the payload in the HTTP response using the registry’s mechanism for creating output. - Write a
Functionwhich accepts aServerRequestand returns anOptional<Handler>In general, your function looks at the request—the
Content-Type, query parameters, etc.--to decide whether your handler should respond to the request. If so, your function should instantiate yourHandlerand return anOptional.of(theHandlerInstance); otherwise, your function should returnOptional.empty().When
MicrometerSupportreceives a request, it invokes the functions of all the enrolled registries, stopping as soon as one function provides a handler.MicrometerSupportthen delegates to that handler to create and send the response. - Pass the
HandlerandFunctionto theMicrometerSupport.enrollRegistrymethod to enroll themCreating and enrolling your own Micrometer meter registryMeterRegistry myRegistry = new PrometheusMeterRegistry(myPrometheusConfig); MicrometerSupport support = MicrometerSupport.builder() .enrollRegistry(myRegistry, request -> request .headers() .bestAccepted(MediaType.TEXT_PLAIN).isPresent() ? Optional.of((req, resp) -> resp.send(myRegistry.scrape())) : Optional.empty()) .build();content_copy- Create the meter registry. This example uses a Prometheus registry but it can be any extension of
MeterRegistry. - Provide the function that checks if the
ServerRequestaccepts content that your meter registry can produce (e.g., eithertext/plainor unspecified is normally an indication for Prometheus-style output) and returns the appropriateOptional<.Handler> - A very simple in-line
Handlerthat sets the response entity from the Prometheus registry’sscrape()method.
- Create the meter registry. This example uses a Prometheus registry but it can be any extension of
Accessing the Helidon Micrometer Endpoint
By default, Helidon Micrometer integration exposes the /micrometer endpoint. You can override this using the Builder or the micrometer.web-context configuration key.
When MicrometerSupport receives a request at the endpoint, it looks for the first enrolled meter registry for which the corresponding Function<ServerRequest, Optional<Handler>> returns a non-empty Handler. Helidon invokes that Handler which must retrieve the metrics output from its meter registry and set and send the response. Note that the Handler which your function returns typically has a reference to the meter registry it will use in preparing the response.