Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ public class PrometheusNaming {
* format, this will be represented as two values: {@code processing_time_seconds_total} for the
* counter value, and the optional {@code processing_time_seconds_created} timestamp.
*
* <p>Use {@link #sanitizeMetricName(String)} to convert arbitrary Strings to valid metric names.
* <p>Use {@link #sanitizeMetricName(String)} for compatibility-preserving sanitization that
* strips reserved suffixes, or {@link #normalizeMetricName(String)} for permissive normalization
* that keeps the original suffixes intact.
*/
public static boolean isValidMetricName(String name) {
return validateMetricName(name) == null;
Expand Down Expand Up @@ -178,6 +180,9 @@ public static String prometheusName(String name) {
* bridge) which relied on {@code sanitizeMetricName} to strip these suffixes before passing names
* to the snapshot builders.
*
* <p>If you want permissive normalization that keeps reserved suffixes intact, use {@link
* #normalizeMetricName(String)} instead.
*
* @throws IllegalArgumentException if the input is empty
*/
public static String sanitizeMetricName(String metricName) {
Expand Down Expand Up @@ -221,6 +226,37 @@ public static String sanitizeMetricName(String metricName, Unit unit) {
return result;
}

/**
* Convert an arbitrary string to a valid metric name without stripping reserved suffixes.
*
* <p>Any non-empty valid UTF-8 string is accepted and returned unchanged. This is the permissive
* normalization behavior introduced in 1.6.0. Use this method for new integrations that want to
* preserve the original metric name and rely on registration-time collision detection instead of
* suffix stripping.
*
* @throws IllegalArgumentException if the input is empty
*/
public static String normalizeMetricName(String metricName) {
if (metricName.isEmpty()) {
throw new IllegalArgumentException("Cannot convert an empty string to a valid metric name.");
}
return metricName;
}

/**
* Like {@link #normalizeMetricName(String)}, but also makes sure that the unit is appended as a
* suffix if the unit is not {@code null}.
*/
public static String normalizeMetricName(String metricName, Unit unit) {
String result = normalizeMetricName(metricName);
if (unit != null) {
if (!result.endsWith("_" + unit) && !result.endsWith("." + unit)) {
result += "_" + unit;
}
}
return result;
}

/**
* Convert an arbitrary string to a name where {@link #isValidLabelName(String)
* isValidLabelName(name)} is true.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static io.prometheus.metrics.model.snapshots.PrometheusNaming.escapeName;
import static io.prometheus.metrics.model.snapshots.PrometheusNaming.isValidLabelName;
import static io.prometheus.metrics.model.snapshots.PrometheusNaming.normalizeMetricName;
import static io.prometheus.metrics.model.snapshots.PrometheusNaming.prometheusName;
import static io.prometheus.metrics.model.snapshots.PrometheusNaming.sanitizeLabelName;
import static io.prometheus.metrics.model.snapshots.PrometheusNaming.sanitizeMetricName;
Expand Down Expand Up @@ -72,6 +73,29 @@ void testSanitizeMetricNameWithUnit() {
assertThat(sanitizeMetricName("total", Unit.RATIO)).isEqualTo("total_" + Unit.RATIO);
}

@Test
void testNormalizeMetricName() {
assertThat(normalizeMetricName("my_counter_total")).isEqualTo("my_counter_total");
assertThat(normalizeMetricName("jvm.info")).isEqualTo("jvm.info");
assertThat(normalizeMetricName("jvm_info")).isEqualTo("jvm_info");
assertThat(normalizeMetricName("a.b")).isEqualTo("a.b");
assertThat(normalizeMetricName("_total")).isEqualTo("_total");
assertThat(normalizeMetricName(".total")).isEqualTo(".total");
assertThat(normalizeMetricName("my_events_created")).isEqualTo("my_events_created");
assertThat(normalizeMetricName("my_histogram_bucket")).isEqualTo("my_histogram_bucket");
}

@Test
void testNormalizeMetricNameWithUnit() {
assertThat(prometheusName(normalizeMetricName("def", Unit.RATIO)))
.isEqualTo("def_" + Unit.RATIO);
assertThat(prometheusName(normalizeMetricName("my_counter_total", Unit.RATIO)))
.isEqualTo("my_counter_total_" + Unit.RATIO);
assertThat(normalizeMetricName("jvm.info", Unit.RATIO)).isEqualTo("jvm.info_" + Unit.RATIO);
assertThat(normalizeMetricName("_total", Unit.RATIO)).isEqualTo("_total_" + Unit.RATIO);
assertThat(normalizeMetricName("total", Unit.RATIO)).isEqualTo("total_" + Unit.RATIO);
}

@Test
void testSanitizeLabelName() {
assertThat(prometheusName(sanitizeLabelName("0abc.def"))).isEqualTo("_abc_def");
Expand Down