Contents

Overview

Helidon SE metrics is inspired by—​but does not fully implement—​the MicroProfile Metrics specification. In particular, the Helidon metrics subsystem furnishes

  • a unified way for Helidon servers to export monitoring data—​telemetry—​to management agents, and

  • a unified Java API which all application programmers can use to register and update metrics to expose telemetry data from their services.

Learn more about the MicroProfile Metrics specification.

Maven Coordinates

To enable metrics add the following dependency to your project’s pom.xml (see Managing Dependencies).

Packaging full-featured metrics
<dependency>
    <groupId>io.helidon.metrics</groupId>
    <artifactId>helidon-metrics</artifactId>
</dependency>
Copied

Adding this dependency packages the full-featured metrics implementation with your service.

Other Packaging Options

Helidon gives you flexibility in how you make metrics available to your service. This document explains your options.

Usage

Instrumenting Your Service

You add metrics to your service by writing code which explicitly invokes the metrics API to register metrics, retrieve previously-registered metrics, and update metric values.

Later sections of this document describe how to do this.

Categorizing the Types of Metrics

Helidon distinguishes among three general types, or scopes, of metrics, as described in the MP metrics specification.

Types (scopes) of metrics
Type/scopeTypical Usage
baseMandated by the MP metrics specification, such as OS or Java runtime measurements (available heap, disk space, etc.).
vendorImplemented by vendors, including the REST.request metrics and other key performance indicator measurements (described in later sections).
applicationDeclared via annotations or programmatically registered by your service code.

When you add metrics annotations to your service code, Helidon registers the resulting metrics as type application.

Metric Registries

A metric registry collects registered metrics of a given type. Helidon supports three registries, one for each of the three metrics types.

When you add code to your service to create a metric programmatically, the code first locates the appropriate registry and then registers the metric with that registry.

Retrieving Metrics Reports From Your Service

When you add the metrics dependency to your project, Helidon automatically provides a built-in REST endpoint /metrics which responds with a report of the registered metrics and their values.

Clients can request a particular output format.

Formats for /metrics output
FormatRequested by
OpenMetrics (Prometheus)default (text/plain)
JSONHeader Accept: application/json

Clients can also limit the report by appending the metric type to the path:

  • /metrics/base

  • /metrics/vendor

  • /metrics/application

Further, clients can narrow down to a specific metric name by adding the name as a subpath such as /metrics/application/myCount.

Example Reporting: Prometheus format
curl -s -H 'Accept: text/plain' -X GET http://localhost:8080/metrics/
Copied
# TYPE base:classloader_total_loaded_class_count counter
# HELP base:classloader_total_loaded_class_count Displays the total number of classes that have been loaded since the Java virtual machine has started execution.
base:classloader_total_loaded_class_count 3157
Example Reporting: JSON format
curl -s -H 'Accept: application/json' -X GET http://localhost:8080/metrics/
Copied
{
   "base" : {
      "memory.maxHeap" : 3817865216,
      "memory.committedHeap" : 335544320,
    }
}

In addition to your application metrics, the reports contain other metrics of interest such as system and VM information.

Enabling the MetricsSupport REST Service

To enable the metrics REST endpoint:

  1. Create an instance of MetricsSupport, either directly as shown below or using its Builder.
  2. Include the MetricsSupport instance in your application’s routing.
import io.helidon.metrics.serviceapi.MetricsSupport;

Routing.builder()
        .register(MetricsSupport.create())
        .register("/myapp", new MyService())
        .build();
Copied

API

To work with Helidon Metrics in your code, follow these steps:

  1. Use a static method on the RegistryFactory to get a reference to the MetricRegistry instance you want to use.
  2. Use the MetricRegistry instance to register new metrics and look up previously-registered metrics.
  3. Use the metric reference returned from the MetricRegistry to update the metric or get its value.

You can also use the MetricRegistry to remove an existing metric.

Helidon Metrics API

The Helidon Metrics API is aligned with the MicroProfile Metrics API. That API defines the classes and interfaces for metric types, metric registries, and other related items. Helidon Metrics reuses that API for classes and interfaces (but not for annotations which Helidon SE does not support).

The following table summarizes the metric types.

Metric Types
Metric TypeUsage
CounterMonotonically increasing count of events.
ConcurrentGaugeIncreasing and decreasing measurement of currently-executing blocks of code.
GaugeAccess to a value managed by other code in the service.
HistogramCalculates the distribution of a value.
MeterCount of invocations and how frequently invocations have occurred.
SimpleTimerCount of invocations and the total duration consumed by those invocations.
TimerFrequency of invocations and the distribution of how long the invocations take.

Each metric type has its own set of methods for updating and retrieving the metric’s value.

The MetricRegistry API

To register or look up metrics programmatically, your service code uses one of the three MetricRegistry instances (base, vendor, and application) which Helidon furnishes automatically.

To get a MetricRegistry reference, first get a Helidon RegistryFactory. Then invoke getRegistry on the RegistryFactory instance.

The MetricRegistry allows your code to register new metrics, look up previously-registered metrics, and remove metrics.

Configuration

To control how the Helidon metrics subsystem behaves, add a metrics section to your configuration file, such as application.yaml.

Type: io.helidon.metrics.serviceapi.MetricsSupport

Configuration Options

Optional configuration options
keytypedefault valuedescription
appName

string

 

Sets the value for the _app tag to be applied to all metrics.

base 

Set the base metrics settings.

cors 

Sets the cross-origin config builder for use in establishing CORS support for the service endpoints.

enabled

boolean

 

Sets whether metrics should be enabled.

key-performance-indicators 

