# SmallRye Metrics

The following guide demonstrates how a Quarkus application can use SmallRye Metrics, an implementation of the MicroProfile Metrics specification.

SmallRye Metrics allows applications to gather metrics and statistics that provide insights into what is happening inside an application. The metrics can be read remotely using the JSON or OpenMetrics format to be processed by additional tools such as Prometheus and stored for analysis and visualization.

Apart from application-specific metrics described in this guide, you may also use built-in metrics exposed by various Quarkus extensions. These are described in the guide for each particular extension that supports built-in metrics.

| Micrometer is the recommended approach to metrics for Quarkus. Use the SmallRye Metrics extension when it is required to retain MicroProfile specification compatibility. When Quarkus will upgrade to Eclipse MicroProfile 6, the SmallRye Metrics support will be discontinued.

| This technology is considered deprecated. Being deprecated means that this extension is likely to be replaced or removed in a future version of Quarkus. For a full list of possible statuses, check our FAQ entry.

## Prerequisites

To complete this guide, you need:

- Roughly 15 minutes

- An IDE

- JDK 17+ installed with `JAVA_HOME` configured appropriately

- Apache Maven 3.9.9

- Optionally the Quarkus CLI if you want to use it

- Optionally Mandrel or GraalVM installed and configured appropriately if you want to build a native executable (or Docker if you use a native container build)

## Architecture

In this example, we build a very simple microservice that offers one REST endpoint. This endpoint serves for determining whether a number is prime. The implementation class is annotated with certain metric annotations so that while responding to users' requests, certain metrics are gathered. The meaning of each metric is explained later.

## Solution

We recommend that you follow the instructions in the next sections and create the application step by step. However, you can skip to the completed example.

1. Clone the Git repository:

       git clone https://github.com/quarkusio/quarkus-quickstarts.git

   - Alternatively, download a Quickstarts archive. The solution is located in the `microprofile-metrics-quickstart` directory and follow with the Running and using the application section.

## Creating a Maven project

To create a new project:

CLI

    quarkus create app org.acme:microprofile-metrics-quickstart \
        --extension='rest,smallrye-metrics' \
        --no-code
    cd microprofile-metrics-quickstart

To create a Gradle project, add the `--gradle` or `--gradle-kotlin-dsl` option.

For more information about how to install and use the Quarkus CLI, see the Quarkus CLI guide.

Maven

    mvn io.quarkus.platform:quarkus-maven-plugin:3.20.2.1:create \
        -DprojectGroupId=org.acme \
        -DprojectArtifactId=microprofile-metrics-quickstart \
        -Dextensions='rest,smallrye-metrics' \
        -DnoCode
    cd microprofile-metrics-quickstart

To create a Gradle project, add the `-DbuildTool=gradle` or `-DbuildTool=gradle-kotlin-dsl` option.

For Windows users:

