diff --git a/applications/parent/pom.xml b/applications/parent/pom.xml
index 95e0dd6c576..4405238918d 100644
--- a/applications/parent/pom.xml
+++ b/applications/parent/pom.xml
@@ -41,8 +41,8 @@
3.6.0
3.1.0
3.1.2
- 4.0.14
- 4.0.14
+ 4.0.15
+ 4.0.15
3.3.0
0.10.2
1.5.0.Final
diff --git a/docs/src/main/asciidoc/includes/attributes.adoc b/docs/src/main/asciidoc/includes/attributes.adoc
index 5b0f4b0970b..1921e8a3392 100644
--- a/docs/src/main/asciidoc/includes/attributes.adoc
+++ b/docs/src/main/asciidoc/includes/attributes.adoc
@@ -277,7 +277,7 @@ endif::[]
:oracle-ucp-javadoc-base-url: https://docs.oracle.com/en/database/oracle/oracle-database/{version-lib-oracle-ucp}/jjuar
:micrometer-url: https://micrometer.io
-:micrometer-api-url: https://docs.micrometer.io/micrometer/reference/concepts.html
+:micrometer-api-url: https://docs.micrometer.io/micrometer/reference/concepts
:micrometer-javadoc-base-url: https://javadoc.io/doc/io.micrometer
:micrometer-javadoc-registry-prometheus-base-url: {micrometer-javadoc-base-url}/micrometer-registry-prometheus/{version-lib-micrometer}/io/micrometer/prometheus
@@ -290,6 +290,10 @@ endif::[]
:openapi-generator-tool-generators-docs-url: {openapi-generator-tool-docs-url}/generators
:openapi-generator-tool-site-url: https://openapi-generator.tech
+// Exposition formats for metrics
+:prometheus-exposition-format-doc-url: https://github.com/prometheus/docs/blob/main/content/docs/instrumenting/exposition_formats.md
+:openmetrics-format-doc-url: https://github.com/prometheus/OpenMetrics/blob/main/specification/OpenMetrics.md
+
// GraalVM
:graalvm-jdk-version: 21
:graalvm-doc-url: https://www.graalvm.org/jdk{graalvm-jdk-version}/
diff --git a/docs/src/main/asciidoc/includes/metrics/metrics-shared.adoc b/docs/src/main/asciidoc/includes/metrics/metrics-shared.adoc
index f341dbe2c37..2c6c560a7f0 100644
--- a/docs/src/main/asciidoc/includes/metrics/metrics-shared.adoc
+++ b/docs/src/main/asciidoc/includes/metrics/metrics-shared.adoc
@@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////////////
- Copyright (c) 2021, 2024 Oracle and/or its affiliates.
+ Copyright (c) 2021, 2025 Oracle and/or its affiliates.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -23,6 +23,8 @@ ifndef::flavor-lc[:flavor-lc: se]
:description: Helidon metrics
:keywords: helidon, metrics
:writing-code-content: code which explicitly invokes the metrics API to register {metrics}, retrieve previously-registered {metrics}, and update {metric} values.
+ifdef::se-flavor[:prom-output-scope-prefix: ]
+ifdef::mp-flavor[:prom-output-scope-prefix: mp_]
* a unified way for
ifdef::mp-flavor[MicroProfile]
@@ -73,8 +75,58 @@ Later sections of this document describe how to do
ifdef::mp-flavor[each of these.]
ifdef::se-flavor[this.]
+// tag::meter-types-summary[]
+=== {metric_uc} Types
+
+Helidon supports meters
+ifdef::se-flavor[inspired by link:{micrometer-url}[Micrometer]]
+ifdef::mp-flavor[described by the link:{microprofile-metrics-spec-url}[MicroProfile Metrics] spec]
+and summarized in the following table:
+
+.Types of {metrics_uc}
+[cols="3,8,2"]
+|====
+| {metric_uc} Type | Description |
+ifdef::se-flavor[Micrometer reference]
+ifdef::mp-flavor[Related MicroProfile annotation]
+
+|
+ifdef::se-flavor[link:{metrics-javadoc-base-url}/io/helidon/metrics/api/Counter.html[`Counter`]]
+ifdef::mp-flavor[link:{microprofile-metrics-javadoc-metric-url}/Counter.html[`Counter`]]
+| Monotonically-increasing `long` value. |
+ifdef::se-flavor[link:{micrometer-api-url}/counters.html[Counters]]
+ifdef::mp-flavor[link:{microprofile-metrics-javadoc-annotation-url}/Counted.html[`@Counted`]]
+
+|
+ifdef::se-flavor[link:{metrics-javadoc-base-url}/io/helidon/metrics/api/DistributionSummary.html[`DistributionSummary`]]
+ifdef::mp-flavor[link:{microprofile-metrics-javadoc-metric-url}/Histogram.html[`Histogram`]]
+
+| Summary of samples each with a `long` value. Reports aggregate information over all samples (count, total, mean, max) as well as the distribution of sample values using percentiles and bucket counts. |
+ifdef::se-flavor[link:{micrometer-api-url}/distribution-summaries.html[Distribution summaries]]
+ifdef::mp-flavor[(none)]
+
+|
+ifdef::se-flavor[link:{metrics-javadoc-base-url}/io/helidon/metrics/api/Timer.html[`Timer`]]
+ifdef::mp-flavor[link:{microprofile-metrics-javadoc-metric-url}/Timer.html[`Timer`]]
+| Accumulation of short-duration (typically under a minute) intervals. Typically updated using a Java link:{jdk-javadoc-url}/java.base/java/time/Duration.html[`Duration`] or by recording the time taken by a method invocation or lambda. Reports the count, total time, max, and mean; provides a
+ifdef::se-flavor[distribution summary]
+ifdef::mp-flavor[histogram]
+of the samples. |
+ifdef::se-flavor[link:{micrometer-api-url}/timers.html[Timers]]
+ifdef::mp-flavor[link:{microprofile-metrics-javadoc-annotation-url}/Timed.html[`@Timed`]]
+
+|
+ifdef::se-flavor[link:{metrics-javadoc-base-url}/io/helidon/metrics/api/Gauge.html[`Gauge extends Number>`]]
+ifdef::mp-flavor[link:{microprofile-metrics-javadoc-metric-url}/Gauge.html[`Gauge extends Number>`]]
+| View of a value that is assignment-compatible with a subtype of Java link:{jdk-javadoc-url}/java.base/java.lang.Number.html[`Number`]. The underlying value is updated by code elsewhere in the system, not by invoking methods on the gauge itself. |
+ifdef::se-flavor[link:{micrometer-api-url}/gauges.html[Gauges]]
+ifdef::mp-flavor[link:{microprofile-metrics-javadoc-annotation-url}/Gauge.html[`@Gauge`]]
+|====
+
+// end::meter-types-summary[]
+
=== Categorizing Types of {Metrics_uc}
-Helidon distinguishes among _scopes_, or types, of
+Helidon distinguishes among _scopes_, or categories, of
ifdef::se-flavor[{metrics}.]
ifdef::mp-flavor[{metrics} as described in the link:{microprofile-metrics-spec-url}[MP metrics specification].]
@@ -82,7 +134,7 @@ Helidon includes {metrics} in the built-in scopes described below.
Applications often register their own {metrics} in the `application` scope but can create their own scopes and register {metrics} within them.
.Built-in {metric} scopes
-[%autowidth]
+[cols="2,8"]
|====
| Built-in Scope | Typical Usage
@@ -134,12 +186,13 @@ Further, clients can narrow down to a specific metric name by adding the name as
curl -s -H 'Accept: text/plain' -X GET http://localhost:8080{metrics-endpoint}
----
-[source,text]
+[source,text,subs="attributes+"]
----
-# 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
+# HELP classloader_loadedClasses_count Displays the number of classes that are currently loaded in the Java virtual machine.
+# TYPE classloader_loadedClasses_count gauge
+classloader_loadedClasses_count{{prom-output-scope-prefix}scope="base",} 5297.0
----
+See the summary of the <> for more information.
[source,bash,subs="attributes+"]
.Example Reporting: JSON format
@@ -161,6 +214,59 @@ curl -s -H 'Accept: application/json' -X GET http://localhost:8080{metrics-endpo
In addition to your application {metrics}, the reports contain other
{metrics} of interest such as system and VM information.
+==== OpenMetrics and Prometheus Format
+The link:{openmetrics-format-doc-url}[OpenMetrics format] and the link:{prometheus-exposition-format-doc-url}[Prometheus exposition format] are very similar in most important respects but are not identical. This brief summary treats them as the same.
+
+The OpenMetrics/Prometheus format represents each {metric} using three lines of output as summarized in the following table.
+
+.OpenMetrics/Prometheus format
+[cols="1,6,6"]
+|====
+| Line prefix | Purpose | Format
+
+| `# TYPE` | Displays the scope, name, and type of the {metric} | `TYPE : <{metric}-type>`
+| `# HELP` | Displays the scope, name, and description of the {metric} | `HELP : `
+| (none) | Displays the scope, {metric} ID, and current value of the {metric} | `: `
+|====
+The OpenMetrics/Prometheus output converts {metric} IDs in these ways:
+
+* Names in camel case are converted to "snake case" and dots are converted to underscores.
+* Names include any units specified for the {metric}.
+* For percentiles, the ID includes a tag identifying which percentile the line of output describes.
+
+As the earlier example output showed, for a {metric} with multiple values, such as a timer or a
+ifdef::se-flavor[distribution summary,]
+ifdef::mp-flavor[histogram,]
+(with, among others, `max`, `mean`, and `count`), the OpenMetrics/Prometheus output reports a "metric family" which includes a separate family member {metric} for each of the multiple values. The name for each member in the family is derived from the registered name for the {metric} plus a suffix indicating which one of the {metric}'s multiple values the line refers to.
+
+The following table summarizes the naming for each {metric} type.
+
+.OpenMetrics/Prometheus {metric_uc} Naming
+|====
+| {metric_uc} Type | Example registered name | {metric_uc} family member | Name Suffix | Example displayed name
+
+.1+| `Counter` | `requests.count` | count | `_total` | `requests_count_total`
+
+.4+|
+ifdef::se-flavor[`DistributionSummary`]
+ifdef::mp-flavor[`Histogram`]
+.4+| `nameLengths`
+| count | `_count` | `nameLengths_count`
+| sum | `_sum` | `nameLengths_sum`
+| max | `_max` | `nameLengths_max`
+| percentile | none | `nameLengths{{prom-output-scope-prefix}scope="base",quantile="0.5",}`
+
+.1+| `Gauge` | `classloader.loadedClasses.count` | value | none | `classloader_loadedClasses_count`
+
+.4+| `Timer` ^1^
+.4+| `vthreads.recentPinned`
+| count | `_count` | `vthreads_recentPinned_seconds_count`
+| sum | `_sum` | `vthreads_recentPinned_seconds_sum`
+| max | `_max` | `vthreads_recentPinned_seconds_max`
+| percentile | none | `vthreads_recentPinned_seconds{{prom-output-scope-prefix}scope="base",quantile="0.5",}`
+|====
+^1^ The OpenMetrics/Prometheus output format reports a timer as a `summary` with units of `seconds`.
+
// end::usage-retrieving[]
// tag::metric-registry-api[]
@@ -223,3 +329,9 @@ ifdef::se-flavor[]
endif::[]
// end::example-apps[]
+
+// tag::format-refcs-no-heading[]
+link:{openmetrics-format-doc-url}[OpenMetrics format]
+
+link:{prometheus-exposition-format-doc-url}[Prometheus exposition format]
+// end::format-refcs-no-heading[]
diff --git a/docs/src/main/asciidoc/mp/metrics/metrics.adoc b/docs/src/main/asciidoc/mp/metrics/metrics.adoc
index 636a4c7e0e6..d0beececff2 100644
--- a/docs/src/main/asciidoc/mp/metrics/metrics.adoc
+++ b/docs/src/main/asciidoc/mp/metrics/metrics.adoc
@@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////////////
- Copyright (c) 2022, 2024 Oracle and/or its affiliates.
+ Copyright (c) 2022, 2025 Oracle and/or its affiliates.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -86,17 +86,16 @@ The MicroProfile Metrics specification describes several metric types you can cr
| Annotation | Usage
| link:{microprofile-metrics-javadoc-annotation-url}/Counted.html[`@Counted`]
-| Monotonically increasing count of events.
+| Automatically registers a monotonically-increasing `Counter` and increments it with each invocation of the annotated constructor or method. ^1^
| link:{microprofile-metrics-javadoc-annotation-url}/Gauge.html[`@Gauge`]
-| Access to a value managed by other code in the service.
+| Automatically registers a `Gauge` whose value is provided by the annotated method. Code elsewhere in the system updates the underlying value.
| link:{microprofile-metrics-javadoc-annotation-url}/Timed.html[`@Timed`]
-| Frequency of invocations and the distribution of how long the invocations take.
+| Automatically registers a `Timer` and updates it with each invocation of the annotated constructor or method. ^1^
|====
-
-Place annotations on constructors or methods to measure those specific executables. If you annotate the class instead, Helidon applies that annotation to all constructors and methods which the class declares.
+^1^ Place annotations on constructors or methods to measure those specific executables. If you annotate the class instead, Helidon applies that annotation to all constructors and methods which the class declares.
==== Metric-referencing Annotations
To get a reference to a specific metric, use a metric-referencing annotation in any bean, including your REST resource classes.
@@ -405,3 +404,5 @@ include::{rootdir}/includes/guides/metrics.adoc[tag=k8s-and-prometheus-integrati
link:{microprofile-metrics-spec-url}[MicroProfile Metrics specification]
link:{microprofile-metrics-javadoc-url}/org/eclipse/microprofile/metrics/package-summary.html[MicroProfile Metrics API]
+
+include::{rootdir}/includes/metrics/metrics-shared.adoc[tag=format-refcs-no-heading]
diff --git a/docs/src/main/asciidoc/se/metrics/metrics.adoc b/docs/src/main/asciidoc/se/metrics/metrics.adoc
index be776226fd1..34dd879e84c 100644
--- a/docs/src/main/asciidoc/se/metrics/metrics.adoc
+++ b/docs/src/main/asciidoc/se/metrics/metrics.adoc
@@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////////////
- Copyright (c) 2018, 2024 Oracle and/or its affiliates.
+ Copyright (c) 2018, 2025 Oracle and/or its affiliates.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -45,6 +45,7 @@ include::{rootdir}/includes/se.adoc[]
** <>
** <>
- <>
+** <>
** <>
== Overview
@@ -270,6 +271,12 @@ include::{rootdir}/includes/metrics/metrics-config.adoc[tag=config-examples]
== Additional Information
+=== References
+
+link:{micrometer-api-url}[Micrometer Metrics concepts documentation]
+
+include::{rootdir}/includes/metrics/metrics-shared.adoc[tag=format-refcs-no-heading]
+
=== Support for the Prometheus Metrics API
- <>
- <>
diff --git a/metrics/api/src/main/java/io/helidon/metrics/api/Counter.java b/metrics/api/src/main/java/io/helidon/metrics/api/Counter.java
index 20d60f1620a..b212997359e 100644
--- a/metrics/api/src/main/java/io/helidon/metrics/api/Counter.java
+++ b/metrics/api/src/main/java/io/helidon/metrics/api/Counter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, 2024 Oracle and/or its affiliates.
+ * Copyright (c) 2023, 2025 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,7 +16,7 @@
package io.helidon.metrics.api;
/**
- * Records a monotonically increasing value.
+ * Records a monotonically increasing value that is updated by invoking methods on the {@code Counter} instance.
*/
public interface Counter extends Meter {
diff --git a/metrics/api/src/main/java/io/helidon/metrics/api/DistributionSummary.java b/metrics/api/src/main/java/io/helidon/metrics/api/DistributionSummary.java
index 33a71aa4e98..5852df4ca79 100644
--- a/metrics/api/src/main/java/io/helidon/metrics/api/DistributionSummary.java
+++ b/metrics/api/src/main/java/io/helidon/metrics/api/DistributionSummary.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, 2024 Oracle and/or its affiliates.
+ * Copyright (c) 2023, 2025 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,7 +18,9 @@
import java.util.Optional;
/**
- * Records a distribution of values (e.g., sizes of responses returned by a server).
+ * Records a distribution of samples (e.g., sizes of responses returned by a server), each with a {@code long} value, and
+ * reports statistics over all samples (count, total, mean, max) as well as grouping samples using percentiles or bucket
+ * boundaries.
*/
public interface DistributionSummary extends Meter {
diff --git a/metrics/api/src/main/java/io/helidon/metrics/api/Gauge.java b/metrics/api/src/main/java/io/helidon/metrics/api/Gauge.java
index 3875f8ee75c..c395a304db3 100644
--- a/metrics/api/src/main/java/io/helidon/metrics/api/Gauge.java
+++ b/metrics/api/src/main/java/io/helidon/metrics/api/Gauge.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, 2024 Oracle and/or its affiliates.
+ * Copyright (c) 2023, 2025 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@
import java.util.function.ToDoubleFunction;
/**
- * Measures a value that can increase or decrease and is updated by external logic, not by explicit invocations
+ * Exposes as a meter a value that can increase or decrease and is updated by external logic, not by explicit invocations
* of methods on this type.
*
* @param subtype of {@link Number} which a specific gauge reports
diff --git a/metrics/api/src/main/java/io/helidon/metrics/api/Timer.java b/metrics/api/src/main/java/io/helidon/metrics/api/Timer.java
index 1570b1604ea..5d39ffd1e05 100644
--- a/metrics/api/src/main/java/io/helidon/metrics/api/Timer.java
+++ b/metrics/api/src/main/java/io/helidon/metrics/api/Timer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, 2024 Oracle and/or its affiliates.
+ * Copyright (c) 2023, 2025 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,7 +22,9 @@
import java.util.function.Supplier;
/**
- * Records timing information about large numbers of short-running events (e.g., HTTP requests).
+ * Accumulates timing information about large numbers of short-running events (e.g., HTTP requests), each with a
+ * {@link java.time.Duration} value, and reports statistics over all samples (count, total time, mean, max) as well as grouping
+ * samples using percentiles or bucket boundaries.
*/
public interface Timer extends Meter, HistogramSupport {
diff --git a/parent/pom.xml b/parent/pom.xml
index 91c42706b7a..9e74bd1c5d8 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -168,7 +168,7 @@
io.helidon.build-tools
helidon-build-cache-maven-plugin
- 4.0.14
+ 4.0.15
diff --git a/pom.xml b/pom.xml
index 2e5c8752724..6e5230fa3b8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -124,7 +124,7 @@
3.1.0
3.1.2
2.3
- 4.0.14
+ 4.0.15
${version.lib.hibernate}
3.1.2
3.2.2