diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusMetricsExportAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusMetricsExportAutoConfiguration.java index 9aba0ae77e6..1e9c04398a5 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusMetricsExportAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusMetricsExportAutoConfiguration.java @@ -82,8 +82,9 @@ public class PrometheusMetricsExportAutoConfiguration { @SuppressWarnings("removal") @Bean @ConditionalOnMissingBean({ PrometheusScrapeEndpoint.class, PrometheusSimpleclientScrapeEndpoint.class }) - PrometheusScrapeEndpoint prometheusEndpoint(PrometheusRegistry prometheusRegistry) { - return new PrometheusScrapeEndpoint(prometheusRegistry); + PrometheusScrapeEndpoint prometheusEndpoint(PrometheusRegistry prometheusRegistry, + PrometheusConfig prometheusConfig) { + return new PrometheusScrapeEndpoint(prometheusRegistry, prometheusConfig.prometheusProperties()); } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusPropertiesConfigAdapter.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusPropertiesConfigAdapter.java index 265e5755cce..1d5b7aa5f02 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusPropertiesConfigAdapter.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusPropertiesConfigAdapter.java @@ -63,13 +63,15 @@ class PrometheusPropertiesConfigAdapter extends PropertiesConfigAdapter map = prometheusProperties.getProperties(); - if (map.isEmpty()) { + Map additionalProperties = prometheusProperties.getProperties(); + if (additionalProperties.isEmpty()) { return null; } Properties properties = PrometheusConfig.super.prometheusProperties(); - properties = (properties != null) ? properties : new Properties(); - properties.putAll(map); + if (properties == null) { + properties = new Properties(); + } + properties.putAll(additionalProperties); return properties; } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/PrometheusScrapeEndpointDocumentationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/PrometheusScrapeEndpointDocumentationTests.java index 429d2e34d4d..032fa92353d 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/PrometheusScrapeEndpointDocumentationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/PrometheusScrapeEndpointDocumentationTests.java @@ -16,6 +16,8 @@ package org.springframework.boot.actuate.autoconfigure.endpoint.web.documentation; +import java.util.Properties; + import io.micrometer.core.instrument.Clock; import io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics; import io.micrometer.prometheusmetrics.PrometheusMeterRegistry; @@ -78,7 +80,7 @@ class PrometheusScrapeEndpointDocumentationTests extends MockMvcEndpointDocument PrometheusMeterRegistry meterRegistry = new PrometheusMeterRegistry((key) -> null, prometheusRegistry, Clock.SYSTEM); new JvmMemoryMetrics().bindTo(meterRegistry); - return new PrometheusScrapeEndpoint(prometheusRegistry); + return new PrometheusScrapeEndpoint(prometheusRegistry, new Properties()); } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/DualPrometheusMetricsExportAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/DualPrometheusMetricsExportAutoConfigurationTests.java index 9b607d834e4..519d0af17ae 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/DualPrometheusMetricsExportAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/DualPrometheusMetricsExportAutoConfigurationTests.java @@ -17,6 +17,7 @@ package org.springframework.boot.actuate.autoconfigure.metrics.export.prometheus; import io.micrometer.core.instrument.Clock; +import io.micrometer.prometheusmetrics.PrometheusConfig; import io.prometheus.client.CollectorRegistry; import io.prometheus.client.exemplars.ExemplarSampler; import io.prometheus.client.exemplars.tracer.common.SpanContextSupplier; @@ -358,8 +359,9 @@ class DualPrometheusMetricsExportAutoConfigurationTests { static class CustomSecondEndpointConfiguration { @Bean - PrometheusScrapeEndpoint prometheusScrapeEndpoint(PrometheusRegistry prometheusRegistry) { - return new PrometheusScrapeEndpoint(prometheusRegistry); + PrometheusScrapeEndpoint prometheusScrapeEndpoint(PrometheusRegistry prometheusRegistry, + PrometheusConfig prometheusConfig) { + return new PrometheusScrapeEndpoint(prometheusRegistry, prometheusConfig.prometheusProperties()); } @Bean diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusMetricsExportAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusMetricsExportAutoConfigurationTests.java index 319ee2393f0..507b38571cc 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusMetricsExportAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusMetricsExportAutoConfigurationTests.java @@ -17,6 +17,7 @@ package org.springframework.boot.actuate.autoconfigure.metrics.export.prometheus; import io.micrometer.core.instrument.Clock; +import io.micrometer.prometheusmetrics.PrometheusConfig; import io.micrometer.prometheusmetrics.PrometheusMeterRegistry; import io.prometheus.metrics.model.registry.PrometheusRegistry; import io.prometheus.metrics.tracer.common.SpanContext; @@ -207,8 +208,9 @@ class PrometheusMetricsExportAutoConfigurationTests { static class CustomEndpointConfiguration { @Bean - PrometheusScrapeEndpoint customEndpoint(PrometheusRegistry prometheusRegistry) { - return new PrometheusScrapeEndpoint(prometheusRegistry); + PrometheusScrapeEndpoint customEndpoint(PrometheusRegistry prometheusRegistry, + PrometheusConfig prometheusConfig) { + return new PrometheusScrapeEndpoint(prometheusRegistry, prometheusConfig.prometheusProperties()); } } diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusOutputFormat.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusOutputFormat.java index 25d18012e78..582a34cf125 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusOutputFormat.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusOutputFormat.java @@ -43,8 +43,9 @@ public enum PrometheusOutputFormat implements Producible CONTENT_TYPE_004(PrometheusTextFormatWriter.CONTENT_TYPE) { @Override - void write(OutputStream outputStream, MetricSnapshots snapshots) throws IOException { - EXPOSITION_FORMATS.getPrometheusTextFormatWriter().write(outputStream, snapshots); + void write(ExpositionFormats expositionFormats, OutputStream outputStream, MetricSnapshots snapshots) + throws IOException { + expositionFormats.getPrometheusTextFormatWriter().write(outputStream, snapshots); } @Override @@ -60,8 +61,9 @@ public enum PrometheusOutputFormat implements Producible CONTENT_TYPE_OPENMETRICS_100(OpenMetricsTextFormatWriter.CONTENT_TYPE) { @Override - void write(OutputStream outputStream, MetricSnapshots snapshots) throws IOException { - EXPOSITION_FORMATS.getOpenMetricsTextFormatWriter().write(outputStream, snapshots); + void write(ExpositionFormats expositionFormats, OutputStream outputStream, MetricSnapshots snapshots) + throws IOException { + expositionFormats.getOpenMetricsTextFormatWriter().write(outputStream, snapshots); } }, @@ -72,14 +74,13 @@ public enum PrometheusOutputFormat implements Producible CONTENT_TYPE_PROTOBUF(PrometheusProtobufWriter.CONTENT_TYPE) { @Override - void write(OutputStream outputStream, MetricSnapshots snapshots) throws IOException { - EXPOSITION_FORMATS.getPrometheusProtobufWriter().write(outputStream, snapshots); + void write(ExpositionFormats expositionFormats, OutputStream outputStream, MetricSnapshots snapshots) + throws IOException { + expositionFormats.getPrometheusProtobufWriter().write(outputStream, snapshots); } }; - private static final ExpositionFormats EXPOSITION_FORMATS = ExpositionFormats.init(); - private final MimeType mimeType; PrometheusOutputFormat(String mimeType) { @@ -91,6 +92,7 @@ public enum PrometheusOutputFormat implements Producible return this.mimeType; } - abstract void write(OutputStream outputStream, MetricSnapshots snapshots) throws IOException; + abstract void write(ExpositionFormats expositionFormats, OutputStream outputStream, MetricSnapshots snapshots) + throws IOException; } diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusScrapeEndpoint.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusScrapeEndpoint.java index 06376ed30b8..e3d1a60c3b7 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusScrapeEndpoint.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusScrapeEndpoint.java @@ -18,8 +18,12 @@ package org.springframework.boot.actuate.metrics.export.prometheus; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.util.Properties; import java.util.Set; +import io.prometheus.metrics.config.PrometheusProperties; +import io.prometheus.metrics.config.PrometheusPropertiesLoader; +import io.prometheus.metrics.expositionformats.ExpositionFormats; import io.prometheus.metrics.model.registry.PrometheusRegistry; import io.prometheus.metrics.model.snapshots.MetricSnapshots; @@ -45,10 +49,32 @@ public class PrometheusScrapeEndpoint { private final PrometheusRegistry prometheusRegistry; + private final ExpositionFormats expositionFormats; + private volatile int nextMetricsScrapeSize = 16; + /** + * Creates a new {@link PrometheusScrapeEndpoint}. + * @param prometheusRegistry the Prometheus registry to use + * @deprecated since 3.3.1 for removal in 3.5.0 in favor of + * {@link #PrometheusScrapeEndpoint(PrometheusRegistry, Properties)} + */ + @Deprecated(since = "3.3.1", forRemoval = true) public PrometheusScrapeEndpoint(PrometheusRegistry prometheusRegistry) { + this(prometheusRegistry, null); + } + + /** + * Creates a new {@link PrometheusScrapeEndpoint}. + * @param prometheusRegistry the Prometheus registry to use + * @param expositionFormatsProperties the properties used to configure Prometheus' + * {@link ExpositionFormats} + */ + public PrometheusScrapeEndpoint(PrometheusRegistry prometheusRegistry, Properties expositionFormatsProperties) { this.prometheusRegistry = prometheusRegistry; + PrometheusProperties prometheusProperties = (expositionFormatsProperties != null) + ? PrometheusPropertiesLoader.load(expositionFormatsProperties) : PrometheusPropertiesLoader.load(); + this.expositionFormats = ExpositionFormats.init(prometheusProperties.getExporterProperties()); } @ReadOperation(producesFrom = PrometheusOutputFormat.class) @@ -57,7 +83,7 @@ public class PrometheusScrapeEndpoint { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(this.nextMetricsScrapeSize); MetricSnapshots metricSnapshots = (includedNames != null) ? this.prometheusRegistry.scrape(includedNames::contains) : this.prometheusRegistry.scrape(); - format.write(outputStream, metricSnapshots); + format.write(this.expositionFormats, outputStream, metricSnapshots); byte[] content = outputStream.toByteArray(); this.nextMetricsScrapeSize = content.length + METRICS_SCRAPE_CHARS_EXTRA; return new WebEndpointResponse<>(content, format); diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusScrapeEndpointIntegrationTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusScrapeEndpointIntegrationTests.java index 6ea796ef3b5..2d041728f53 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusScrapeEndpointIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/prometheus/PrometheusScrapeEndpointIntegrationTests.java @@ -16,6 +16,8 @@ package org.springframework.boot.actuate.metrics.export.prometheus; +import java.util.Properties; + import io.micrometer.core.instrument.Clock; import io.micrometer.core.instrument.Counter; import io.micrometer.core.instrument.MeterRegistry; @@ -141,7 +143,7 @@ class PrometheusScrapeEndpointIntegrationTests { @Bean PrometheusScrapeEndpoint prometheusScrapeEndpoint(PrometheusRegistry prometheusRegistry) { - return new PrometheusScrapeEndpoint(prometheusRegistry); + return new PrometheusScrapeEndpoint(prometheusRegistry, new Properties()); } @Bean diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/prometheus/SecondCustomPrometheusScrapeEndpointIntegrationTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/prometheus/SecondCustomPrometheusScrapeEndpointIntegrationTests.java index b77c73f6e4d..fb781030958 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/prometheus/SecondCustomPrometheusScrapeEndpointIntegrationTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/export/prometheus/SecondCustomPrometheusScrapeEndpointIntegrationTests.java @@ -16,6 +16,8 @@ package org.springframework.boot.actuate.metrics.export.prometheus; +import java.util.Properties; + import io.micrometer.core.instrument.Clock; import io.micrometer.core.instrument.Counter; import io.micrometer.core.instrument.composite.CompositeMeterRegistry; @@ -183,7 +185,7 @@ class SecondCustomPrometheusScrapeEndpointIntegrationTests { @Bean PrometheusScrapeEndpoint prometheusScrapeEndpoint(PrometheusRegistry prometheusRegistry) { - return new PrometheusScrapeEndpoint(prometheusRegistry); + return new PrometheusScrapeEndpoint(prometheusRegistry, new Properties()); } @Bean