diff --git a/.github/renovate-tracked-deps.json b/.github/renovate-tracked-deps.json
index 412a82a33..95fa34155 100644
--- a/.github/renovate-tracked-deps.json
+++ b/.github/renovate-tracked-deps.json
@@ -16,6 +16,11 @@
"mise"
]
},
+ ".github/workflows/api-diff.yml": {
+ "regex": [
+ "mise"
+ ]
+ },
".github/workflows/build.yml": {
"regex": [
"mise"
diff --git a/.github/workflows/api-diff.yml b/.github/workflows/api-diff.yml
new file mode 100644
index 000000000..3a6ed2edf
--- /dev/null
+++ b/.github/workflows/api-diff.yml
@@ -0,0 +1,79 @@
+---
+name: API Diff
+
+on:
+ pull_request:
+ types:
+ - opened
+ - synchronize
+ - reopened
+ - labeled
+ - unlabeled
+ workflow_dispatch:
+ inputs:
+ baseline_version:
+ description: Version to compare the PR artifacts against
+ required: false
+ default: "1.5.1"
+
+permissions:
+ contents: read
+
+jobs:
+ api-diff:
+ runs-on: ubuntu-24.04
+ env:
+ API_DIFF_BASELINE_VERSION: ${{ inputs.baseline_version || '1.5.1' }}
+ BREAKING_API_CHANGE_ACCEPTED: >-
+ ${{ contains(github.event.pull_request.labels.*.name, 'breaking-api-change-accepted') }}
+
+ steps:
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
+ with:
+ persist-credentials: false
+ - uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4.0.1
+ with:
+ version: v2026.5.18
+ sha256: cfac593469d028d7ae5fe36e37bd7c59118b5238e92d8a876209578464f24a84
+ - name: Cache local Maven repository
+ uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
+ with:
+ path: ~/.m2/repository
+ key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+ - name: Run japicmp API diff
+ run: mise run api-diff
+ - name: Fail on incompatible published API changes
+ run: |
+ python3 - <<'PY'
+ import os
+ from pathlib import Path
+ import sys
+ import xml.etree.ElementTree as ET
+
+ failures = []
+ for report in sorted(Path(".").glob("**/target/japicmp/api-diff.xml")):
+ parts = report.parts
+ module = "/".join(parts[: parts.index("target")])
+ tree = ET.parse(report)
+ for change in tree.findall(".//compatibilityChange"):
+ binary = change.get("binaryCompatible") == "false"
+ source = change.get("sourceCompatible") == "false"
+ if binary or source:
+ failures.append((module, change.get("type", "unknown")))
+
+ if not failures:
+ print("No incompatible published API changes detected.")
+ sys.exit(0)
+
+ print("Incompatible published API changes detected:")
+ for module, change_type in failures[:100]:
+ print(f"- {module}: {change_type}")
+ if len(failures) > 100:
+ print(f"... and {len(failures) - 100} more")
+ if os.environ.get("BREAKING_API_CHANGE_ACCEPTED") == "true":
+ print("Accepted by PR label `breaking-api-change-accepted`.")
+ sys.exit(0)
+ print("Run `mise run api-diff` locally for full japicmp output.")
+ print("Reports are written to `**/target/japicmp/*`.")
+ sys.exit(1)
+ PY
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index 05b7cbaf5..4847aee2f 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -49,6 +49,7 @@ jobs:
- name: Build (CodeQL traces the build)
run: >
./mvnw clean compile
+ -P '!default'
-DskipTests
-Dcoverage.skip=true
-Dcheckstyle.skip=true
diff --git a/mise.toml b/mise.toml
index 973ef10a8..616159a90 100644
--- a/mise.toml
+++ b/mise.toml
@@ -59,6 +59,19 @@ run = "./mvnw verify"
description = "build all modules without tests"
run = "./mvnw install -DskipTests -Dcoverage.skip=true"
+[tasks."api-diff"]
+description = "Compare published API against the configured japicmp baseline"
+run = """
+BASELINE_VERSION="${API_DIFF_BASELINE_VERSION:-1.5.1}"
+./mvnw -B verify \
+ -P 'api-diff,!examples-and-integration-tests' \
+ -Dapi.diff.baseline.version="${BASELINE_VERSION}" \
+ -DskipTests \
+ -Dcoverage.skip=true \
+ -Dcheckstyle.skip=true \
+ -Dwarnings=-nowarn
+"""
+
[tasks."lint"]
description = "Run all lints"
depends = ["lint:bom"]
diff --git a/pom.xml b/pom.xml
index f9c25d9e2..a53c8e24e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -29,6 +29,7 @@
2.28.1-alpha825
+ 1.5.10.70falsefalse
@@ -38,6 +39,7 @@
prometheus-metrics-parent
+ prometheus-metrics-annotationsprometheus-metrics-bomprometheus-metrics-coreprometheus-metrics-config
@@ -171,6 +173,11 @@
exec-maven-plugin3.6.3
+
+ com.github.siom79.japicmp
+ japicmp-maven-plugin
+ 0.26.1
+
@@ -401,6 +408,71 @@
+
+ api-diff
+
+
+
+ com.github.siom79.japicmp
+ japicmp-maven-plugin
+
+
+
+ ${project.groupId}
+ ${project.artifactId}
+ ${api.diff.baseline.version}
+ jar
+
+
+
+
+ ${project.build.directory}/${project.build.finalName}.jar
+
+
+
+ public
+ true
+
+ io.prometheus.metrics.annotations.StableApi
+ @io.prometheus.metrics.annotations.StableApi
+
+
+ io.prometheus.metrics.expositionformats.generated
+ io.prometheus.metrics.shaded
+
+ false
+
+ false
+
+
+ false
+
+ false
+ true
+ true
+ true
+ true
+ true
+ true
+
+ bundle
+ jar
+
+
+
+
+
+ api-diff
+ verify
+
+ cmp
+
+
+
+
+
+
+ errorprone
diff --git a/prometheus-metrics-annotations/pom.xml b/prometheus-metrics-annotations/pom.xml
new file mode 100644
index 000000000..4b22354c4
--- /dev/null
+++ b/prometheus-metrics-annotations/pom.xml
@@ -0,0 +1,22 @@
+
+
+ 4.0.0
+
+
+ io.prometheus
+ client_java
+ 1.6.2-SNAPSHOT
+
+
+ prometheus-metrics-annotations
+ bundle
+
+ Prometheus Metrics Annotations
+
+ Annotations for Prometheus Metrics library API contracts.
+
+
+
+ io.prometheus.metrics.annotations
+
+
diff --git a/prometheus-metrics-annotations/src/main/java/io/prometheus/metrics/annotations/StableApi.java b/prometheus-metrics-annotations/src/main/java/io/prometheus/metrics/annotations/StableApi.java
new file mode 100644
index 000000000..a3bfe89ae
--- /dev/null
+++ b/prometheus-metrics-annotations/src/main/java/io/prometheus/metrics/annotations/StableApi.java
@@ -0,0 +1,22 @@
+package io.prometheus.metrics.annotations;
+
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Marks a Java element as part of the stable, published Prometheus Metrics API.
+ *
+ *
Use this on public or protected types to publish the type and its members. Use it on
+ * individual constructors, methods, and fields when only part of a public type is stable.
+ */
+@Documented
+@Retention(CLASS)
+@Target({TYPE, CONSTRUCTOR, METHOD, FIELD})
+public @interface StableApi {}
diff --git a/prometheus-metrics-bom/pom.xml b/prometheus-metrics-bom/pom.xml
index b01bcce43..66bcb524e 100644
--- a/prometheus-metrics-bom/pom.xml
+++ b/prometheus-metrics-bom/pom.xml
@@ -19,6 +19,11 @@
+
+ io.prometheus
+ prometheus-metrics-annotations
+ ${project.version}
+ io.prometheusprometheus-metrics-config
diff --git a/prometheus-metrics-config/pom.xml b/prometheus-metrics-config/pom.xml
index d505248e7..e207c6b49 100644
--- a/prometheus-metrics-config/pom.xml
+++ b/prometheus-metrics-config/pom.xml
@@ -21,6 +21,12 @@
+
+ io.prometheus
+ prometheus-metrics-annotations
+ ${project.version}
+ true
+ org.junit-pioneerjunit-pioneer
diff --git a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/EscapingScheme.java b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/EscapingScheme.java
index 1cd037bf3..1d6bd37cf 100644
--- a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/EscapingScheme.java
+++ b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/EscapingScheme.java
@@ -1,7 +1,9 @@
package io.prometheus.metrics.config;
+import io.prometheus.metrics.annotations.StableApi;
import javax.annotation.Nullable;
+@StableApi
public enum EscapingScheme {
/** NO_ESCAPING indicates that a name will not be escaped. */
ALLOW_UTF8("allow-utf-8"),
diff --git a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExemplarsProperties.java b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExemplarsProperties.java
index 765d33ac5..93190ef19 100644
--- a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExemplarsProperties.java
+++ b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExemplarsProperties.java
@@ -1,8 +1,10 @@
package io.prometheus.metrics.config;
+import io.prometheus.metrics.annotations.StableApi;
import javax.annotation.Nullable;
/** Properties starting with io.prometheus.exemplars */
+@StableApi
public class ExemplarsProperties {
private static final String PREFIX = "io.prometheus.exemplars";
diff --git a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterFilterProperties.java b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterFilterProperties.java
index d59330cb9..999c2c8e8 100644
--- a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterFilterProperties.java
+++ b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterFilterProperties.java
@@ -1,5 +1,6 @@
package io.prometheus.metrics.config;
+import io.prometheus.metrics.annotations.StableApi;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -7,6 +8,7 @@
import javax.annotation.Nullable;
/** Properties starting with io.prometheus.exporter.filter */
+@StableApi
public class ExporterFilterProperties {
public static final String METRIC_NAME_MUST_BE_EQUAL_TO = "metric_name_must_be_equal_to";
diff --git a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterHttpServerProperties.java b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterHttpServerProperties.java
index 0623f78e1..4f921c2ac 100644
--- a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterHttpServerProperties.java
+++ b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterHttpServerProperties.java
@@ -1,8 +1,10 @@
package io.prometheus.metrics.config;
+import io.prometheus.metrics.annotations.StableApi;
import javax.annotation.Nullable;
/** Properties starting with io.prometheus.exporter.http_server */
+@StableApi
public class ExporterHttpServerProperties {
private static final String PORT = "port";
diff --git a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterOpenTelemetryProperties.java b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterOpenTelemetryProperties.java
index 6e93f5de7..8c0bdd5c7 100644
--- a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterOpenTelemetryProperties.java
+++ b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterOpenTelemetryProperties.java
@@ -1,5 +1,6 @@
package io.prometheus.metrics.config;
+import io.prometheus.metrics.annotations.StableApi;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
@@ -31,6 +32,7 @@
* href="https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/">OpenTelemetry
* SDK Environment Variables
*/
+@StableApi
public class ExporterOpenTelemetryProperties {
// See
diff --git a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterProperties.java b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterProperties.java
index 460a5cae2..a1c67266a 100644
--- a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterProperties.java
+++ b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterProperties.java
@@ -1,8 +1,10 @@
package io.prometheus.metrics.config;
+import io.prometheus.metrics.annotations.StableApi;
import javax.annotation.Nullable;
/** Properties starting with io.prometheus.exporter */
+@StableApi
public class ExporterProperties {
private static final String INCLUDE_CREATED_TIMESTAMPS = "include_created_timestamps";
diff --git a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterPushgatewayProperties.java b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterPushgatewayProperties.java
index aea4b2d8f..10e8c0f33 100644
--- a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterPushgatewayProperties.java
+++ b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterPushgatewayProperties.java
@@ -1,8 +1,10 @@
package io.prometheus.metrics.config;
+import io.prometheus.metrics.annotations.StableApi;
import java.time.Duration;
import javax.annotation.Nullable;
+@StableApi
public class ExporterPushgatewayProperties {
private static final String ADDRESS = "address";
diff --git a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/MetricsProperties.java b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/MetricsProperties.java
index a530f35e1..c2758bd87 100644
--- a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/MetricsProperties.java
+++ b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/MetricsProperties.java
@@ -2,12 +2,14 @@
import static java.util.Collections.unmodifiableList;
+import io.prometheus.metrics.annotations.StableApi;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nullable;
/** Properties starting with io.prometheus.metrics */
+@StableApi
public class MetricsProperties {
private static final String EXEMPLARS_ENABLED = "exemplars_enabled";
diff --git a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/OpenMetrics2Properties.java b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/OpenMetrics2Properties.java
index be1d13279..1f5080f05 100644
--- a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/OpenMetrics2Properties.java
+++ b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/OpenMetrics2Properties.java
@@ -1,11 +1,13 @@
package io.prometheus.metrics.config;
+import io.prometheus.metrics.annotations.StableApi;
import javax.annotation.Nullable;
/**
* Properties starting with io.prometheus.openmetrics2. These properties are experimental and
* subject to change.
*/
+@StableApi
public class OpenMetrics2Properties {
private static final String PREFIX = "io.prometheus.openmetrics2";
diff --git a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/PrometheusProperties.java b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/PrometheusProperties.java
index 55e7d8dab..aa145d07c 100644
--- a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/PrometheusProperties.java
+++ b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/PrometheusProperties.java
@@ -1,5 +1,6 @@
package io.prometheus.metrics.config;
+import io.prometheus.metrics.annotations.StableApi;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
@@ -10,6 +11,7 @@
*
*
This class represents the runtime configuration.
*/
+@StableApi
public class PrometheusProperties {
private static final PrometheusProperties instance = PrometheusPropertiesLoader.load();
diff --git a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/PrometheusPropertiesException.java b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/PrometheusPropertiesException.java
index bdb024514..b6f6fac4b 100644
--- a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/PrometheusPropertiesException.java
+++ b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/PrometheusPropertiesException.java
@@ -1,5 +1,8 @@
package io.prometheus.metrics.config;
+import io.prometheus.metrics.annotations.StableApi;
+
+@StableApi
public class PrometheusPropertiesException extends RuntimeException {
private static final long serialVersionUID = 0L;
diff --git a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/PrometheusPropertiesLoader.java b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/PrometheusPropertiesLoader.java
index 018ea2c5d..6d52b71ef 100644
--- a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/PrometheusPropertiesLoader.java
+++ b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/PrometheusPropertiesLoader.java
@@ -1,5 +1,6 @@
package io.prometheus.metrics.config;
+import io.prometheus.metrics.annotations.StableApi;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
@@ -17,6 +18,7 @@
* Boot's Externalized Configuration, like support for YAML, Properties, and env vars, or
* support for Spring's naming conventions for properties.
*/
+@StableApi
public class PrometheusPropertiesLoader {
/** See {@link PrometheusProperties#get()}. */
diff --git a/prometheus-metrics-core/pom.xml b/prometheus-metrics-core/pom.xml
index 3ba812f1d..61d10d3c5 100644
--- a/prometheus-metrics-core/pom.xml
+++ b/prometheus-metrics-core/pom.xml
@@ -21,6 +21,12 @@
+
+ io.prometheus
+ prometheus-metrics-annotations
+ ${project.version}
+ true
+ io.prometheusprometheus-metrics-model
diff --git a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/datapoints/CounterDataPoint.java b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/datapoints/CounterDataPoint.java
index 7055d7565..4c5c2d28f 100644
--- a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/datapoints/CounterDataPoint.java
+++ b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/datapoints/CounterDataPoint.java
@@ -1,5 +1,6 @@
package io.prometheus.metrics.core.datapoints;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.model.snapshots.Labels;
/**
@@ -56,6 +57,7 @@
* CounterDataPoint counterData = counterWithoutLabels;
* }
*/
+@StableApi
public interface CounterDataPoint extends DataPoint {
/** Add one. */
diff --git a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/datapoints/DataPoint.java b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/datapoints/DataPoint.java
index 5b6017ddf..cfdc84df3 100644
--- a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/datapoints/DataPoint.java
+++ b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/datapoints/DataPoint.java
@@ -1,3 +1,6 @@
package io.prometheus.metrics.core.datapoints;
+import io.prometheus.metrics.annotations.StableApi;
+
+@StableApi
public interface DataPoint {}
diff --git a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/datapoints/DistributionDataPoint.java b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/datapoints/DistributionDataPoint.java
index 0f2a072de..f87bede40 100644
--- a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/datapoints/DistributionDataPoint.java
+++ b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/datapoints/DistributionDataPoint.java
@@ -1,5 +1,6 @@
package io.prometheus.metrics.core.datapoints;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.model.snapshots.Labels;
/**
@@ -17,6 +18,7 @@
*
See JavaDoc of {@link CounterDataPoint} on how using data points directly can improve
* performance.
*/
+@StableApi
public interface DistributionDataPoint extends DataPoint, TimerApi {
/** Get the count of observations. */
diff --git a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/datapoints/GaugeDataPoint.java b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/datapoints/GaugeDataPoint.java
index eec0304c7..8d917985e 100644
--- a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/datapoints/GaugeDataPoint.java
+++ b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/datapoints/GaugeDataPoint.java
@@ -1,5 +1,6 @@
package io.prometheus.metrics.core.datapoints;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.model.snapshots.Labels;
/**
@@ -9,6 +10,7 @@
*
See JavaDoc of {@link CounterDataPoint} on how using data points directly can improve
* performance.
*/
+@StableApi
public interface GaugeDataPoint extends DataPoint, TimerApi {
/** Add one. */
diff --git a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/datapoints/StateSetDataPoint.java b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/datapoints/StateSetDataPoint.java
index bf13b5214..f08876cae 100644
--- a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/datapoints/StateSetDataPoint.java
+++ b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/datapoints/StateSetDataPoint.java
@@ -1,11 +1,14 @@
package io.prometheus.metrics.core.datapoints;
+import io.prometheus.metrics.annotations.StableApi;
+
/**
* Represents a single StateSet data point.
*
*
See JavaDoc of {@link CounterDataPoint} on how using data points directly can improve
* performance.
*/
+@StableApi
public interface StateSetDataPoint extends DataPoint {
/**
diff --git a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/datapoints/Timer.java b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/datapoints/Timer.java
index d860bfa08..ee302a4c5 100644
--- a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/datapoints/Timer.java
+++ b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/datapoints/Timer.java
@@ -1,10 +1,12 @@
package io.prometheus.metrics.core.datapoints;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.model.snapshots.Unit;
import java.io.Closeable;
import java.util.function.DoubleConsumer;
/** Helper class for observing durations. */
+@StableApi
public class Timer implements Closeable {
private final DoubleConsumer observeFunction;
diff --git a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/datapoints/TimerApi.java b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/datapoints/TimerApi.java
index 8267f7f78..00729503e 100644
--- a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/datapoints/TimerApi.java
+++ b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/datapoints/TimerApi.java
@@ -1,5 +1,6 @@
package io.prometheus.metrics.core.datapoints;
+import io.prometheus.metrics.annotations.StableApi;
import java.util.concurrent.Callable;
import java.util.function.Supplier;
@@ -11,6 +12,7 @@
* must use base units (e.g. seconds, bytes) and leave converting them to something more readable to
* graphing tools".
*/
+@StableApi
public interface TimerApi {
/**
diff --git a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/exemplars/ExemplarSampler.java b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/exemplars/ExemplarSampler.java
index 1219b2a09..ad1591c21 100644
--- a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/exemplars/ExemplarSampler.java
+++ b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/exemplars/ExemplarSampler.java
@@ -2,6 +2,7 @@
import static java.util.Objects.requireNonNull;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.core.util.Scheduler;
import io.prometheus.metrics.model.snapshots.Exemplar;
import io.prometheus.metrics.model.snapshots.Exemplars;
@@ -31,6 +32,7 @@
*
*
We'll add a Jakarta servlet, the built-in HTTPServer, etc. soon, and likely move common code
* into a common module.
*/
+@StableApi
public class PrometheusMetricsServlet extends HttpServlet {
private static final long serialVersionUID = 0L;
diff --git a/prometheus-metrics-exporter-servlet-javax/pom.xml b/prometheus-metrics-exporter-servlet-javax/pom.xml
index 53df64c8d..d5749f71c 100644
--- a/prometheus-metrics-exporter-servlet-javax/pom.xml
+++ b/prometheus-metrics-exporter-servlet-javax/pom.xml
@@ -29,6 +29,12 @@
+
+ io.prometheus
+ prometheus-metrics-annotations
+ ${project.version}
+ true
+ io.prometheusprometheus-metrics-exporter-common
diff --git a/prometheus-metrics-exporter-servlet-javax/src/main/java/io/prometheus/metrics/exporter/servlet/javax/PrometheusMetricsServlet.java b/prometheus-metrics-exporter-servlet-javax/src/main/java/io/prometheus/metrics/exporter/servlet/javax/PrometheusMetricsServlet.java
index a486aec93..aa2e3e3a9 100644
--- a/prometheus-metrics-exporter-servlet-javax/src/main/java/io/prometheus/metrics/exporter/servlet/javax/PrometheusMetricsServlet.java
+++ b/prometheus-metrics-exporter-servlet-javax/src/main/java/io/prometheus/metrics/exporter/servlet/javax/PrometheusMetricsServlet.java
@@ -1,5 +1,6 @@
package io.prometheus.metrics.exporter.servlet.javax;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.config.PrometheusProperties;
import io.prometheus.metrics.exporter.common.PrometheusScrapeHandler;
import io.prometheus.metrics.model.registry.PrometheusRegistry;
@@ -13,6 +14,7 @@
* PrometheusScrapeHandler to handle HTTP GET requests and export metrics. The servlet can be
* configured with custom PrometheusProperties and a PrometheusRegistry.
*/
+@StableApi
public class PrometheusMetricsServlet extends HttpServlet {
private static final long serialVersionUID = 0L;
diff --git a/prometheus-metrics-exposition-textformats/pom.xml b/prometheus-metrics-exposition-textformats/pom.xml
index 91cb0de39..17c0dc450 100644
--- a/prometheus-metrics-exposition-textformats/pom.xml
+++ b/prometheus-metrics-exposition-textformats/pom.xml
@@ -22,6 +22,12 @@
+
+ io.prometheus
+ prometheus-metrics-annotations
+ ${project.version}
+ true
+ io.prometheusprometheus-metrics-model
diff --git a/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/ExpositionFormatWriter.java b/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/ExpositionFormatWriter.java
index 03ac229ca..7ea071bf7 100644
--- a/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/ExpositionFormatWriter.java
+++ b/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/ExpositionFormatWriter.java
@@ -1,5 +1,6 @@
package io.prometheus.metrics.expositionformats;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.config.EscapingScheme;
import io.prometheus.metrics.model.snapshots.MetricSnapshots;
import java.io.ByteArrayOutputStream;
@@ -7,6 +8,7 @@
import java.io.OutputStream;
import javax.annotation.Nullable;
+@StableApi
public interface ExpositionFormatWriter {
boolean accepts(@Nullable String acceptHeader);
diff --git a/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/ExpositionFormats.java b/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/ExpositionFormats.java
index feabd89b8..0cfce9b5f 100644
--- a/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/ExpositionFormats.java
+++ b/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/ExpositionFormats.java
@@ -1,10 +1,12 @@
package io.prometheus.metrics.expositionformats;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.config.ExporterProperties;
import io.prometheus.metrics.config.OpenMetrics2Properties;
import io.prometheus.metrics.config.PrometheusProperties;
import javax.annotation.Nullable;
+@StableApi
public class ExpositionFormats {
private final PrometheusProtobufWriter prometheusProtobufWriter;
diff --git a/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/OpenMetrics2TextFormatWriter.java b/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/OpenMetrics2TextFormatWriter.java
index 19e1e4c93..f400ecce0 100644
--- a/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/OpenMetrics2TextFormatWriter.java
+++ b/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/OpenMetrics2TextFormatWriter.java
@@ -9,6 +9,7 @@
import static io.prometheus.metrics.model.snapshots.SnapshotEscaper.getOriginalMetadataName;
import static io.prometheus.metrics.model.snapshots.SnapshotEscaper.getSnapshotLabelName;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.config.EscapingScheme;
import io.prometheus.metrics.config.OpenMetrics2Properties;
import io.prometheus.metrics.model.snapshots.ClassicHistogramBuckets;
@@ -45,6 +46,7 @@
* href="https://github.com/prometheus/docs/blob/main/docs/specs/om/open_metrics_spec_2_0.md">OpenMetrics
* 2.0 specification evolves.
*/
+@StableApi
public class OpenMetrics2TextFormatWriter implements ExpositionFormatWriter {
public static class Builder {
diff --git a/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/OpenMetricsTextFormatWriter.java b/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/OpenMetricsTextFormatWriter.java
index cd299cb94..02614a561 100644
--- a/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/OpenMetricsTextFormatWriter.java
+++ b/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/OpenMetricsTextFormatWriter.java
@@ -10,6 +10,7 @@
import static io.prometheus.metrics.model.snapshots.SnapshotEscaper.getMetadataName;
import static io.prometheus.metrics.model.snapshots.SnapshotEscaper.getSnapshotLabelName;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.config.EscapingScheme;
import io.prometheus.metrics.model.snapshots.ClassicHistogramBuckets;
import io.prometheus.metrics.model.snapshots.CounterSnapshot;
@@ -43,6 +44,7 @@
* Write the OpenMetrics text format as defined on https://openmetrics.io.
*/
+@StableApi
public class OpenMetricsTextFormatWriter implements ExpositionFormatWriter {
public static class Builder {
diff --git a/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/PrometheusProtobufWriter.java b/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/PrometheusProtobufWriter.java
index 342beb255..d7f4e4469 100644
--- a/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/PrometheusProtobufWriter.java
+++ b/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/PrometheusProtobufWriter.java
@@ -1,5 +1,6 @@
package io.prometheus.metrics.expositionformats;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.config.EscapingScheme;
import io.prometheus.metrics.model.snapshots.MetricSnapshots;
import java.io.IOException;
@@ -12,6 +13,7 @@
*
*
As of today, this is the only exposition format that supports native histograms.
*/
+@StableApi
public class PrometheusProtobufWriter implements ExpositionFormatWriter {
@Nullable private static final ExpositionFormatWriter DELEGATE = createProtobufWriter();
diff --git a/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/PrometheusTextFormatWriter.java b/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/PrometheusTextFormatWriter.java
index 9251ac85e..f94d710ba 100644
--- a/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/PrometheusTextFormatWriter.java
+++ b/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/PrometheusTextFormatWriter.java
@@ -12,6 +12,7 @@
import static io.prometheus.metrics.model.snapshots.SnapshotEscaper.getMetadataName;
import static io.prometheus.metrics.model.snapshots.SnapshotEscaper.getSnapshotLabelName;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.config.EscapingScheme;
import io.prometheus.metrics.model.snapshots.ClassicHistogramBuckets;
import io.prometheus.metrics.model.snapshots.CounterSnapshot;
@@ -40,6 +41,7 @@
* Write the Prometheus text format. This is the default if you view a Prometheus endpoint with your
* Web browser.
*/
+@StableApi
public class PrometheusTextFormatWriter implements ExpositionFormatWriter {
public static final String CONTENT_TYPE = "text/plain; version=0.0.4; charset=utf-8";
diff --git a/prometheus-metrics-instrumentation-caffeine/pom.xml b/prometheus-metrics-instrumentation-caffeine/pom.xml
index f2776f309..ed00e6e7d 100644
--- a/prometheus-metrics-instrumentation-caffeine/pom.xml
+++ b/prometheus-metrics-instrumentation-caffeine/pom.xml
@@ -29,6 +29,12 @@
+
+ io.prometheus
+ prometheus-metrics-annotations
+ ${project.version}
+ true
+ io.prometheusprometheus-metrics-core
diff --git a/prometheus-metrics-instrumentation-caffeine/src/main/java/io/prometheus/metrics/instrumentation/caffeine/CacheMetricsCollector.java b/prometheus-metrics-instrumentation-caffeine/src/main/java/io/prometheus/metrics/instrumentation/caffeine/CacheMetricsCollector.java
index 28edff88f..ba7552910 100644
--- a/prometheus-metrics-instrumentation-caffeine/src/main/java/io/prometheus/metrics/instrumentation/caffeine/CacheMetricsCollector.java
+++ b/prometheus-metrics-instrumentation-caffeine/src/main/java/io/prometheus/metrics/instrumentation/caffeine/CacheMetricsCollector.java
@@ -5,6 +5,7 @@
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.github.benmanes.caffeine.cache.Policy;
import com.github.benmanes.caffeine.cache.stats.CacheStats;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.model.registry.MultiCollector;
import io.prometheus.metrics.model.snapshots.CounterSnapshot;
import io.prometheus.metrics.model.snapshots.GaugeSnapshot;
@@ -55,6 +56,7 @@
* caffeine_cache_load_duration_seconds_sum{cache="mycache"} 0.0034
*
*/
+@StableApi
public class CacheMetricsCollector implements MultiCollector {
private static final double NANOSECONDS_PER_SECOND = 1_000_000_000.0;
diff --git a/prometheus-metrics-instrumentation-dropwizard/pom.xml b/prometheus-metrics-instrumentation-dropwizard/pom.xml
index 0f4c1ead3..fd90bfd51 100644
--- a/prometheus-metrics-instrumentation-dropwizard/pom.xml
+++ b/prometheus-metrics-instrumentation-dropwizard/pom.xml
@@ -29,6 +29,12 @@
+
+ io.prometheus
+ prometheus-metrics-annotations
+ ${project.version}
+ true
+ io.prometheusprometheus-metrics-core
diff --git a/prometheus-metrics-instrumentation-dropwizard/src/main/java/io/prometheus/metrics/instrumentation/dropwizard/DropwizardExports.java b/prometheus-metrics-instrumentation-dropwizard/src/main/java/io/prometheus/metrics/instrumentation/dropwizard/DropwizardExports.java
index 0c1c8455f..4e527ce87 100644
--- a/prometheus-metrics-instrumentation-dropwizard/src/main/java/io/prometheus/metrics/instrumentation/dropwizard/DropwizardExports.java
+++ b/prometheus-metrics-instrumentation-dropwizard/src/main/java/io/prometheus/metrics/instrumentation/dropwizard/DropwizardExports.java
@@ -9,6 +9,7 @@
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Snapshot;
import com.codahale.metrics.Timer;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.instrumentation.dropwizard5.InvalidMetricHandler;
import io.prometheus.metrics.instrumentation.dropwizard5.internal.AbstractDropwizardExports;
import io.prometheus.metrics.instrumentation.dropwizard5.labels.CustomLabelMapper;
@@ -22,6 +23,7 @@
*
This is a thin wrapper around {@link AbstractDropwizardExports} that handles the Dropwizard
* 4.x specific API where metric names are Strings.
*/
+@StableApi
public class DropwizardExports
extends AbstractDropwizardExports<
MetricRegistry,
diff --git a/prometheus-metrics-instrumentation-dropwizard5/pom.xml b/prometheus-metrics-instrumentation-dropwizard5/pom.xml
index ffee45702..654b575ce 100644
--- a/prometheus-metrics-instrumentation-dropwizard5/pom.xml
+++ b/prometheus-metrics-instrumentation-dropwizard5/pom.xml
@@ -22,6 +22,12 @@
+
+ io.prometheus
+ prometheus-metrics-annotations
+ ${project.version}
+ true
+ io.prometheusprometheus-metrics-core
diff --git a/prometheus-metrics-instrumentation-dropwizard5/src/main/java/io/prometheus/metrics/instrumentation/dropwizard5/DropwizardExports.java b/prometheus-metrics-instrumentation-dropwizard5/src/main/java/io/prometheus/metrics/instrumentation/dropwizard5/DropwizardExports.java
index 86c64b54e..dec51dc92 100644
--- a/prometheus-metrics-instrumentation-dropwizard5/src/main/java/io/prometheus/metrics/instrumentation/dropwizard5/DropwizardExports.java
+++ b/prometheus-metrics-instrumentation-dropwizard5/src/main/java/io/prometheus/metrics/instrumentation/dropwizard5/DropwizardExports.java
@@ -10,6 +10,7 @@
import io.dropwizard.metrics5.MetricRegistry;
import io.dropwizard.metrics5.Snapshot;
import io.dropwizard.metrics5.Timer;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.instrumentation.dropwizard5.internal.AbstractDropwizardExports;
import io.prometheus.metrics.instrumentation.dropwizard5.labels.CustomLabelMapper;
import io.prometheus.metrics.model.registry.PrometheusRegistry;
@@ -22,6 +23,7 @@
*
This is a thin wrapper around {@link AbstractDropwizardExports} that handles the Dropwizard
* 5.x specific API where metric names are {@link MetricName} objects.
*/
+@StableApi
public class DropwizardExports
extends AbstractDropwizardExports<
MetricRegistry,
diff --git a/prometheus-metrics-instrumentation-dropwizard5/src/main/java/io/prometheus/metrics/instrumentation/dropwizard5/InvalidMetricHandler.java b/prometheus-metrics-instrumentation-dropwizard5/src/main/java/io/prometheus/metrics/instrumentation/dropwizard5/InvalidMetricHandler.java
index bac1aa0af..cb7d965ff 100644
--- a/prometheus-metrics-instrumentation-dropwizard5/src/main/java/io/prometheus/metrics/instrumentation/dropwizard5/InvalidMetricHandler.java
+++ b/prometheus-metrics-instrumentation-dropwizard5/src/main/java/io/prometheus/metrics/instrumentation/dropwizard5/InvalidMetricHandler.java
@@ -1,6 +1,9 @@
package io.prometheus.metrics.instrumentation.dropwizard5;
+import io.prometheus.metrics.annotations.StableApi;
+
@FunctionalInterface
+@StableApi
public interface InvalidMetricHandler {
InvalidMetricHandler ALWAYS_THROW = (metricName, exc) -> false;
diff --git a/prometheus-metrics-instrumentation-dropwizard5/src/main/java/io/prometheus/metrics/instrumentation/dropwizard5/labels/CustomLabelMapper.java b/prometheus-metrics-instrumentation-dropwizard5/src/main/java/io/prometheus/metrics/instrumentation/dropwizard5/labels/CustomLabelMapper.java
index f2174970c..61fb5de5a 100644
--- a/prometheus-metrics-instrumentation-dropwizard5/src/main/java/io/prometheus/metrics/instrumentation/dropwizard5/labels/CustomLabelMapper.java
+++ b/prometheus-metrics-instrumentation-dropwizard5/src/main/java/io/prometheus/metrics/instrumentation/dropwizard5/labels/CustomLabelMapper.java
@@ -1,5 +1,6 @@
package io.prometheus.metrics.instrumentation.dropwizard5.labels;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.model.snapshots.Labels;
import java.util.ArrayList;
import java.util.List;
@@ -10,6 +11,7 @@
* labels and names. Prometheus metric name and labels are extracted from the Dropwizard name based
* on the provided list of {@link MapperConfig}s. The FIRST matching config will be used.
*/
+@StableApi
public class CustomLabelMapper {
private final List compiledMapperConfigs;
diff --git a/prometheus-metrics-instrumentation-dropwizard5/src/main/java/io/prometheus/metrics/instrumentation/dropwizard5/labels/MapperConfig.java b/prometheus-metrics-instrumentation-dropwizard5/src/main/java/io/prometheus/metrics/instrumentation/dropwizard5/labels/MapperConfig.java
index 2fced7ef6..46d4d36e4 100644
--- a/prometheus-metrics-instrumentation-dropwizard5/src/main/java/io/prometheus/metrics/instrumentation/dropwizard5/labels/MapperConfig.java
+++ b/prometheus-metrics-instrumentation-dropwizard5/src/main/java/io/prometheus/metrics/instrumentation/dropwizard5/labels/MapperConfig.java
@@ -1,5 +1,6 @@
package io.prometheus.metrics.instrumentation.dropwizard5.labels;
+import io.prometheus.metrics.annotations.StableApi;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
@@ -15,6 +16,7 @@
*
Dropwizard metrics that match the "match" pattern will be further processed to have a new name
* and new labels based on this config.
*/
+@StableApi
public final class MapperConfig {
// Each part of the metric name between dots. Accepts letters, digits, underscores, hyphens,
// colons, and glob wildcards (*) to support a broad range of metric naming conventions.
diff --git a/prometheus-metrics-instrumentation-guava/pom.xml b/prometheus-metrics-instrumentation-guava/pom.xml
index bb23faf3e..63980781c 100644
--- a/prometheus-metrics-instrumentation-guava/pom.xml
+++ b/prometheus-metrics-instrumentation-guava/pom.xml
@@ -29,6 +29,12 @@
+
+ io.prometheus
+ prometheus-metrics-annotations
+ ${project.version}
+ true
+ io.prometheusprometheus-metrics-core
diff --git a/prometheus-metrics-instrumentation-guava/src/main/java/io/prometheus/metrics/instrumentation/guava/CacheMetricsCollector.java b/prometheus-metrics-instrumentation-guava/src/main/java/io/prometheus/metrics/instrumentation/guava/CacheMetricsCollector.java
index 7a66e1d17..b807a28f0 100644
--- a/prometheus-metrics-instrumentation-guava/src/main/java/io/prometheus/metrics/instrumentation/guava/CacheMetricsCollector.java
+++ b/prometheus-metrics-instrumentation-guava/src/main/java/io/prometheus/metrics/instrumentation/guava/CacheMetricsCollector.java
@@ -3,6 +3,7 @@
import com.google.common.cache.Cache;
import com.google.common.cache.CacheStats;
import com.google.common.cache.LoadingCache;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.model.registry.MultiCollector;
import io.prometheus.metrics.model.snapshots.CounterSnapshot;
import io.prometheus.metrics.model.snapshots.GaugeSnapshot;
@@ -51,6 +52,7 @@
* guava_cache_load_duration_seconds_sum{cache="mycache"} 0.0034
*
*/
+@StableApi
public class CacheMetricsCollector implements MultiCollector {
private static final double NANOSECONDS_PER_SECOND = 1_000_000_000.0;
diff --git a/prometheus-metrics-instrumentation-jvm/pom.xml b/prometheus-metrics-instrumentation-jvm/pom.xml
index d50a567e4..5cbdc3bd7 100644
--- a/prometheus-metrics-instrumentation-jvm/pom.xml
+++ b/prometheus-metrics-instrumentation-jvm/pom.xml
@@ -22,6 +22,12 @@
+
+ io.prometheus
+ prometheus-metrics-annotations
+ ${project.version}
+ true
+ io.prometheusprometheus-metrics-core
diff --git a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmBufferPoolMetrics.java b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmBufferPoolMetrics.java
index 8fc4b87e9..a31d46ba4 100644
--- a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmBufferPoolMetrics.java
+++ b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmBufferPoolMetrics.java
@@ -1,5 +1,6 @@
package io.prometheus.metrics.instrumentation.jvm;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.config.PrometheusProperties;
import io.prometheus.metrics.core.metrics.GaugeWithCallback;
import io.prometheus.metrics.model.registry.PrometheusRegistry;
@@ -41,6 +42,7 @@
* jvm_buffer_pool_used_bytes{pool="mapped"} 0.0
*
*/
+@StableApi
public class JvmBufferPoolMetrics {
private static final String JVM_BUFFER_POOL_USED_BYTES = "jvm_buffer_pool_used_bytes";
diff --git a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmClassLoadingMetrics.java b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmClassLoadingMetrics.java
index 34e9dcb8a..28b10cfb7 100644
--- a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmClassLoadingMetrics.java
+++ b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmClassLoadingMetrics.java
@@ -1,5 +1,6 @@
package io.prometheus.metrics.instrumentation.jvm;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.config.PrometheusProperties;
import io.prometheus.metrics.core.metrics.CounterWithCallback;
import io.prometheus.metrics.core.metrics.GaugeWithCallback;
@@ -37,6 +38,7 @@
* jvm_classes_unloaded_total 0.0
*
*/
+@StableApi
public class JvmClassLoadingMetrics {
private static final String JVM_CLASSES_CURRENTLY_LOADED = "jvm_classes_currently_loaded";
diff --git a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmCompilationMetrics.java b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmCompilationMetrics.java
index 975b6c6a3..86b5cc88d 100644
--- a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmCompilationMetrics.java
+++ b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmCompilationMetrics.java
@@ -2,6 +2,7 @@
import static io.prometheus.metrics.model.snapshots.Unit.millisToSeconds;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.config.PrometheusProperties;
import io.prometheus.metrics.core.metrics.CounterWithCallback;
import io.prometheus.metrics.model.registry.PrometheusRegistry;
@@ -33,6 +34,7 @@
* jvm_compilation_time_seconds_total 0.152
*
*/
+@StableApi
public class JvmCompilationMetrics {
private static final String JVM_COMPILATION_TIME_SECONDS_TOTAL =
diff --git a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmGarbageCollectorMetrics.java b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmGarbageCollectorMetrics.java
index a87b52a4f..aec943706 100644
--- a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmGarbageCollectorMetrics.java
+++ b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmGarbageCollectorMetrics.java
@@ -1,5 +1,6 @@
package io.prometheus.metrics.instrumentation.jvm;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.config.PrometheusProperties;
import io.prometheus.metrics.core.metrics.SummaryWithCallback;
import io.prometheus.metrics.model.registry.PrometheusRegistry;
@@ -37,6 +38,7 @@
* jvm_gc_collection_seconds_sum{gc="PS Scavenge"} 0.0
*
*/
+@StableApi
public class JvmGarbageCollectorMetrics {
private static final String JVM_GC_COLLECTION_SECONDS = "jvm_gc_collection_seconds";
diff --git a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmMemoryMetrics.java b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmMemoryMetrics.java
index 1b34dba6c..2fb377882 100644
--- a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmMemoryMetrics.java
+++ b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmMemoryMetrics.java
@@ -1,5 +1,6 @@
package io.prometheus.metrics.instrumentation.jvm;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.config.PrometheusProperties;
import io.prometheus.metrics.core.metrics.GaugeWithCallback;
import io.prometheus.metrics.model.registry.PrometheusRegistry;
@@ -104,6 +105,7 @@
* jvm_memory_used_bytes{area="nonheap"} 1.1490688E7
*
*/
+@StableApi
public class JvmMemoryMetrics {
private static final String JVM_MEMORY_OBJECTS_PENDING_FINALIZATION =
diff --git a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmMemoryPoolAllocationMetrics.java b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmMemoryPoolAllocationMetrics.java
index 5dfb4199b..a8f520584 100644
--- a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmMemoryPoolAllocationMetrics.java
+++ b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmMemoryPoolAllocationMetrics.java
@@ -2,6 +2,7 @@
import com.sun.management.GarbageCollectionNotificationInfo;
import com.sun.management.GcInfo;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.config.PrometheusProperties;
import io.prometheus.metrics.core.metrics.Counter;
import io.prometheus.metrics.model.registry.PrometheusRegistry;
@@ -47,6 +48,7 @@
* jvm_memory_pool_allocated_bytes_total{pool="PS Survivor Space"} 4115280.0
*
*/
+@StableApi
public class JvmMemoryPoolAllocationMetrics {
private static final String JVM_MEMORY_POOL_ALLOCATED_BYTES_TOTAL =
diff --git a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmMetrics.java b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmMetrics.java
index b0abd86b1..d7ab40d13 100644
--- a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmMetrics.java
+++ b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmMetrics.java
@@ -1,5 +1,6 @@
package io.prometheus.metrics.instrumentation.jvm;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.config.PrometheusProperties;
import io.prometheus.metrics.model.registry.PrometheusRegistry;
import io.prometheus.metrics.model.snapshots.Labels;
@@ -13,6 +14,7 @@
* JvmMetrics.builder().register();
* }
*/
+@StableApi
public class JvmMetrics {
private static final Set REGISTERED = ConcurrentHashMap.newKeySet();
diff --git a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmNativeMemoryMetrics.java b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmNativeMemoryMetrics.java
index 6b11df38a..d08e3fb11 100644
--- a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmNativeMemoryMetrics.java
+++ b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmNativeMemoryMetrics.java
@@ -1,5 +1,6 @@
package io.prometheus.metrics.instrumentation.jvm;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.config.PrometheusProperties;
import io.prometheus.metrics.core.metrics.GaugeWithCallback;
import io.prometheus.metrics.model.registry.PrometheusRegistry;
@@ -85,6 +86,7 @@
* jvm_native_memory_reserved_bytes{pool="Unknown"} 32768.0
*
*/
+@StableApi
public class JvmNativeMemoryMetrics {
private static final String JVM_NATIVE_MEMORY_RESERVED_BYTES = "jvm_native_memory_reserved_bytes";
private static final String JVM_NATIVE_MEMORY_COMMITTED_BYTES =
diff --git a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmRuntimeInfoMetric.java b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmRuntimeInfoMetric.java
index 58363780f..095b643b0 100644
--- a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmRuntimeInfoMetric.java
+++ b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmRuntimeInfoMetric.java
@@ -1,5 +1,6 @@
package io.prometheus.metrics.instrumentation.jvm;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.config.PrometheusProperties;
import io.prometheus.metrics.core.metrics.Info;
import io.prometheus.metrics.model.registry.PrometheusRegistry;
@@ -26,6 +27,7 @@
* jvm_runtime_info{runtime="OpenJDK Runtime Environment",vendor="Oracle Corporation",version="1.8.0_382-b05"} 1
*
*/
+@StableApi
public class JvmRuntimeInfoMetric {
private static final String JVM_RUNTIME_INFO = "jvm_runtime_info";
diff --git a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmThreadsMetrics.java b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmThreadsMetrics.java
index 0e98e29d3..af41887bf 100644
--- a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmThreadsMetrics.java
+++ b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/JvmThreadsMetrics.java
@@ -2,6 +2,7 @@
import static java.util.Objects.requireNonNull;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.config.PrometheusProperties;
import io.prometheus.metrics.core.metrics.CounterWithCallback;
import io.prometheus.metrics.core.metrics.GaugeWithCallback;
@@ -61,6 +62,7 @@
* jvm_threads_state{state="WAITING"} 3.0
*
*/
+@StableApi
public class JvmThreadsMetrics {
private static final String UNKNOWN = "UNKNOWN";
diff --git a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/ProcessMetrics.java b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/ProcessMetrics.java
index b341f848a..6132ad08e 100644
--- a/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/ProcessMetrics.java
+++ b/prometheus-metrics-instrumentation-jvm/src/main/java/io/prometheus/metrics/instrumentation/jvm/ProcessMetrics.java
@@ -1,5 +1,6 @@
package io.prometheus.metrics.instrumentation.jvm;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.config.PrometheusProperties;
import io.prometheus.metrics.core.metrics.CounterWithCallback;
import io.prometheus.metrics.core.metrics.GaugeWithCallback;
@@ -67,6 +68,7 @@
* process_virtual_memory_bytes 1.2683624448E10
*
*/
+@StableApi
public class ProcessMetrics {
private static final String PROCESS_CPU_SECONDS_TOTAL = "process_cpu_seconds_total";
diff --git a/prometheus-metrics-model/pom.xml b/prometheus-metrics-model/pom.xml
index cdac0a60b..c1a83dea0 100644
--- a/prometheus-metrics-model/pom.xml
+++ b/prometheus-metrics-model/pom.xml
@@ -22,6 +22,12 @@
+
+ io.prometheus
+ prometheus-metrics-annotations
+ ${project.version}
+ true
+ io.prometheusprometheus-metrics-config
diff --git a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/Collector.java b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/Collector.java
index f903ce676..0f2ccd516 100644
--- a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/Collector.java
+++ b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/Collector.java
@@ -1,5 +1,6 @@
package io.prometheus.metrics.model.registry;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor;
import io.prometheus.metrics.model.snapshots.MetricMetadata;
import io.prometheus.metrics.model.snapshots.MetricSnapshot;
@@ -13,6 +14,7 @@
* href="https://prometheus.io/docs/instrumenting/writing_clientlibs/">https://prometheus.io/docs/instrumenting/writing_clientlibs/.
*/
@FunctionalInterface
+@StableApi
public interface Collector {
/** Called when the Prometheus server scrapes metrics. */
diff --git a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/MetricNameFilter.java b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/MetricNameFilter.java
index 609f7fd33..642f27150 100644
--- a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/MetricNameFilter.java
+++ b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/MetricNameFilter.java
@@ -2,6 +2,7 @@
import static java.util.Collections.unmodifiableCollection;
+import io.prometheus.metrics.annotations.StableApi;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -9,6 +10,7 @@
import javax.annotation.Nullable;
/** Filter samples (i.e. time series) by name. */
+@StableApi
public class MetricNameFilter implements Predicate {
/** For convenience, a filter that allows all names. */
diff --git a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/MetricType.java b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/MetricType.java
index 5258da84e..f1b5d76ba 100644
--- a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/MetricType.java
+++ b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/MetricType.java
@@ -1,11 +1,14 @@
package io.prometheus.metrics.model.registry;
+import io.prometheus.metrics.annotations.StableApi;
+
/**
* Represents the type of Prometheus metric.
*
*
This enum is used for registration-time validation to ensure that metrics with the same name
* have consistent types across all registered collectors.
*/
+@StableApi
public enum MetricType {
COUNTER,
GAUGE,
diff --git a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/MultiCollector.java b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/MultiCollector.java
index 692f0be71..54ce8c47c 100644
--- a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/MultiCollector.java
+++ b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/MultiCollector.java
@@ -1,5 +1,6 @@
package io.prometheus.metrics.model.registry;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor;
import io.prometheus.metrics.model.snapshots.MetricMetadata;
import io.prometheus.metrics.model.snapshots.MetricSnapshot;
@@ -13,6 +14,7 @@
/** Like {@link Collector}, but collecting multiple Snapshots at once. */
@FunctionalInterface
+@StableApi
public interface MultiCollector {
/** Called when the Prometheus server scrapes metrics. */
diff --git a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/PrometheusRegistry.java b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/PrometheusRegistry.java
index 071c90f4b..882f5711d 100644
--- a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/PrometheusRegistry.java
+++ b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/PrometheusRegistry.java
@@ -2,6 +2,7 @@
import static java.util.Collections.emptySet;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.model.snapshots.MetricFamilyDescriptor;
import io.prometheus.metrics.model.snapshots.MetricMetadata;
import io.prometheus.metrics.model.snapshots.MetricSnapshot;
@@ -17,6 +18,7 @@
import java.util.function.Predicate;
import javax.annotation.Nullable;
+@StableApi
public class PrometheusRegistry {
public static final PrometheusRegistry defaultRegistry = new PrometheusRegistry();
diff --git a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/PrometheusScrapeRequest.java b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/PrometheusScrapeRequest.java
index 91a1313ab..2ec6c768f 100644
--- a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/PrometheusScrapeRequest.java
+++ b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/PrometheusScrapeRequest.java
@@ -1,8 +1,10 @@
package io.prometheus.metrics.model.registry;
+import io.prometheus.metrics.annotations.StableApi;
import javax.annotation.Nullable;
/** Infos extracted from the request received by the endpoint */
+@StableApi
public interface PrometheusScrapeRequest {
/** Absolute path of the HTTP request. */
diff --git a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/ClassicHistogramBucket.java b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/ClassicHistogramBucket.java
index ebadd1f16..0f487efdf 100644
--- a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/ClassicHistogramBucket.java
+++ b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/ClassicHistogramBucket.java
@@ -1,9 +1,12 @@
package io.prometheus.metrics.model.snapshots;
+import io.prometheus.metrics.annotations.StableApi;
+
/**
* Helper class for iterating over {@link ClassicHistogramBuckets}. Note that the {@code count} is
* not cumulative.
*/
+@StableApi
public class ClassicHistogramBucket implements Comparable {
private final long count; // not cumulative
diff --git a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/ClassicHistogramBuckets.java b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/ClassicHistogramBuckets.java
index c697bee39..b2998d799 100644
--- a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/ClassicHistogramBuckets.java
+++ b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/ClassicHistogramBuckets.java
@@ -1,5 +1,6 @@
package io.prometheus.metrics.model.snapshots;
+import io.prometheus.metrics.annotations.StableApi;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -11,6 +12,7 @@
* Immutable container for histogram buckets with fixed bucket boundaries. Note that the counts are
* not cumulative.
*/
+@StableApi
public class ClassicHistogramBuckets implements Iterable {
/** Used in native histograms to indicate that no classic histogram buckets are present. */
diff --git a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/CounterSnapshot.java b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/CounterSnapshot.java
index e5831168b..42a06f3bb 100644
--- a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/CounterSnapshot.java
+++ b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/CounterSnapshot.java
@@ -1,5 +1,6 @@
package io.prometheus.metrics.model.snapshots;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.config.EscapingScheme;
import java.util.ArrayList;
import java.util.Collection;
@@ -7,6 +8,7 @@
import javax.annotation.Nullable;
/** Immutable snapshot of a Counter. */
+@StableApi
public class CounterSnapshot extends MetricSnapshot {
/**
diff --git a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/DataPointSnapshot.java b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/DataPointSnapshot.java
index d960912a0..910e2ef50 100644
--- a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/DataPointSnapshot.java
+++ b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/DataPointSnapshot.java
@@ -1,8 +1,10 @@
package io.prometheus.metrics.model.snapshots;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.config.EscapingScheme;
@SuppressWarnings("this-escape")
+@StableApi
public abstract class DataPointSnapshot {
private final Labels labels;
private final long createdTimestampMillis;
diff --git a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/DistributionDataPointSnapshot.java b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/DistributionDataPointSnapshot.java
index 1ae0559e1..2d1331915 100644
--- a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/DistributionDataPointSnapshot.java
+++ b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/DistributionDataPointSnapshot.java
@@ -1,9 +1,12 @@
package io.prometheus.metrics.model.snapshots;
+import io.prometheus.metrics.annotations.StableApi;
+
/**
* Common base class for histogram and summary data. Histograms and Summaries represent
* distributions, like a latency distribution or a distribution of request sizes in Bytes.
*/
+@StableApi
public abstract class DistributionDataPointSnapshot extends DataPointSnapshot {
private final long count; // optional, negative value means no count.
private final double sum; // optional, Double.NaN means no sum.
diff --git a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/DuplicateLabelsException.java b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/DuplicateLabelsException.java
index 721655105..fd1e6d838 100644
--- a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/DuplicateLabelsException.java
+++ b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/DuplicateLabelsException.java
@@ -1,9 +1,12 @@
package io.prometheus.metrics.model.snapshots;
+import io.prometheus.metrics.annotations.StableApi;
+
/**
* Thrown when a collector tries to create a {@link MetricSnapshot} where multiple data points have
* the same labels (same label names and label values).
*/
+@StableApi
public class DuplicateLabelsException extends IllegalArgumentException {
private static final long serialVersionUID = 0L;
diff --git a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/Exemplar.java b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/Exemplar.java
index 418603580..07dc811f8 100644
--- a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/Exemplar.java
+++ b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/Exemplar.java
@@ -2,9 +2,11 @@
import static java.util.Objects.requireNonNull;
+import io.prometheus.metrics.annotations.StableApi;
import javax.annotation.Nullable;
/** Immutable representation of an Exemplar. */
+@StableApi
public class Exemplar {
/** Label name for trace id. */
diff --git a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/Exemplars.java b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/Exemplars.java
index 887a80fff..1408419b7 100644
--- a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/Exemplars.java
+++ b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/Exemplars.java
@@ -1,5 +1,6 @@
package io.prometheus.metrics.model.snapshots;
+import io.prometheus.metrics.annotations.StableApi;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -14,6 +15,7 @@
*
This is currently backed by a {@code List}. May be refactored later to use a more
* efficient data structure.
*/
+@StableApi
public class Exemplars implements Iterable {
/** EMPTY means no Exemplars. */
diff --git a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/GaugeSnapshot.java b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/GaugeSnapshot.java
index 03474852f..7a4208b05 100644
--- a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/GaugeSnapshot.java
+++ b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/GaugeSnapshot.java
@@ -1,5 +1,6 @@
package io.prometheus.metrics.model.snapshots;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.config.EscapingScheme;
import java.util.ArrayList;
import java.util.Collection;
@@ -7,6 +8,7 @@
import javax.annotation.Nullable;
/** Immutable snapshot of a Gauge. */
+@StableApi
public final class GaugeSnapshot extends MetricSnapshot {
/**
diff --git a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/HistogramSnapshot.java b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/HistogramSnapshot.java
index acc78d3d3..06c687c9f 100644
--- a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/HistogramSnapshot.java
+++ b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/HistogramSnapshot.java
@@ -1,11 +1,13 @@
package io.prometheus.metrics.model.snapshots;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.config.EscapingScheme;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/** Immutable snapshot of a Histogram. */
+@StableApi
public final class HistogramSnapshot extends MetricSnapshot {
private final boolean gaugeHistogram;
diff --git a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/InfoSnapshot.java b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/InfoSnapshot.java
index 20f9038b1..0178eea2e 100644
--- a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/InfoSnapshot.java
+++ b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/InfoSnapshot.java
@@ -1,5 +1,6 @@
package io.prometheus.metrics.model.snapshots;
+import io.prometheus.metrics.annotations.StableApi;
import io.prometheus.metrics.config.EscapingScheme;
import java.util.ArrayList;
import java.util.Collection;
@@ -7,6 +8,7 @@
import javax.annotation.Nullable;
/** Immutable snapshot of an Info metric. */
+@StableApi
public final class InfoSnapshot extends MetricSnapshot {
/**
diff --git a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/Label.java b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/Label.java
index 45acd56ee..7af8d3310 100644
--- a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/Label.java
+++ b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/Label.java
@@ -1,8 +1,10 @@
package io.prometheus.metrics.model.snapshots;
+import io.prometheus.metrics.annotations.StableApi;
import java.util.Objects;
/** Utility for iterating over {@link Labels}. */
+@StableApi
public final class Label implements Comparable