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 6b081816d..ba24b0883 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 @@ -10,19 +10,23 @@ public class ExporterProperties { // milliseconds is the default - we only provide a boolean flag to avoid a breaking change private static final String PROMETHEUS_TIMESTAMPS_IN_MS = "prometheusTimestampsInMs"; private static final String EXEMPLARS_ON_ALL_METRIC_TYPES = "exemplarsOnAllMetricTypes"; + private static final String ADD_SUFFIXES_TO_METRIC_NAMES = "addSuffixesToMetricNames"; private static final String PREFIX = "io.prometheus.exporter"; @Nullable private final Boolean includeCreatedTimestamps; @Nullable private final Boolean prometheusTimestampsInMs; @Nullable private final Boolean exemplarsOnAllMetricTypes; + @Nullable private final Boolean addSuffixesToMetricNames; private ExporterProperties( @Nullable Boolean includeCreatedTimestamps, @Nullable Boolean prometheusTimestampsInMs, - @Nullable Boolean exemplarsOnAllMetricTypes) { + @Nullable Boolean exemplarsOnAllMetricTypes, + @Nullable Boolean addSuffixesToMetricNames) { this.includeCreatedTimestamps = includeCreatedTimestamps; this.prometheusTimestampsInMs = prometheusTimestampsInMs; this.exemplarsOnAllMetricTypes = exemplarsOnAllMetricTypes; + this.addSuffixesToMetricNames = addSuffixesToMetricNames; } /** Include the {@code _created} timestamps in text format? Default is {@code false}. */ @@ -43,6 +47,10 @@ public boolean getExemplarsOnAllMetricTypes() { return exemplarsOnAllMetricTypes != null && exemplarsOnAllMetricTypes; } + public boolean isAddSuffixesToMetricNames() { + return addSuffixesToMetricNames == null || addSuffixesToMetricNames; + } + /** * Note that this will remove entries from {@code properties}. This is because we want to know if * there are unused properties remaining after all properties have been loaded. @@ -55,8 +63,13 @@ static ExporterProperties load(Map properties) Util.loadBoolean(PREFIX + "." + PROMETHEUS_TIMESTAMPS_IN_MS, properties); Boolean exemplarsOnAllMetricTypes = Util.loadBoolean(PREFIX + "." + EXEMPLARS_ON_ALL_METRIC_TYPES, properties); + Boolean addSuffixesToMetricNames = + Util.loadBoolean(PREFIX + "." + ADD_SUFFIXES_TO_METRIC_NAMES, properties); return new ExporterProperties( - includeCreatedTimestamps, timestampsInMs, exemplarsOnAllMetricTypes); + includeCreatedTimestamps, + timestampsInMs, + exemplarsOnAllMetricTypes, + addSuffixesToMetricNames); } public static Builder builder() { @@ -68,6 +81,7 @@ public static class Builder { @Nullable private Boolean includeCreatedTimestamps; @Nullable private Boolean exemplarsOnAllMetricTypes; boolean prometheusTimestampsInMs; + @Nullable private Boolean addSuffixesToMetricNames; private Builder() {} @@ -89,9 +103,18 @@ public Builder prometheusTimestampsInMs(boolean prometheusTimestampsInMs) { return this; } + /** See {@link #isAddSuffixesToMetricNames()}. */ + public Builder addSuffixesToMetricNames(boolean addSuffixesToMetricNames) { + this.addSuffixesToMetricNames = addSuffixesToMetricNames; + return this; + } + public ExporterProperties build() { return new ExporterProperties( - includeCreatedTimestamps, prometheusTimestampsInMs, exemplarsOnAllMetricTypes); + includeCreatedTimestamps, + prometheusTimestampsInMs, + exemplarsOnAllMetricTypes, + addSuffixesToMetricNames); } } } diff --git a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/HistogramTest.java b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/HistogramTest.java index 19e4cdc79..9fc3ad3c3 100644 --- a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/HistogramTest.java +++ b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/HistogramTest.java @@ -949,7 +949,7 @@ public void testDefaults() throws IOException { // text ByteArrayOutputStream out = new ByteArrayOutputStream(); - OpenMetricsTextFormatWriter writer = new OpenMetricsTextFormatWriter(false, true); + OpenMetricsTextFormatWriter writer = OpenMetricsTextFormatWriter.create(); writer.write(out, MetricSnapshots.of(snapshot), EscapingScheme.ALLOW_UTF8); assertThat(out).hasToString(expectedTextFormat); } diff --git a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/InfoTest.java b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/InfoTest.java index fccc5d8d7..9500c25ad 100644 --- a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/InfoTest.java +++ b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/InfoTest.java @@ -120,11 +120,15 @@ public void testConstLabelsDuplicate2() { } private void assertTextFormat(String expected, Info info) throws IOException { - OpenMetricsTextFormatWriter writer = new OpenMetricsTextFormatWriter(true, true); + OpenMetricsTextFormatWriter writer = + OpenMetricsTextFormatWriter.builder() + .setCreatedTimestampsEnabled(true) + .setExemplarsOnAllMetricTypesEnabled(true) + .build(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); writer.write( outputStream, MetricSnapshots.of(info.collect()), EscapingScheme.UNDERSCORE_ESCAPING); - String result = outputStream.toString(StandardCharsets.UTF_8.name()); + String result = outputStream.toString(StandardCharsets.UTF_8); if (!result.contains(expected)) { throw new AssertionError(expected + " is not contained in the following output:\n" + result); } 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 0ffa23a58..98f3c1427 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 @@ -30,10 +30,12 @@ public static ExpositionFormats init(ExporterProperties properties) { PrometheusTextFormatWriter.builder() .setIncludeCreatedTimestamps(properties.getIncludeCreatedTimestamps()) .setTimestampsInMs(properties.getPrometheusTimestampsInMs()) + .setAddSuffixesToMetricNames(properties.isAddSuffixesToMetricNames()) .build(), OpenMetricsTextFormatWriter.builder() .setCreatedTimestampsEnabled(properties.getIncludeCreatedTimestamps()) .setExemplarsOnAllMetricTypesEnabled(properties.getExemplarsOnAllMetricTypes()) + .setAddSuffixesToMetricNames(properties.isAddSuffixesToMetricNames()) .build()); } 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 1ba1c627d..aafc50eab 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 @@ -47,6 +47,7 @@ public class OpenMetricsTextFormatWriter implements ExpositionFormatWriter { public static class Builder { boolean createdTimestampsEnabled; boolean exemplarsOnAllMetricTypesEnabled; + boolean addSuffixesToMetricNames = true; private Builder() {} @@ -67,9 +68,19 @@ public Builder setExemplarsOnAllMetricTypesEnabled(boolean exemplarsOnAllMetricT return this; } + /** + * @param addSuffixesToMetricNames whether to add the conventional suffixes to metric names, + * like _total for counters, _bucket for histogram buckets, _count and _sum for histograms + * and summaries, _info for info metrics. This is enabled by default. + */ + public Builder setAddSuffixesToMetricNames(boolean addSuffixesToMetricNames) { + this.addSuffixesToMetricNames = addSuffixesToMetricNames; + return this; + } + public OpenMetricsTextFormatWriter build() { return new OpenMetricsTextFormatWriter( - createdTimestampsEnabled, exemplarsOnAllMetricTypesEnabled); + createdTimestampsEnabled, exemplarsOnAllMetricTypesEnabled, addSuffixesToMetricNames); } } @@ -77,15 +88,27 @@ public OpenMetricsTextFormatWriter build() { "application/openmetrics-text; version=1.0.0; charset=utf-8"; private final boolean createdTimestampsEnabled; private final boolean exemplarsOnAllMetricTypesEnabled; + private final boolean addSuffixesToMetricNames; /** * @param createdTimestampsEnabled whether to include the _created timestamp in the output - This * will produce an invalid OpenMetrics output, but is kept for backwards compatibility. + * @deprecated this constructor is deprecated and will be removed in the next major version - use + * {@link #builder()} or {@link #create()} instead */ + @Deprecated public OpenMetricsTextFormatWriter( boolean createdTimestampsEnabled, boolean exemplarsOnAllMetricTypesEnabled) { + this(createdTimestampsEnabled, exemplarsOnAllMetricTypesEnabled, true); + } + + private OpenMetricsTextFormatWriter( + boolean createdTimestampsEnabled, + boolean exemplarsOnAllMetricTypesEnabled, + boolean addSuffixesToMetricNames) { this.createdTimestampsEnabled = createdTimestampsEnabled; this.exemplarsOnAllMetricTypesEnabled = exemplarsOnAllMetricTypesEnabled; + this.addSuffixesToMetricNames = addSuffixesToMetricNames; } public static Builder builder() { @@ -400,7 +423,8 @@ private void writeNameAndLabels( metricInsideBraces = true; writer.write('{'); } - writeName(writer, name + (suffix != null ? suffix : ""), NameType.Metric); + writeName( + writer, name + (suffix != null && addSuffixesToMetricNames ? suffix : ""), NameType.Metric); if (!labels.isEmpty() || additionalLabelName != null) { writeLabels( writer, 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 5dc3f629b..24a185743 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 @@ -44,10 +44,12 @@ public class PrometheusTextFormatWriter implements ExpositionFormatWriter { private final boolean writeCreatedTimestamps; private final boolean timestampsInMs; + private final boolean addSuffixesToMetricNames; public static class Builder { boolean includeCreatedTimestamps; boolean timestampsInMs = true; + private boolean addSuffixesToMetricNames = true; private Builder() {} @@ -65,8 +67,19 @@ public Builder setTimestampsInMs(boolean timestampsInMs) { return this; } + /** + * @param addSuffixesToMetricNames whether to add the conventional suffixes to metric names, + * like _total for counters, _bucket for histogram buckets, _count and _sum for histograms + * and summaries, _info for info metrics. This is enabled by default. + */ + public Builder setAddSuffixesToMetricNames(boolean addSuffixesToMetricNames) { + this.addSuffixesToMetricNames = addSuffixesToMetricNames; + return this; + } + public PrometheusTextFormatWriter build() { - return new PrometheusTextFormatWriter(includeCreatedTimestamps, timestampsInMs); + return new PrometheusTextFormatWriter( + includeCreatedTimestamps, timestampsInMs, addSuffixesToMetricNames); } } @@ -78,12 +91,14 @@ public PrometheusTextFormatWriter build() { */ @Deprecated public PrometheusTextFormatWriter(boolean writeCreatedTimestamps) { - this(writeCreatedTimestamps, false); + this(writeCreatedTimestamps, false, true); } - private PrometheusTextFormatWriter(boolean writeCreatedTimestamps, boolean timestampsInMs) { + private PrometheusTextFormatWriter( + boolean writeCreatedTimestamps, boolean timestampsInMs, boolean addSuffixesToMetricNames) { this.writeCreatedTimestamps = writeCreatedTimestamps; this.timestampsInMs = timestampsInMs; + this.addSuffixesToMetricNames = addSuffixesToMetricNames; } public static PrometheusTextFormatWriter.Builder builder() { @@ -400,7 +415,8 @@ private void writeNameAndLabels( metricInsideBraces = true; writer.write('{'); } - writeName(writer, name + (suffix != null ? suffix : ""), NameType.Metric); + writeName( + writer, name + (suffix != null && addSuffixesToMetricNames ? suffix : ""), NameType.Metric); if (!labels.isEmpty() || additionalLabelName != null) { writeLabels( writer, labels, additionalLabelName, additionalLabelValue, metricInsideBraces, scheme); diff --git a/prometheus-metrics-instrumentation-caffeine/src/test/java/io/prometheus/metrics/instrumentation/caffeine/CacheMetricsCollectorTest.java b/prometheus-metrics-instrumentation-caffeine/src/test/java/io/prometheus/metrics/instrumentation/caffeine/CacheMetricsCollectorTest.java index 245a071e9..b9c59da07 100644 --- a/prometheus-metrics-instrumentation-caffeine/src/test/java/io/prometheus/metrics/instrumentation/caffeine/CacheMetricsCollectorTest.java +++ b/prometheus-metrics-instrumentation-caffeine/src/test/java/io/prometheus/metrics/instrumentation/caffeine/CacheMetricsCollectorTest.java @@ -12,7 +12,12 @@ import io.prometheus.metrics.config.EscapingScheme; import io.prometheus.metrics.expositionformats.OpenMetricsTextFormatWriter; import io.prometheus.metrics.model.registry.PrometheusRegistry; -import io.prometheus.metrics.model.snapshots.*; +import io.prometheus.metrics.model.snapshots.CounterSnapshot; +import io.prometheus.metrics.model.snapshots.DataPointSnapshot; +import io.prometheus.metrics.model.snapshots.GaugeSnapshot; +import io.prometheus.metrics.model.snapshots.Labels; +import io.prometheus.metrics.model.snapshots.MetricSnapshots; +import io.prometheus.metrics.model.snapshots.SummarySnapshot; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.UncheckedIOException; @@ -310,10 +315,14 @@ private DataPointSnapshot getDataPointSnapshot( private String convertToOpenMetricsFormat(PrometheusRegistry registry) { final ByteArrayOutputStream out = new ByteArrayOutputStream(); - final OpenMetricsTextFormatWriter writer = new OpenMetricsTextFormatWriter(true, true); + final OpenMetricsTextFormatWriter writer = + OpenMetricsTextFormatWriter.builder() + .setCreatedTimestampsEnabled(true) + .setExemplarsOnAllMetricTypesEnabled(true) + .build(); try { writer.write(out, registry.scrape(), EscapingScheme.ALLOW_UTF8); - return out.toString(StandardCharsets.UTF_8.name()); + return out.toString(StandardCharsets.UTF_8); } catch (IOException e) { throw new UncheckedIOException(e); } diff --git a/prometheus-metrics-instrumentation-dropwizard/src/test/java/io/prometheus/metrics/instrumentation/dropwizard/DropwizardExportsTest.java b/prometheus-metrics-instrumentation-dropwizard/src/test/java/io/prometheus/metrics/instrumentation/dropwizard/DropwizardExportsTest.java index 9d21c7381..f8208efc8 100644 --- a/prometheus-metrics-instrumentation-dropwizard/src/test/java/io/prometheus/metrics/instrumentation/dropwizard/DropwizardExportsTest.java +++ b/prometheus-metrics-instrumentation-dropwizard/src/test/java/io/prometheus/metrics/instrumentation/dropwizard/DropwizardExportsTest.java @@ -339,7 +339,11 @@ public Double getValue() { private String convertToOpenMetricsFormat(PrometheusRegistry _registry) { ByteArrayOutputStream out = new ByteArrayOutputStream(); - OpenMetricsTextFormatWriter writer = new OpenMetricsTextFormatWriter(true, true); + OpenMetricsTextFormatWriter writer = + OpenMetricsTextFormatWriter.builder() + .setCreatedTimestampsEnabled(true) + .setExemplarsOnAllMetricTypesEnabled(true) + .build(); try { writer.write(out, _registry.scrape(), EscapingScheme.UNDERSCORE_ESCAPING); return out.toString(StandardCharsets.UTF_8); diff --git a/prometheus-metrics-instrumentation-dropwizard5/src/test/java/io/prometheus/metrics/instrumentation/dropwizard5/DropwizardExportsTest.java b/prometheus-metrics-instrumentation-dropwizard5/src/test/java/io/prometheus/metrics/instrumentation/dropwizard5/DropwizardExportsTest.java index c3a5fa4d5..f21f8a317 100644 --- a/prometheus-metrics-instrumentation-dropwizard5/src/test/java/io/prometheus/metrics/instrumentation/dropwizard5/DropwizardExportsTest.java +++ b/prometheus-metrics-instrumentation-dropwizard5/src/test/java/io/prometheus/metrics/instrumentation/dropwizard5/DropwizardExportsTest.java @@ -348,7 +348,11 @@ public Double getValue() { private String convertToOpenMetricsFormat(PrometheusRegistry _registry) { ByteArrayOutputStream out = new ByteArrayOutputStream(); - OpenMetricsTextFormatWriter writer = new OpenMetricsTextFormatWriter(true, true); + OpenMetricsTextFormatWriter writer = + OpenMetricsTextFormatWriter.builder() + .setCreatedTimestampsEnabled(true) + .setExemplarsOnAllMetricTypesEnabled(true) + .build(); try { writer.write(out, _registry.scrape(), EscapingScheme.UNDERSCORE_ESCAPING); return out.toString(StandardCharsets.UTF_8); diff --git a/prometheus-metrics-instrumentation-dropwizard5/src/test/java/io/prometheus/metrics/instrumentation/dropwizard5/labels/CustomLabelMapperTest.java b/prometheus-metrics-instrumentation-dropwizard5/src/test/java/io/prometheus/metrics/instrumentation/dropwizard5/labels/CustomLabelMapperTest.java index 183b50b24..a89edd077 100644 --- a/prometheus-metrics-instrumentation-dropwizard5/src/test/java/io/prometheus/metrics/instrumentation/dropwizard5/labels/CustomLabelMapperTest.java +++ b/prometheus-metrics-instrumentation-dropwizard5/src/test/java/io/prometheus/metrics/instrumentation/dropwizard5/labels/CustomLabelMapperTest.java @@ -217,7 +217,11 @@ public void test_WHEN_AdditionalLabels_THEN_ShouldReturnCorrectSample() { private String convertToOpenMetricsFormat(MetricSnapshots snapshots) { ByteArrayOutputStream out = new ByteArrayOutputStream(); - OpenMetricsTextFormatWriter writer = new OpenMetricsTextFormatWriter(true, true); + OpenMetricsTextFormatWriter writer = + OpenMetricsTextFormatWriter.builder() + .setCreatedTimestampsEnabled(true) + .setExemplarsOnAllMetricTypesEnabled(true) + .build(); try { writer.write(out, snapshots, EscapingScheme.UNDERSCORE_ESCAPING); return out.toString(StandardCharsets.UTF_8); diff --git a/prometheus-metrics-instrumentation-guava/src/test/java/io/prometheus/metrics/instrumentation/guava/CacheMetricsCollectorTest.java b/prometheus-metrics-instrumentation-guava/src/test/java/io/prometheus/metrics/instrumentation/guava/CacheMetricsCollectorTest.java index 31da91f20..62fdaa08a 100644 --- a/prometheus-metrics-instrumentation-guava/src/test/java/io/prometheus/metrics/instrumentation/guava/CacheMetricsCollectorTest.java +++ b/prometheus-metrics-instrumentation-guava/src/test/java/io/prometheus/metrics/instrumentation/guava/CacheMetricsCollectorTest.java @@ -160,7 +160,11 @@ private DataPointSnapshot getDataPointSnapshot( private String convertToOpenMetricsFormat(PrometheusRegistry registry) { final ByteArrayOutputStream out = new ByteArrayOutputStream(); - final OpenMetricsTextFormatWriter writer = new OpenMetricsTextFormatWriter(true, true); + final OpenMetricsTextFormatWriter writer = + OpenMetricsTextFormatWriter.builder() + .setCreatedTimestampsEnabled(true) + .setExemplarsOnAllMetricTypesEnabled(true) + .build(); try { writer.write(out, registry.scrape(), EscapingScheme.ALLOW_UTF8); return out.toString(StandardCharsets.UTF_8); diff --git a/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/TestUtil.java b/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/TestUtil.java index 64e15590c..bc2480d05 100644 --- a/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/TestUtil.java +++ b/prometheus-metrics-instrumentation-jvm/src/test/java/io/prometheus/metrics/instrumentation/jvm/TestUtil.java @@ -11,7 +11,11 @@ class TestUtil { static String convertToOpenMetricsFormat(MetricSnapshots snapshots) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); - OpenMetricsTextFormatWriter writer = new OpenMetricsTextFormatWriter(true, true); + OpenMetricsTextFormatWriter writer = + OpenMetricsTextFormatWriter.builder() + .setCreatedTimestampsEnabled(true) + .setExemplarsOnAllMetricTypesEnabled(true) + .build(); writer.write(out, snapshots, EscapingScheme.ALLOW_UTF8); return out.toString(StandardCharsets.UTF_8); } diff --git a/prometheus-metrics-simpleclient-bridge/src/test/java/io/prometheus/metrics/simpleclient/bridge/SimpleclientCollectorTest.java b/prometheus-metrics-simpleclient-bridge/src/test/java/io/prometheus/metrics/simpleclient/bridge/SimpleclientCollectorTest.java index a17ed8bc4..1945fdf83 100644 --- a/prometheus-metrics-simpleclient-bridge/src/test/java/io/prometheus/metrics/simpleclient/bridge/SimpleclientCollectorTest.java +++ b/prometheus-metrics-simpleclient-bridge/src/test/java/io/prometheus/metrics/simpleclient/bridge/SimpleclientCollectorTest.java @@ -266,7 +266,8 @@ private String origOpenMetrics() throws IOException { private String newOpenMetrics() throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); - OpenMetricsTextFormatWriter writer = new OpenMetricsTextFormatWriter(true, false); + OpenMetricsTextFormatWriter writer = + OpenMetricsTextFormatWriter.builder().setCreatedTimestampsEnabled(true).build(); writer.write(out, newRegistry.scrape(), EscapingScheme.ALLOW_UTF8); return out.toString(StandardCharsets.UTF_8); }