Set the KPI metrics settings.

registries 

Sets the registry settings for the specified registry type.

routing

string

 

Sets the routing name to use for setting up the service’s endpoint.

tags

Map<string, string>

 

Sets the global tags to be applied to all metrics.

web-context

string

 

Sets the web context to use for the service’s endpoint.

Examples

Helidon SE includes several prewritten example applications illustrating aspects of metrics:

The rest of this section shows how to add a metric to your code and how to configure the Helidon metrics subsystem.

Example Application Code

The following example illustrates registering and updating a new Counter in application code.

Define and use a Counter
import io.helidon.metrics.api.RegistryFactory;
import org.eclipse.microprofile.metrics.Counter;
import org.eclipse.microprofile.metrics.MetricRegistry;
//...

public class MyService implements Service {

    private final MetricRegistry registry = RegistryFactory.getInstance()
        .getRegistry(MetricRegistry.Type.APPLICATION); 
    private final Counter accessCtr = registry.counter("accessctr"); 

    @Override
    public void update(Routing.Rules rules) {
        rules
             .any(this::countAccess)
             .get("/", this::myGet);
    }

    private void countAccess(ServerRequest request, ServerResponse response) {
            accessCtr.inc(); 
            request.next();
    }
}
Copied
  • Get the application metric registry.
  • Create a counter in that registry.
  • Increment the counter for every request.

Helidon-provided endpoints for /metrics do their work synchronously, using the same thread on which the request arrived via Netty. To prevent performance degradation, avoid including long-running code that can be invoked by these handlers while Helidon is responding to the metric. For example, if you implement your own application-specific metric types, you will write logic to format the JSON and OpenMetrics output for those metric types. Helidon invokes this formatting logic whenever a client accesses the /metrics endpoints, so make that formatting code as efficient as possible.

Example Configuration

Metrics configuration is quite extensive and powerful and, therefore, a bit complicated. The rest of this section illustrates some of the most common scenarios.

Disable Metrics Subsystem

Disabling metrics entirely
metrics:
  enabled: false
Copied

Helidon does not update metrics, and the /metrics endpoints respond with 404 plus a message that the metrics subsystem is disabled.

Disable Selected Metrics

You can be even more selective. Within a registry type you can configure up to two regular expression patterns:

  • one matching metric names to exclude, and

  • one matching metric names to include.

Helidon updates and reports a metric only if two conditions hold:

  • the metric name does not match the exclude regex pattern (if you define one), and

  • either

    • there is no include regex pattern, or

    • the metric name matches the include pattern.

Note

Make sure any include regex pattern you specify matches all the metric names you want to capture.

Suppose your application creates and updates a group of metrics with names such as myapp.xxx.queries, myapp.xxx.creates, myapp.xxx.updates, and myapp.xxx.deletes where xxx can be either supplier or customer.

The following example gathers all metrics except those from your application regarding suppliers although supplier updates are included:

Disabling and enabling metrics by name
metrics:
  registries:
    - type: application
      filter:
        exclude: "myapp\.supplier\..*"
        include: "myapp\.supplier\.updates"
Copied

This setting excludes metrics with names starting with myapp.supplier except for the metric myapp.supplier.updates. The exclude and include values are regular expressions.

Collecting Basic and Extended Key Performance Indicator (KPI) Metrics

Any time you include the Helidon metrics module in your application, Helidon tracks two basic performance indicator metrics:

  • a Counter of all requests received (requests.count), and

  • a Meter of all requests received (requests.meter).

Helidon SE also includes additional, extended KPI metrics which are disabled by default:

  • current number of requests in-flight - a ConcurrentGauge (requests.inFlight) of requests currently being processed

  • long-running requests - a Meter (requests.longRunning) measuring the rate at which Helidon processes requests which take at least a given amount of time to complete; configurable, defaults to 10000 milliseconds (10 seconds)

  • load - a Meter (requests.load) measuring the rate at which requests are worked on (as opposed to received)

  • deferred - a Meter (requests.deferred) measuring the rate at which a request’s processing is delayed after Helidon receives the request

You can enable and control these metrics using configuration:

Controlling extended KPI metrics
metrics:
  key-performance-indicators:
    extended: true
    long-running:
      threshold-ms: 2000
Copied

Additional Information

Support for the Prometheus Metrics API

Helidon provides optional support for the Prometheus metrics API.

To use it, your service registers Prometheus support with your routing set-up. You can customize its configuration. For information about using Prometheus, see the Prometheus documentation: https://prometheus.io/docs/introduction/overview/.

Helidon’s fully-functional, built-in metrics implementation supports Prometheus (OpenMetrics) output. Use the optional support described in this section only if you want to use the Prometheus API from your application code.

Maven Coordinates

Dependency for Helidon Prometheus API support
    <dependency>
        <groupId>io.helidon.metrics</groupId>
        <artifactId>helidon-metrics-prometheus</artifactId>
    </dependency>
Copied

Usage

Your application code uses the Prometheus API to manage metrics. To expose those metrics to clients via a REST endpoint, your code uses the PrometheusSupport interface which Helidon provides.

API

Your code creates a PrometheusSupport object either using a static factory method (shown in the following example) or by using its Builder.

import io.helidon.metrics.prometheus.PrometheusSupport;

Routing.builder()
                .register(PrometheusSupport.create())
                .register("/myapp", new MyService())
                .build();
Copied

This example uses the default Prometheus CollectorRegistry. By default, the PrometheusSupport and exposes its REST endpoint at the path /metrics. Use the builder obtained by PrometheusSupport.builder() to configure a different CollectorRegistry or a different path.