- If using cmd, (don’t use backward slash `\` and put everything on the same line)

- If using Powershell, wrap `-D` parameters in double quotes e.g. `"-DprojectArtifactId=microprofile-metrics-quickstart"`

This command generates a Quarkus project that uses the `smallrye-metrics` extension.

If you already have your Quarkus project configured, you can add the `smallrye-metrics` extension to your project by running the following command in your project base directory:

CLI

    quarkus extension add smallrye-metrics

Maven

    ./mvnw quarkus:add-extension -Dextensions='smallrye-metrics'

Gradle

    ./gradlew addExtension --extensions='smallrye-metrics'

This adds the following to your build file:

pom.xml

    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-smallrye-metrics</artifactId>
    </dependency>

build.gradle

    implementation("io.quarkus:quarkus-smallrye-metrics")

## Writing an application

The following procedures create a Quarkus application that consists of a single class that implements an algorithm for checking whether a number is prime. This algorithm is exposed over a REST interface. Additionally, specific annotations are required to ensure that the desired metrics are calculated over time and can be exported for manual analysis or processing by additional tooling.

The application will gather the following metrics:

- `performedChecks`: A counter that increases by one each time the user asks about a number.

- `highestPrimeNumberSoFar`: A gauge that stores the highest number asked about by the user if the number was determined to be prime.

- `checksTimer`: A compound metric that benchmarks how much time the primality tests take. Additional details are provided later.

The full source code looks as follows:

    package org.acme.microprofile.metrics;

    import org.eclipse.microprofile.metrics.MetricUnits;
    import org.eclipse.microprofile.metrics.annotation.Counted;
    import org.eclipse.microprofile.metrics.annotation.Gauge;
    import org.eclipse.microprofile.metrics.annotation.Timed;

    import jakarta.ws.rs.GET;
    import jakarta.ws.rs.Path;
    import jakarta.ws.rs.Produces;
    import jakarta.ws.rs.core.MediaType;

    @Path("/")
    public class PrimeNumberChecker {

        private long highestPrimeNumberSoFar = 2;

        @GET
        @Path("/{number}")
        @Produces(MediaType.TEXT_PLAIN)
        @Counted(name = "performedChecks", description = "How many primality checks have been performed.")
        @Timed(name = "checksTimer", description = "A measure of how long it takes to perform the primality test.", unit = MetricUnits.MILLISECONDS)
        public String checkIfPrime(long number) {
            if (number < 1) {
                return "Only natural numbers can be prime numbers.";
            }
            if (number == 1) {
                return "1 is not prime.";
            }
            if (number == 2) {
                return "2 is prime.";
            }
            if (number % 2 == 0) {
                return number + " is not prime, it is divisible by 2.";
            }
            for (int i = 3; i < Math.floor(Math.sqrt(number)) + 1; i = i + 2) {
                if (number % i == 0) {
                    return number + " is not prime, is divisible by " + i + ".";
                }
            }
            if (number > highestPrimeNumberSoFar) {
                highestPrimeNumberSoFar = number;
            }
            return number + " is prime.";
        }

        @Gauge(name = "highestPrimeNumberSoFar", unit = MetricUnits.NONE, description = "Highest prime number so far.")
        public Long highestPrimeNumberSoFar() {
            return highestPrimeNumberSoFar;
        }

    }

## Running and using the application

To execute the application created in Writing an application, do the following:

1. Run the microservice in dev mode:

   CLI

       quarkus dev

   Maven

       ./mvnw quarkus:dev

   Gradle

       ./gradlew --console=plain quarkusDev

2. Generate values for the metrics.

   1. Query the endpoint to determine whether some numbers are prime numbers:

          curl localhost:8080/350

      The application will respond that 350 is not a prime number because it can be divided by 2.

      - For large prime numbers, the test takes more time.

            curl localhost:8080/629521085409773

        The application will respond that 629521085409773 is a prime number.

   2. Perform additional calls with numbers of your choice.

3. Review the generated metrics:

       curl -H"Accept: application/json" localhost:8080/q/metrics/application

   You will receive a response such as:

       {
         "org.acme.microprofile.metrics.PrimeNumberChecker.checksTimer" : {                                            (1)
           "p50": 217.231273,                                                                                                                        (2)
           "p75": 217.231273,
           "p95": 217.231273,
           "p98": 217.231273,
           "p99": 217.231273,
           "p999": 217.231273,
           "min": 0.58961,                                                                                                                            (3)
           "mean": 112.15909190834819,                                                                                                        (4)
           "max": 217.231273,                                                                                                                    (5)
           "stddev": 108.2721053982776,                                                                                                    (6)
           "count": 2,                                                                                                                                    (7)
           "meanRate": 0.04943519091742238,                                                                                            (8)
           "oneMinRate": 0.2232140583080189,
           "fiveMinRate": 0.3559527083952095,
           "fifteenMinRate": 0.38474303050928976
         },
         "org.acme.microprofile.metrics.PrimeNumberChecker.performedChecks" : 2,                                    (9)
         "org.acme.microprofile.metrics.PrimeNumberChecker.highestPrimeNumberSoFar" : 629521085409773                (10)
       }

1 | `checksTimer`: A compound metric that benchmarks how much time the primality tests take. All durations are measured in milliseconds. It consists of these values below.
2 | `p50, p75, p95, p99, p999`: Percentiles of the durations. For example, the value in `p95` means that 95 % of the measurements were faster than this duration.
3 | `min`: The shortest duration it took to perform a primality test was probably performed for a small number.
4 | `mean`: The mean value of the measured durations.
5 | `max`: The longest duration, probably it was with a large prime number.
6 | `stddev`: The standard deviation.
7 | `count`: The number of observations, the value of which is the same as `performedChecks`.
8 | `meanRate, oneMinRate, fiveMinRate, fifteenMinRate`: Mean throughput and one-, five-, and fifteen-minute exponentially-weighted moving average throughput.
9 | `performedChecks`: A counter which is increased by one each time the user asks about a number.
10 | `highestPrimeNumberSoFar`: A gauge that stores the highest number that was asked about by the user and which was determined to be prime.

| If you prefer an OpenMetrics export rather than the JSON format, remove the `-H"Accept: application/json"` argument from your command line.

| Management interface By default, the metrics are exposed on the main HTTP server. You can expose them on a separate network interface and port by enabling the management interface with the `quarkus.management.enabled=true` property. Refer to the management interface reference for more information.

Configuration Reference

Configuration property fixed at build time - All other configuration properties are overridable at runtime

Configuration property | Type | Default
--- | --- | ---
`quarkus.smallrye-metrics.path` The path to the metrics handler. By default, this value will be resolved as a path relative to `${quarkus.http.non-application-root-path}`. If the management interface is enabled, the value will be resolved as a path relative to `${quarkus.management.root-path}`. Environment variable: `QUARKUS_SMALLRYE_METRICS_PATH` | string | `metrics`
`quarkus.smallrye-metrics.extensions.enabled` Whether metrics published by Quarkus extensions should be enabled. Environment variable: `QUARKUS_SMALLRYE_METRICS_EXTENSIONS_ENABLED` | boolean | `true`
`quarkus.smallrye-metrics.micrometer.compatibility` Apply Micrometer compatibility mode, where instead of regular 'base' and 'vendor' metrics, Quarkus exposes the same 'jvm' metrics that Micrometer does. Application metrics are unaffected by this mode. The use case is to facilitate migration from Micrometer-based metrics, because original dashboards for JVM metrics will continue working without having to rewrite them. Environment variable: `QUARKUS_SMALLRYE_METRICS_MICROMETER_COMPATIBILITY` | boolean | `false`
`quarkus.smallrye-metrics.jaxrs.enabled` Whether detailed JAX-RS metrics should be enabled. See MicroProfile Metrics: Optional REST metrics. Environment variable: `QUARKUS_SMALLRYE_METRICS_JAXRS_ENABLED` | boolean | `false`