From e2ebb56911647415f140b208520619ec3a524cf3 Mon Sep 17 00:00:00 2001 From: Peter Paul Bakker Date: Mon, 7 Mar 2022 10:55:44 +0100 Subject: [PATCH 1/2] Tweak performance for Prometheus scraping endpoint Reduce the number of times capacity growth is needed inside the StringWriter. A typical default SpringBoot Prometheus page has more than 11k characters. Best performance results when no capacity growth is needed at all, so base it on previous metrics page size plus some room for possible extra metric info. See gh-30085 --- .../export/prometheus/PrometheusScrapeEndpoint.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) 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 eb179c543842..46974bab0cf6 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 @@ -42,8 +42,12 @@ @WebEndpoint(id = "prometheus") public class PrometheusScrapeEndpoint { + private static final int METRICS_SCRAPE_CHARS_EXTRA = 1024; + private final CollectorRegistry collectorRegistry; + private volatile int nextMetricsScrapeSize = 16; + public PrometheusScrapeEndpoint(CollectorRegistry collectorRegistry) { this.collectorRegistry = collectorRegistry; } @@ -51,12 +55,16 @@ public PrometheusScrapeEndpoint(CollectorRegistry collectorRegistry) { @ReadOperation(producesFrom = TextOutputFormat.class) public WebEndpointResponse scrape(TextOutputFormat format, @Nullable Set includedNames) { try { - Writer writer = new StringWriter(); + Writer writer = new StringWriter(nextMetricsScrapeSize); Enumeration samples = (includedNames != null) ? this.collectorRegistry.filteredMetricFamilySamples(includedNames) : this.collectorRegistry.metricFamilySamples(); format.write(writer, samples); - return new WebEndpointResponse<>(writer.toString(), format); + + String scrapePage = writer.toString(); + nextMetricsScrapeSize = scrapePage.length() + METRICS_SCRAPE_CHARS_EXTRA; + + return new WebEndpointResponse<>(scrapePage, format); } catch (IOException ex) { // This actually never happens since StringWriter doesn't throw an IOException From 93f31ee063b20fe3bd2f8bb214dfca8bf7f2add2 Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Wed, 9 Mar 2022 11:31:23 +0100 Subject: [PATCH 2/2] Polish "Tweak performance for Prometheus scraping endpoint"\n\nSee gh-30085 --- .../metrics/export/prometheus/PrometheusScrapeEndpoint.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 46974bab0cf6..89cc2822d3e0 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 @@ -55,14 +55,14 @@ public PrometheusScrapeEndpoint(CollectorRegistry collectorRegistry) { @ReadOperation(producesFrom = TextOutputFormat.class) public WebEndpointResponse scrape(TextOutputFormat format, @Nullable Set includedNames) { try { - Writer writer = new StringWriter(nextMetricsScrapeSize); + Writer writer = new StringWriter(this.nextMetricsScrapeSize); Enumeration samples = (includedNames != null) ? this.collectorRegistry.filteredMetricFamilySamples(includedNames) : this.collectorRegistry.metricFamilySamples(); format.write(writer, samples); String scrapePage = writer.toString(); - nextMetricsScrapeSize = scrapePage.length() + METRICS_SCRAPE_CHARS_EXTRA; + this.nextMetricsScrapeSize = scrapePage.length() + METRICS_SCRAPE_CHARS_EXTRA; return new WebEndpointResponse<>(scrapePage, format); }